AlsoI know that I achieve that by using a javascript eventlister on the change event (or so) on the inputbox and communicate the width to a method of my livewire component with @wire->emit but I really need to do it with the @entangle method in order to understand and better learn the way to use it.
I have a component with x-data values, on button press this values change from false to true, but when livewire re-render on a wire:model-lazy input this value return to initial x-data state, how can i solve this, and maintain value.
I recently had to create a file uploader that allowed the user to both click a button and select files, or simply drag files unto the page. I decided to give Livewire a shot as it seemed interesting. My first thought was to use a js package like resumeable.js or DropZone, but after reading Livewires file upload docs, I figured it might be easier to just use the built in system and extend it with some simple JavaScript.
To make our code a bit cleaner we will add a script tag inside the page to set up the data for alpine first. It will just return an object with some defaults we will use later. Add x-data="fileUpload()" to the outermost div, and add the script shown below. Be sure to nest it inside the outermost div, as livewire does not like multiple root elements.
Normally when you add a file input to the page with livewire, you would simply use wire:model to automatically upload the files as they are added (to a temp directory). But as we need to implement the upload when dragging files, it makes sense to implement this ourselves as well. Luckily livewire makes this very simple.
First we will add the WithFileUploads trait to the component to tell livewire that we want file uploads. Next we add a new public property to the component class to have a place for livewire to store a reference to the files.
So we add a new method to handle all uploads called uploadFiles(). It receives the files and uses the livewire @this.uploadMultiple() function to upload them to the livewire component. Note that the first argument is the name of the public property in the component class. Not that I am rebinding this to $this. This is because the this changes when inside the functions of each callback in the upload. This could also be handled by using arrow functions
I am aware that there is some flickering when the file is right on top of the text in the middle of the page. Sadly I have yet to find a solution for this. Let me know if you find a solution so I can update the guide. @rsinnbeck
And just like that we can see the progress of the uploads!Be aware that you might not be able to see the progress bar move at all, as the uploads are so fast when working locally. Therefor it might be a good idea to enable throttling in the browser, so you can actually see it progress: -to-perform-network-throttling-in-chrome
You might notice that if you add files in more than one go, it will replace all the files from earlier. This is due to the fact that, livewire just throws away old files when using @this.uploadMultiple(). Luckily we can just overwrite the upload function for this component to force it to merge the uploads.
As the files are only uploaded to a temp folder, you of course want to submit the form to finally save them. But perhaps the user added a file by accident and want to remove it without starting over. Let's add a remove button!
Update the Upload component to allow for file uploads with the WithFileUploads trait, and create a method to eventually decide what you'll do with the file when the form is submitted. I've added some example validation rules here, but you'll need to adjust it depending on your needs.
As soon as you choose a file to upload via the input, Livewire will begin uploading the file in the background and store it as a temporary file until it's ready to be moved. This is the event we want to hook into to display the progress.
Next, we listen to the global events fired by Livewire for the upload, and set uploading to true or false depending on which event fired. Alongside that, we read the progress from the event's detail object and set that within our x-data object.
Under the hood, wire:model adds an event listener to update a property every time the input event is dispatched on or under the element. Another way to communicate between Livewire and Alpine is by using Alpine to dispatch an input event with some data within or on an element with wire:model on it.
Fortunately a library like Pikaday adds it's extra DOM at the end of the page. Many other libraries manipulate the DOM as soon as they are initialized and continue to mutate the DOM as you interact with them.
If you can follow, you should be able to see the potential here. This API allows you to interact with a Livewire component, programatically, from JavaScript. This pattern unlocks all sorts of potential.
You may be wondering, "But how do I get the unique component id?". Well, you can inspect the source and look at the wire:id attribute on the root element of the component. OR you can use this very handy syntax from inside your Livewire component's view:
If you followed, Livewire has a Blade directive called @this that is an alias for window.livewire.find('...'). This directive makes it extremely easy to talk to the current Livewire component from JavaScript, particularly AlpineJS expressions.
It's important that you use the $this->form->fill() method instead of assigning the data directly to the $this->data property. This is because the post's data needs to be internally transformed into a useful format before being stored.
In some cases, the form's model is not available until the form has been submitted. For example, in a Create Post form, the post does not exist until the form has been submitted. Therefore, you can't pass it in to $form->model(). However, you can pass a model class instead:
On its own, this isn't as powerful as passing a model instance. For example, relationships won't be saved to the post after it is created. To do that, you'll need to pass the post to the form after it has been created, and call saveRelationships() to save the relationships to it:
In all of our previous examples, we've been saving the form's data to the public $data property on the Livewire component. However, you can save the data to individual properties instead. For example, if you have a form with a title field, you can save the form's data to the $title property instead. To do this, don't pass a statePath() to the form at all. Ensure that all of your fields have their own public properties on the class.
By default, the InteractsWithForms trait only handles one form per Livewire component - form(). To add more forms to the Livewire component, you can define them in the getForms() method, and return an array containing the name of each form:
Filament is also able to generate forms for a specific Eloquent model. These are more powerful, as they will automatically save the data in the form for you, and ensure the form fields are properly configured to access that model.
By default, passing a model to the make:livewire-form command will result in a form that creates a new record in your database. If you pass the --edit flag to the command, it will generate an edit form for a specific record. This will automatically fill the form with the data from the record, and save the data back to the model when the form is submitted.
Notice that the above will only be visible if the value of visible is set to true. Using the @entangle function, we are retrieving and sharing the value of the isVisible PHP variable inside of the Livewire component controller.
Be sure to visit the Livewire docs on sharing data with Alpine here: -
livewire.com/docs/2.x/alpine-js. You can utilize so many cool features to make interacting with Alpine and Livewire data as seamless as can be.
Laravel Livewire is a great tool to achieve dynamic behavior on the page, without directly writing JavaScript code. And, like any tool, it has a lot of "hidden gems", both in its official docs, and practical extra tips provided by developers. I decided to compile some of them in this article. Let's get into it!
But if your render() method is just a one-line to render the default view, you may delete that render() method from the component and it will all still work, loading the default render() from the vendor's method.
If you use some external package with Livewire components, you may have your Livewire component in a different folder than the default app/Http/Livewire. Then, you may need to bind its name to the actual location.
Livewire components are generated using the default templates, so-called "stubs". They are hidden away in the "vendor" folder of the Livewire package, but you can publish them and edit them according to your needs.
For example, if you want to generate the components without the render() method, just remove it from the stub file, and then each time you run php artisan make:livewire Component, it will take the template from your updated public stub.
One of the main criticism of Livewire is the fact that it does too many requests to the server. If you have wire:model on the input field, each keystroke would potentially call the server to re-render the component. It's very convenient if you have some real-time effects, like "live search". But generally, server requests may be quite expensive, in terms of performance.
wire:model.lazy: by default, Livewire is listening for all events on the input, and then performs the server requests. By providing a lazy directive, you tell Livewire to listen only to the change event. It means that the user may keep typing and changing the value, and the server request will be fired only when the user clicks away from that field.
wire:model.defer: this will not fire the server requests on the change of the input. It will save the new value internally and will pass it to the next network request, which may come from other input fields or other button clicks.
3a8082e126