How can I emit and recognise changes from child components (in separated files) using AlpineJS?
I'm trying to build a form in Livewire/alpinejs that would only show the next step after selected a value in the previous step.
I know I can use livewire model/emitUp to catch changes from the selectfield child component and then use x-show accordingly. However, emitting up is rather slow, waiting around 5 seconds after selecting each select field isn't a good user experience. Hence the user of AlpineJs.
The issue is that x-data is scoped locally and I cannot pass down a variable and assign that as the x-model. AlpineJS has $dispatch, but it seems to only work within a file. So I can't dispatch when the x-model changed and then catch that change in Livewire Main Form.
Livewire Main Form
<div>
<form>
<livewire:selectfield />
{{-- Only show this div when livewire:selectfield has selected a value (Incomplete code)--}}
<p>
Should see this only when a select-field value has been selected
</p>
</form>
<div>
Livewire Select Field
<div x-data="{ selectedField: '' }">
<label> Form Label </label>
<select x-model="selectedField">
<option value="1">Opt 1</option>
<option value="2">Opt 2</option>
<option value="3">Opt 3</option>
</select>
</div>
Is there any way of showing/hiding div elements when the child component input fields have a selected input? Preferably with AlpineJS due for user experience and less network bombardments.
EDIT
Turns out I just didn't use the functions properly! Ignore this
Must of read the docs wrong. Using Livewire/AlpineJS can emit values from child to parent, similar to VueJS.
The child component HTML should have
<button type="button" #click="$dispatch('custom-event')">Test Model Update Upwards</button>
The parent component has this html. In your case, just add the custom event where it makes sense.
<p #custom-event.window="console.log('Workign emit function cross child/parent')"></p>
Related
I have a situation where I am showing/hiding form fields based on the input of a previous field. For example:
<x-forms.select #change="bussingRequired = $event.target.value" label="Bussing Required" name="bussing_required" required >
<option value="Yes">Yes</option>
<option value="No">No</option>
</x-forms.select>
<div class="col-span-12" x-show="bussingRequired == 'Yes'">
<div>
<!-- show another required field -->
</div>
</div>
The problem with this is x-show only hides the element with CSS and the field still exists in the DOM. Since the hidden field is required, frontend validation fails.
My question is what is the better way to handle this? Is there a way to completely remove the element from the DOM with alpineJS? Is there a way to modify the frontend validation in laravel with something like a required_if like we have in the backend?
I'm trying to render a modal that gets triggered by a button, so that I can then include payment elements in this modal and allow the user to begin to make payment. However, most Livewire modals I've seen - here, for example - use Livewire events to do the toggling of the model, which both requires adding ugly logic to the view and seems like it would still be slower than anything client-side.
It seems to me like it would be faster to allow Bootstrap to trigger the modal via its own JavaScript (using data-bs-* attributes), and only make use of Livewire when actually loading the content into the modal. Is this approach possible, or do Livewire components have to be loaded via Livewire in order to be populated by it?
Using the LiveWire is logical when you need to exchange information with the server and need to request and respond via HTTP protocol. LiveWire has replaced ajax or something like axios. So it’s better you use a modal bootstrap or any element handled on front and use livewire when you want to do something on the server for example fetch or save data via database. You can use livewire components in any blade as any part of your project.
I use tailwind modals, in theory you could use any modal, the only thing is that you put the wire to each input, look at this example
<div class="md:col-span-3">
<label
for="class_name"
class="block text-gray-700 text-sm font-bold mb-2"
>
Description:
</label>
<textarea
class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 resize rounded-md shadow-sm block mt-1 w-full"
id="step_description"
wire:model.defer="step_description"
></textarea>
</div>
I have a textarea and when I type in it, render function works. What is the problem?
<label class="tf-form-label" for="form.reason">
{{ __('Reason') }}
</label>
<textarea wire:model.debounce.250ms="form.reason" rows="5" name="form.reason" id="form.reason" class="tf-input" ></textarea>
<x-jet-input-error for="form.reason" class="mt-2" />
That is the default behaviour when you bind an element to a Livewire. Debounce does not prevent this, just provides control over when Livewire triggers a network request to update itself.
If you don't want to update on every character input, you either want to use the lazy which sends a network request when it detects the native change event, or defer which batches updates and sends them when you explicitly tell the form to submit.
We are re-designing a site and part of that re-design involves making the site accessible to screen readers and the like. I'm using latest version (2.8.0). Here's what's happening --- validation for all text, select and textarea fields in our forms work perfectly. In order to be accessible, checkbox and radio inputs are wrapped in tags. The html for a set of checkboxes looks like this:
<div class="form-group">
<p id="applicant_type_desc" style="margin-bottom: 6px;"><strong>I am: <span class="text-danger" aria-hidden="true">*</span><span class="sr-only">Required</span></strong> <em class="small">(check all that apply)</em></p>
<div class="checkbox">
<label id="applicant_type_patient_desc">
<input type="hidden" name="applicant_type_patient" id="" value="N">
<input type="checkbox" name="applicant_type_patient" id="applicant_type_patient" value="Y" {checked_applicant_type_patient} aria-labelledby="applicant_type_desc applicant_type_patient_desc" data-parsley-multiple="type" data-parsley-error-message="Please specify whether you are a patient, relative, employee or other.">
A patient
</label>
</div>
followed by more checkbox divs without error messages and ended with an end div for the for form-group wrapper.
If I load the form and click 'submit', all the text fields are validated properly. If I add 'required' to the checkbox above, when 'submit' is clicked nothing happens and the form is submitted with no validation at all.
The same thing happens when I try to validate a radio button set as required.
There is some custom jQuery and parsley code which creates a div to hold all the error messages and transforms the error messages into links to the field id so that a screen reader can follow them and focus on the field in error. But imho, this should have no effect on why the form validation doesn't kick in.
I'm absolutely baffled.
FYI - I tried this using an earlier version (2.0.3) of parsley and the validation actually worked, although all my custom error processing was ignored.
Any insight would be greatly appreciated.
As it turns out, parsley handles the errorswrapper element differently for text, textarea and selects then it does for checkboxes and radio buttons.
The starting wrapper element for text, textarea and select contains the parsley-data-id attribute whereas checkbox and radio button elements contain the parsley-data-multiple attribute whether that was generated by parsley or entered manually in the html.
My code was looking for parsley-data-id and, of course the jquery selector failed and generated an error. A colleague was able to spot this for me while we were looking at the page in chrome inspector. Once i saw the error, making a simple adjustment to the form:error event function allowed everything to work.
I'm trying to cover my project with test and faced with problem.
The "press" method of TestCase fails with 'InvalidArgumentException: Unreachable field ""'
However the "see" method sees the needed button
Besides another form on another page tests fine
Hours of debug show me that the issue might be in the fact that the problem form has multiple (with this brackets []) inputs
Test code that fails
$this->type($params['from'], 'from[]');
$this->type($params['event'], 'event[]');
$this->type($params['class'], 'class[]');
$this->type($params['method'], 'method[]');
$this->press('save_handlers');
With form and button everythings is okey
Button:
<button type="submit" class="btn btn-primary btn-block" name="save_handlers">Save</button>
And of course button is in the form tag
Indeed, the problem is linked with the fact that there are attributes with brackets[].
I just had the same problem. I'm using a form with multiple checkboxes, and all of them have the same name (but different id) : codes[]. I'm doing this in order to retrieve them later (in a controller) simply as an array of values.
<input id="perm-0" type="checkbox" name="codes[]" value="perm-0" />
<input id="perm-1" type="checkbox" name="codes[]" value="perm-1" />
<input id="perm-2" type="checkbox" name="codes[]" value="perm-2" />
My friend var_dump() told me that the Symfony component which parses the form inputs doesn't like it when I'm using codes[] with nothing inside the brackets. It is seen as two fields : "codes" and "" instead of codes[]. That's causing the Unreachable field "" error.
A simple solution I found is to simply add an explicit index for the codes[] array :
<input id="perm-0" type="checkbox" name="codes[0]" value="perm-0" />
<input id="perm-1" type="checkbox" name="codes[1]" value="perm-1" />
<input id="perm-2" type="checkbox" name="codes[2]" value="perm-2" />
This way each checkbox is distinct from others, and the method press() does not cause the error any more.
It seems that this doesn't affect the processing of the resulting array in my controller.
This seems rather confusing seeing as the docs state this:
"Press" a button with the given text or name.
While the docblock above the actual press method states the following:
Submit a form using the button with the given text value.
So instead of using the value of the name attribute (save_handler) use the actual text (Save).
$this->press('Save');