My project using livewire 3 has a slight problem that occurs when my component uses lazy components.
<livewire:report lazy />
When I don't use lazy, monthpicker and datepicker don't have problems when I refresh the page manually or switch pages using the wire:navigate link.
But when I add lazy to my component, monthpicker and datepicker can't work.
My guess is because livewire uses placeholder before loading to my page which has monthpicker and datepicker.
My code:
<div class="row">
<div class="col-md-8">
<div class="card card-custom gutter-b example example-compact">
<div class="card-header">
<h3 class="card-title">Report</h3>
</div>
<form wire:submit.prevent="submit">
<div class="card-body">
<div class="form-group">
<label>Pilih Bulan<span class="text-danger">*</span></label>
<input type="text"
class="form-control custom-width"
placeholder="Select month"
wire:model='bulan'
id="month_picker"
autocomplete="off"
/>
@error('bulan') <span class="error">{{ $message }}</span> @enderror
</div>
</div>
<div class="card-footer">
<div class="text-center" wire:loading>
<button type="button" class="btn btn-primary spinner spinner-white spinner-right" disabled>
Validating
</button>
</div>
<button type="submit" class="btn btn-primary mr-2"
wire:loading.attr="disabled"
wire:loading.class="d-none">
Generate
</button>
</div>
</form>
</div>
</div>
</div>
@push('script')
<script>
var KTBootstrapDatepicker = function() {
var arrows;
if (KTUtil.isRTL()) {
arrows = {
leftArrow: '<i class="la la-angle-right"></i>',
rightArrow: '<i class="la la-angle-left"></i>'
}
} else {
arrows = {
leftArrow: '<i class="la la-angle-left"></i>',
rightArrow: '<i class="la la-angle-right"></i>'
}
}
var demos = function() {
$('#kt_datepicker').datepicker({
rtl: KTUtil.isRTL(),
todayHighlight: true,
orientation: "bottom left",
templates: arrows,
autoclose: true,
format: "dd-mm-yyyy"
}).on("changeDate", function(e){
@this.set('bulan', e.format());
});
$('#month_picker').datepicker({
rtl: KTUtil.isRTL(),
todayHighlight: true,
orientation: "bottom left",
templates: arrows,
autoclose: true,
format: "mm-yyyy",
viewMode: "months",
minViewMode: "months",
}).on("changeDate", function(e){
@this.set('bulan', e.format());
});
}
return {
init: function() {
demos();
}
};
}();
jQuery(document).ready(function() {
KTBootstrapDatepicker.init();
});
</script>
@endpush
I've tried reading and using Hook on livewire 3 as per documentation but still not able to solve this problem.
Livewire.hook('morph.added', ({ el }) => {
//
})
Maybe I missed something? Need your help
A possible solution is to use the syntax @script @endscript
instead of @push('script') @endpush
in this way Livewire will manage the component script and this will allow it to execute correctly:
@script
<script>
const KTBootstrapDatepicker = function() {
let arrows;
if (KTUtil.isRTL()) {
.....
</script>
@endscript
Note that I used const instead of var to declare KTBootstrapDatepicker since the @script @endscript syntax has some issues with old constructs or comments when placed in the first position
Some suggestions:
instead of @this.set('bulan', e.format())
to avoid an AJAX call everytime the value changes, you can use the following syntax: @this.bulan = e.format()
. This way the changes are kept locally but can be sent to the backend when you execute a submit (you can check this using the network tab of your browser).
Using @script @endscript you can use also the $wire.bulan = e.format()
syntax instead of @this.bulan = e.format()
Although the datepicker seems to work well, since it is managed by the Bootstrap code, it may cause some interference with Livewire. To avoid conflicts you could wrap the datepicker inputs in a tag with the wire:ignore attribute, this way Livewire won't interfere with the inputs:
<div wire:ignore>
<input type="text"
class="form-control custom-width"
placeholder="Select month"
id="month_picker"
.....
>
</div>