typing in textarea triggers render in livewire - laravel

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.

Related

Is it possible to trigger a Livewire modal component with Bootstrap?

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>

Livewire Alpinejs Emit/Dispatch variables across files

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>

parsley.js 'fails' when trying to validate checkbox

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.

Laravel testing form press method doesn't works

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');

Safari Ajax bug? checked radio not checked

In Safari, If I load a piece of html via XHR (ajax) the browser does not render the radio button that has the checked="checked" attribute as checked.
the html I fetch via ajax:
<input type="radio" name="radiotest" value="off">
<input type="radio" name="radiotest" value="on" checked="checked">
the browser renders two unchecked radio buttons. If I load the exact same code directly from a plain html file (no ajax) the radio buttons render as they should, the last being in its checked state.
what's wrong, is this a known bug? Is there a fix available?
EDIT:
Probing further this looks like a browser bug, and I could not so far fix it with jQuery Post processing, any help appreciated.. here is what I've found:
I have a page that pulls in some form element via ajax.
The html is this:
<input type="checkbox" name="checktest">
<input type="checkbox" name="checktest" checked="checked">
<input type="radio" name="radiotest" value="off">
<input type="radio" name="radiotest" value="on" checked="checked">
after the form element are pulled in, the checkboxed render correct, but the radios both render unckecked. Now, If i run the following jQuery command (from the Safari 5 console):
$('#activemodules input[checked="checked"]');
..it returns an object containing the one checked checkbox.
but if I run the command:
$('#activemodules input[value="on"]');
it actually retuns the correct object, and it even shows its outerHTML property correct like this:
outerHTML: "<input type="radio" name="radiotest" value="on" checked="checked">"
now, if I do:
$('#activemodules input[value="on"]').attr('checked','checked');
Safari get's it, and renders it correctly. I guess I'll just have to pass a data-ischecked="true" attribute and use that to catch and 're-check' all radio buttons after the ajax bit is loaded.. but still, even if I can do this, I'd like to hear any comment or suggestions on this.
This is what my solutions ended like:
First I add a data-ischecked="1" attribute to the radios that are checked:
<input type="radio" name="foo" data-ischecked="1" value="bar" checked="checked">
then, after the ajax call succeeds and finishes I run this:
$('#myradios :radio')
.each(function(){
if( $(this).data('ischecked') ){
$(this).attr('checked','checked');
$(this).removeAttr('data-ischecked');
}
});
This seems to work fine.. but I found out some other stuff of importance:
If I called the data attribute simply data-checked instead of data-ischecked it DID NOT WORK, maybe this is a reserved name?
And also; if I ran the operation on the broader selector scope:
$(':radio')
.each ...
then it also DID NOT WORK
I don't know why, but adding the id of a parent element of the radios that was also part of the html returned by the ajax call to the selecor scope like this:
$('#myradios :radio')
made it work..
I found that mikkelbreum's solution only worked if I did not include the "checked" attribute in the AJAX-injected code.
<input type="radio" name="foo" data-ischecked="1" value="bar">

Resources