You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中点击搜索栏下拉选项填充表单的问题求助

问题描述

在Laravel 9(PHP 7.4+)项目中,基于Typeahead JS实现了MySQL数据库数据的搜索下拉功能,期望点击下拉结果时自动填充下方关联表单字段。目前搜索下拉可正常显示结果,但点击后无法填充表单,尝试过AJAX和Vue Axios方案均未解决。


相关代码

视图代码片段

<form method="POST" action="{{ route('incident.store') }}">
    @csrf

    {{--* Injured Person --}}
    <div class="card">
        <div class="card-header">
            <i class="fa fa-align-justify"></i> {{ __('Injured Person') }}
        </div>
        <div class="card-body" id="app">
            <div class="form-group row">
                <label>Search CNIC</label>
                <div class="input-group">
                    <input class="form-control" type="text" placeholder="{{ __('Search   CNIC') }}"
                        name="ip_search_cnic" v-model='message' id="ip_cnic">
                    <div class=" input-group-append">
                        <button class="btn btn-primary" type="button" id="search_button"
                            v-on:click=" searchInjuredPerson ">Search</button>
                    </div>
                </div>
                <div class="form-group row">
                    <label>Name</label>
                    <input class="form-control" type="text" placeholder="{{ __('Name') }}"
                        name="ip_name" id="ip_name" v-model="injuredPerson.name" required autofocus>
                </div>

                <div class="form-group row">
                    <label>CNIC</label>
                    <input class="form-control" type="text" placeholder="{{ __('CNIC') }}"
                        name="ip_cnic" id="ip_cnic" v-model="injuredPerson.cnic" required autofocus>
                </div>

                <div class="form-group row">
                    <label>Address</label>
                    <textarea class="form-control" name="ip_address" rows="9" id="ip_address"
                        placeholder="{{ __('Address') }}" v-model="injuredPerson.address"
                        required></textarea>
                </div>

                <div class="form-group row">
                    <label>Phone Number</label>
                    <input class="form-control" type="tel" placeholder="{{ __('Phone Number') }}"
                        name="ip_phone_number" id="ip_phone_number" v-model="injuredPerson.phoneNumber"
                        required autofocus>
                </div>

                <div class="form-group row">
                    <label>Date of Birth</label>
                    <input class="form-control" type="date" placeholder="{{ __('Date of Birth') }}"
                        name="ip_date_of_birth" id="ip_date_of_birth"
                        v-model="injuredPerson.dateOfBirth" required autofocus>
                </div>

                <div class="form-group row">
                    <label>Age</label>
                    <input class="form-control" type="number" name="ip_age" id="ip_age"
                        placeholder="{{ __('Age') }}" v-model="injuredPerson.age" required autofocus>
                </div>

            </div>
        </div>
      </form>

AJAX脚本

@section('javascript')
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    $(document).ready(function() {
// Handle search input keyup event
$('#searchInput').keyup(function() {
var searchCnic = $(this).val();

// Make an AJAX request to fetch matching injured persons
$.ajax({
url: '/incident/search',
type: 'POST',
data: { ip_cnic: searchCnic },
success: function(response) {
// Process the response and populate the dropdown list
var dropdownList = $('#searchResults');
dropdownList.empty();

$.each(response, function(index, injuredPerson) {
dropdownList.append($('
<option />', {
value: injuredPerson.id,
text: injuredPerson.cnic
}));
});
}
});
});

// Handle dropdown selection change event
$('#searchResults').change(function() {
var selectedInjuredPersonId = $(this).val();

// Fetch the injured person details using AJAX
$.ajax({
url: '/incident/' + selectedInjuredPersonId,
type: 'GET',
success: function(response) {
// Populate the form fields with the retrieved data
$('#ip_name').val(response.name);
$('#ip_cnic').val(response.cnic);
$('#ip_address').val(response.address);
$('#ip_phone_number').val(response.phone_number);
$('#ip_date_of_birth').val(response.date_of_birth);
$('#ip_age').val(response.age);
}
});
});
});
</script>
@endsection

路由配置(web.php)

//Showing dropdown for of fetched data by typehead
Route::get('/home', [TypeaheadController::class, 'index']);
Route::get('/autocomplete-search', [TypeaheadController::class, 'autocompleteSearch']);

// For filling the form fields
Route::post('incident/search', 'IncidentController@search')->name('incident.search');
Route::get('incident/{injured_person}', 'IncidentController@showPerson')->name('incident.show');

控制器代码

public function search(Request $request)
{
    $cnic = $request->input('ip_cnic');

    // Perform the search query
    $results = InjuredPerson::where('ip_cnic', 'LIKE', '%' . $cnic . '%')->get();

    return response()->json($results);
}

public function showPerson(InjuredPerson $injured_person)
{
    return response()->json($injured_person);
}

问题现象

搜索下拉可正常显示匹配结果,但点击选项后表单字段无任何填充动作,无法实现自动拉取数据并填充表单的需求。


解决方案

核心问题排查

  1. DOM元素ID不匹配:脚本监听的#searchInput、操作的#searchResults在视图中不存在;视图中存在两个id="ip_cnic"的元素,导致选择器失效。
  2. Vue与jQuery混用冲突:表单用Vue的v-model绑定,但脚本用jQuery的val()赋值,Vue无法感知DOM手动修改,数据不同步。
  3. Typeahead事件未正确监听:未使用Typeahead原生的typeahead:selected事件处理选项点击,而是错误监听普通select的change事件。

修复后代码示例

视图(修正ID冲突,添加Typeahead容器)

<form method="POST" action="{{ route('incident.store') }}">
    @csrf

    {{--* Injured Person --}}
    <div class="card">
        <div class="card-header">
            <i class="fa fa-align-justify"></i> {{ __('Injured Person') }}
        </div>
        <div class="card-body" id="app">
            <div class="form-group row">
                <label>Search CNIC</label>
                <div class="input-group">
                    <!-- 修正搜索框ID为唯一值 -->
                    <input class="form-control" type="text" placeholder="{{ __('Search CNIC') }}"
                        name="ip_search_cnic" v-model='searchCnic' id="ip_search_cnic">
                    <div class="input-group-append">
                        <button class="btn btn-primary" type="button" v-on:click="searchInjuredPerson">Search</button>
                    </div>
                </div>
                <!-- Typeahead下拉结果容器 -->
                <div id="typeahead-results" class="mt-2"></div>

                <div class="form-group row">
                    <label>Name</label>
                    <input class="form-control" type="text" placeholder="{{ __('Name') }}"
                        name="ip_name" id="ip_name" v-model="injuredPerson.name" required autofocus>
                </div>

                <div class="form-group row">
                    <label>CNIC</label>
                    <!-- 修正CNIC输入框ID为唯一值 -->
                    <input class="form-control" type="text" placeholder="{{ __('CNIC') }}"
                        name="ip_cnic" id="ip_cnic_input" v-model="injuredPerson.cnic" required autofocus>
                </div>

                <div class="form-group row">
                    <label>Address</label>
                    <textarea class="form-control" name="ip_address" rows="9" id="ip_address"
                        placeholder="{{ __('Address') }}" v-model="injuredPerson.address"
                        required></textarea>
                </div>

                <div class="form-group row">
                    <label>Phone Number</label>
                    <input class="form-control" type="tel" placeholder="{{ __('Phone Number') }}"
                        name="ip_phone_number" id="ip_phone_number" v-model="injuredPerson.phoneNumber"
                        required autofocus>
                </div>

                <div class="form-group row">
                    <label>Date of Birth</label>
                    <input class="form-control" type="date" placeholder="{{ __('Date of Birth') }}"
                        name="ip_date_of_birth" id="ip_date_of_birth"
                        v-model="injuredPerson.dateOfBirth" required autofocus>
                </div>

                <div class="form-group row">
                    <label>Age</label>
                    <input class="form-control" type="number" name="ip_age" id="ip_age"
                        placeholder="{{ __('Age') }}" v-model="injuredPerson.age" required autofocus>
                </div>

            </div>
        </div>
      </form>

Vue+Typeahead脚本(统一数据处理逻辑)

@section('javascript')
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
<script>
new Vue({
    el: '#app',
    data: {
        searchCnic: '',
        injuredPerson: {
            name: '',
            cnic: '',
            address: '',
            phoneNumber: '',
            dateOfBirth: '',
            age: ''
        }
    },
    mounted() {
        // 初始化Typeahead
        $('#ip_search_cnic').typeahead({
            hint: true,
            highlight: true,
            minLength: 1
        }, {
            name: 'cnics',
            source: (query, syncResults, asyncResults) => {
                // 异步请求搜索结果,携带CSRF令牌
                axios.post('{{ route('incident.search') }}', {
                    ip_cnic: query,
                    _token: '{{ csrf_token() }}'
                }).then(response => {
                    asyncResults(response.data);
                });
            },
            display: 'ip_cnic' // 指定显示的字段名
        }).on('typeahead:selected', (event, selectedItem) => {
            // 选中选项后拉取详情并填充Vue数据
            axios.get('{{ route('incident.show', '') }}/' + selectedItem.id)
                .then(response => {
                    this.injuredPerson = {
                        name: response.data.name,
                        cnic: response.data.ip_cnic,
                        address: response.data.address,
                        phoneNumber: response.data.phone_number,
                        dateOfBirth: response.data.date_of_birth,
                        age: response.data.age
                    };
                });
        });
    },
    methods: {
        searchInjuredPerson() {
            // 手动触发搜索下拉
            $('#ip_search_cnic').typeahead('open');
        }
    }
});
</script>
@endsection

控制器(优化返回字段)

public function search(Request $request)
{
    $cnic = $request->input('ip_cnic');
    // 仅返回Typeahead需要的字段
    $results = InjuredPerson::select('id', 'ip_cnic')
        ->where('ip_cnic', 'LIKE', '%' . $cnic . '%')
        ->get();
    return response()->json($results);
}

public function showPerson(InjuredPerson $injured_person)
{
    // 返回表单需要的字段,与Vue数据对应
    return response()->json([
        'name' => $injured_person->name,
        'ip_cnic' => $injured_person->ip_cnic,
        'address' => $injured_person->address,
        'phone_number' => $injured_person->phone_number,
        'date_of_birth' => $injured_person->date_of_birth,
        'age' => $injured_person->age
    ]);
}

路由(Laravel 9规范写法)

use App\Http\Controllers\TypeaheadController;
use App\Http\Controllers\IncidentController;

//Showing dropdown for of fetched data by typehead
Route::get('/home', [TypeaheadController::class, 'index']);
Route::get('/autocomplete-search', [TypeaheadController::class, 'autocompleteSearch']);

// For filling the form fields
Route::post('incident/search', [IncidentController::class, 'search'])->name('incident.search');
Route::get('incident/{injured_person}', [IncidentController::class, 'showPerson'])->name('incident.show');

关键注意事项

  • 确保引入Typeahead官方库(typeahead.bundle.min.js);
  • Laravel POST请求必须携带CSRF令牌,否则会被框架拦截;
  • Vue数据字段需与控制器返回的JSON字段严格对应;
  • 页面中所有DOM元素ID必须唯一,避免选择器冲突。

内容的提问来源于stack exchange,提问作者Ali Hassan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 05:02:35