我正在使用 Laravel Livewire 3 和相关选择选项,例如国家、州、城市,使用 Select 2 并在选择选项上进行搜索,选择国家/地区后 select2 搜索消失。
当我选择国家/地区时,国家/地区搜索中的 select2 会消失,同一城市、州/省也会消失。
<div>
<div class="col-12 col-md-6">
<div class="ps-checkout__group">
<label class="ps-checkout__label">Country *</label>
<select wire:model.live="bSelectedCountry" name="bCountry" class="form-control input-dropdown bCountry">
<option value="">Select a country</option>
@foreach(App\Models\SysCountry::where('status', 1)->get() as $item)
<option value="{{$item->id}}" >{{$item->name}}</option>
@endforeach
</select>
</div>
</div>
<div class="col-12 col-md-6">
<div class="ps-checkout__group">
<label class="ps-checkout__label">State *</label>
<select wire:model.live="billingStateId" class="form-control input-dropdown bState" >
<option value="">Select a State</option>
@foreach($billingStateList as $item)
<option value="{{$item->id}}" >{{$item->name}}</option>
@endforeach
</select>
</div>
</div>
@push('scripts')
<script>
$(document).ready(function() {
$('.bCountry').select2();
$('.bCountry').on('change', function() {
let data = $(this).val();
@this.set('bSelectedCountry', data);
});
//## State
$('.bState').select2();
$('.bState').on('change', function() {
let data = $(this).val();
@this.set('billingStateId', data);
});
});
</script>
@endpush
Livewire Component
------------------------------
public $billingStateList, $billingCityList;
public function updatedbSelectedCountry($id){
$this->billingStateList = SysState::where(['country_id' => $id])->get();
}
public function updatedBillingStateId($id){
$this->billingCityList = SysCity::where(['state_id' => $id])->get();
}
</div>
由于辅助 select 依赖于父级,因此必须动态更新。这就导致Livewire的管理和Select2的管理发生冲突,在DOM的修改上有重叠。因此,我决定从 Livewire 中删除对选择的管理,并仍然让它从存储中读取数据。
景色
<div>
<div class="col-12 col-md-6">
<div class="ps-checkout__group">
<label class="ps-checkout__label">Country *</label>
<span wire:ignore>
<select class="form-control input-dropdown bCountry">
<option value="">Select a country</option>
<!-- the options will be loaded by JS -->
</select>
</span>
</div>
</div>
<div class="col-12 col-md-6">
<div class="ps-checkout__group">
<label class="ps-checkout__label">State *</label>
<span wire:ignore>
<select class="form-control input-dropdown bState">
<!-- the options will be loaded by JS -->
</select>
</span>
</div>
</div>
<br>
<br>
<div> <!-- this is for debugging -->
Country: [{{ $bSelectedCountry }}]
<br>
State: [{{ $bSelectedState }}]
</div>
</div>
@push('scripts')
<script>
$(function () {
// The countries are converted in JSON data to be managed by JS
const countries = {{ Js::from($countries) }};
$(".bCountry").select2({data: countries})
.on("change", async (el) => {
// assigns the value of the select to the property of the class
@this.bSelectedCountry = el.target.value;
// reset of the secondary select
@this.bSelectedState = null;
// request for rows to the backend - due to this call the view is updated automatically
const statesList = await @this.stateList();
// update of the child select
initStates (statesList);
});
// initial setup of the child select
initStates();
});
function initStates (data = {}) {
const stateSelect = $(".bState");
if (stateSelect.hasClass("select2-hidden-accessible"))
stateSelect.select2("destroy");
stateSelect.empty()
.append('<option value="">Select a State</option>')
.select2({data: data})
.off('change')
.on("change", (el) => {
// assigns the value of the select to the property of the class
@this.bSelectedState = el.target.value;
// this replaces the .live modifier
@this.$refresh();
});
}
</script>
@endpush
每个 select 都由包含 wire:ignore 的 span 包裹,以防止 Livewire 更新。这意味着选项和交互必须通过 Javascript 进行管理。
我还添加了所选值的输出以进行调试。
班级
class TestSelect extends Component
{
public $billingCountriesList;
public $billingStatesList;
public $bSelectedCountry = null;
public $bSelectedState = null;
public function updatedbSelectedCountry($id) {
$this->billingStateList = SysState::where(['country_id' => $id])->get();
}
public function updatedBillingStateId($id) {
$this->billingCityList = SysCity::where(['country_id' => $id])->get();
}
public function stateList() {
return SysCountry::where('status', 1)
->ordeBy('name')
->get(['id', 'name as text']) // Select2 accepts id - text
->toArray();
}
public function render() {
// the countries for the main select are passed from the backend
$countries = SysCountries::where('status', 1)
->ordeBy('name')
->get(['id', 'name as text']) // Select2 accepts id - text
->toArray();
return view('livewire.test-select', ['countries' => $countries]);
}
我把主选择选项的阅读移到了课堂一侧,它 始终建议将数据选择保留在后端,而且在这种情况下,需要进行一些操作