Call livewire function in custom form component from alpine and set state for two fields

Hi, I am making a pretty cool plugin I think where users can easily select a time slot. My goal is to set two date fields from this special selector. I have the alpine side working where I can select two timeslots, but i am stuck on how to pass the alpine data to livewire to accordingly set the state of the date fields. In the screenshot you can see what I am trying to achieve. Now in the alpine script I have an object called selectedSlots which are correctly filled with the time selected by the user. My next step is to send the selectedSlots to php via this.$wire.updateTime
setTime: function(element) {
const from = parseFloat(element.getAttribute('data-from'));
const till = parseFloat(element.getAttribute('data-till'));

if (this.clicks === 0) {
this.selectedSlots.from = from;
this.selectedSlots.till = till;
this.clicks++;
}else if(this.clicks === 1){
// second click
this.selectedSlots.from = from < this.selectedSlots.from ? from : this.selectedSlots.from;
this.selectedSlots.till = till > this.selectedSlots.till ? till : this.selectedSlots.till;
this.clicks = 0;
}

this.$wire.updateTime();
console.log(this.selectedSlots);
},
setTime: function(element) {
const from = parseFloat(element.getAttribute('data-from'));
const till = parseFloat(element.getAttribute('data-till'));

if (this.clicks === 0) {
this.selectedSlots.from = from;
this.selectedSlots.till = till;
this.clicks++;
}else if(this.clicks === 1){
// second click
this.selectedSlots.from = from < this.selectedSlots.from ? from : this.selectedSlots.from;
this.selectedSlots.till = till > this.selectedSlots.till ? till : this.selectedSlots.till;
this.clicks = 0;
}

this.$wire.updateTime();
console.log(this.selectedSlots);
},
However this keeps ginving me the message Unable to call component method. Public method [updateTime] not found on component But that function IS in the livewire form component... I also tried using the this.$wire.dispatch method with a listener using #[On] but it gives the same result. Am I missing something here...? Help would be appriciated! I will make this public because I think it will be very usefull!
No description
Solution:
For people trying to achieve setting multiple fields: Make your component which needs to set multiple values return a stringified json object. Then just decode it in your afterStateUpdated and set the other fields!...
Jump to solution
7 Replies
gladjanus43
gladjanus43OP4mo ago
The issue for me is that I cannot use the regular state entanglement to pass the state, because I want to set two separate states with this one component... What would be the best way to attack this problem? I figured out that Form fields are ofcourse not livewire components. Is there somebody who can help me in the right direction? I dont know what would be logical and how the state management is normally done in the different form components. Does it work that If I use the $getStatePath() function and update the state directly of the parent form it will update the values correctly? Or is there another method which I need to use to correctly set the form value And how can I access the values of the form from my custom form component...
Dennis Koch
Dennis Koch4mo ago
because I want to set two separate states with this one component.
Yeah, that's not really possible, you need to bind an object or array. I haven't build a custom field yet, but can you use afterStateUpdated() on your field to split the value into multiple values?
gladjanus43
gladjanus43OP4mo ago
Hmmmm, thats unfortunate. You mean that my component returns an array which can be user That might be possible I also saw something from lara zeus (qr code generator) where a component was rendered with multiple fields. Is that something which could work, meaning that I can then set the values within the form component
Dennis Koch
Dennis Koch4mo ago
I guess you could probably deviate from a standard field and add addtional methods on your field to define different statePaths. That could work to.
YourField::make('something_unique')
->field1('field_1')
->field2('field_2')
YourField::make('something_unique')
->field1('field_1')
->field2('field_2')
Store that info and use it when entangling data.
gladjanus43
gladjanus43OP4mo ago
Really awesome. I made a separate field which sets the state as json. Now I added this field to a component which also renders two fields from and till:
$this->schema(function () {
return [
Grid::make()->schema([
DateTimePicker::make($this->getStartTimeColumn()),
DateTimePicker::make($this->getEndTimeColumn()),
]),
TimeChooserField::make($this->name)
->afterStateUpdated(function ($state) {
dd('test');
})
->live(),

];
})->columnSpanFull();
$this->schema(function () {
return [
Grid::make()->schema([
DateTimePicker::make($this->getStartTimeColumn()),
DateTimePicker::make($this->getEndTimeColumn()),
]),
TimeChooserField::make($this->name)
->afterStateUpdated(function ($state) {
dd('test');
})
->live(),

];
})->columnSpanFull();
Working all as intended, now I only need the after state to set the values of the other fields only it is not calling the afterStateUpdated function unfortunatly
No description
gladjanus43
gladjanus43OP4mo ago
Thanks for the suggestion, got it working 🙂
Solution
gladjanus43
gladjanus434mo ago
For people trying to achieve setting multiple fields: Make your component which needs to set multiple values return a stringified json object. Then just decode it in your afterStateUpdated and set the other fields!
Want results from more Discord servers?
Add your server