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

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>

Related

Laravel not rendering form element, but only the contents inside

I have been stumped on this for a couple hours and can not figure a way around it.
Larvel 8 with Livewire
I have a very basic form.
<form action="/dashboard/payment" method="POST">
#csrf
<button type="submit" class="btn btn-primary my-3 w-100" id="checkout-button">
<span wire:loading>Please Wait</span>
<span wire:loading.remove>Pay - $
<span>100</span>
<br>
<small>Description of payment</small>
</span>
</button>
</form>
But the form tag itself it is not rendering the html. It is only rendering the button inside.
When incrementing a value with another button, the form tag is then rendered into html and the button can be used as expected.
The incrementing button only ++ to a value and updates the database with the new value.
This is the only thing holding me back, I have searched everywhere but cant find any information about form tags not rendering.
Note: Neither the opening tag or the closing tag is rendered until the other button is pressed.
Any ideas or information would be fantastic and greatly appreciated.

typing in textarea triggers render in livewire

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.

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>

What are the methods to pass Springboot/Thyleaf objects to Modal forms?

I'm confused. I've thought it's possible to pass SpringBoot/Thymeleaf objects from the html page to the Modal form. I've come across many examples using ajax to pull data from the REST endpoint instead.
Is using ajax to pull in objects into Modals, the only method?
Thymeleaf is a server side templating language... the concept of a modal form usually means showing/hiding a window opens and closes on the client side (meaning JavaScript that runs when a user clicks a link or a button ). If you don't want to use an API to pull that data (which I think makes the most sense), then you have to create a hidden modal for every row on your page. For example:
<div th:each="item, i: ${items}">
<a href="#"
onClick="openModal(this.getAttribute('data-modal'))"
th:data-modal="|#modal${i.index}|">
Edit modal #<span th:text="${i.index}" />
</a>
<div th:id="|modal${i.index}|" style="display: none;">
<p>I am a modal form for element <span th:text="${i.index}" />!</p>
<input type="text" th:value="${item.value}" />
</div>
</div>
You can see how this works... creating a hidden div/modal form for every row (so you don't have to call an API to get the form values), but it comes with a lot of extra HTML.

How to Use JavaScript instead of Custom HTML Attributes for Angular Forms?

Considering this example markup (from http://www.ng-newsletter.com/posts/validations.html):
<div class="row">
<div class="large-12 columns">
<label>Your name</label>
<input type="text"
placeholder="Name"
name="inputNameAttributeValue"
ng-model="signup.name"
ng-minlength=3
ng-maxlength=20 required />
<div class="error"
ng-show="signup_form.name.$dirty && signup_form.name.$invalid">
<small class="error"
ng-show="signup_form.name.$error.required">
Your name is required.
</small>
<small class="error"
ng-show="signup_form.name.$error.minlength">
Your name is required to be at least 3 characters
</small>
<small class="error"
ng-show="signup_form.name.$error.maxlength">
Your name cannot be longer than 20 characters
</small>
</div>
</div>
</div>
Is there a way to accomplish the same thing, but use JavaScript instead of custom Angular attributes?
For example, is there a way I can use JavaScript instead of these Angular html attributes: ng-model, ng-minlength, ng-maxlenth, ng-show?
EDIT:
Just to clarify, I'm looking for a solution that uses the Angular JavaScript API. I would like to have a separate JavaScript document (linked from my HTML document) that uses the Angular JavaScript API. For example, is there a way to specify ng-model for a particular form field using the Angular API instead of the custom Angular HTML attribute?
As I understand it, you want to add a directive (for example ng-model) from javascript, similar to how you would do it with jQuery. Short answer: Don't do it.
Longer Answer: It's probably technically possible, but it would violate the basic principles of AngularJS. Your controller should not touch the HTML at all, in fact any code which should directly manipulate the HTML should be placed in a directive. And that directive should be placed on the input directly in your HTML, which is exactly what you wanted to avoid.
If placing directives in your HTML is not practical for your project, then perhaps you should reconsider using AngularJS.
There's a rather long (and well written) answer here on Stackoverflow which explains "how to think in AngularJS", you might find that it's of interest: https://stackoverflow.com/a/15012542/179024
It would also be interesting to know why you want to do this? There is often an "Angular way" of doing things, but it can be different from what we are used to doing.

Resources