Stacking Page Styles0:32
You can see I have some CSS here for Quill, but how about we make a stack for our styles so we only load them on the pages that need them. So let's say stack, let's name it styles, and on our edit announcement, let's push to that stack. So let's just say up here, say push to styles, and let's say end push. Let's paste that in here. Also make sure to grab the other one we have here for Quill, because we only need it on that page. So let's grab this, paste it in here, and let's see if Quill still works to make sure the stack is working correctly.
So let's grab this, paste it in here, and let's see if Quill still works to make sure the stack is working correctly. And it is, cool. Let's go ahead and grab the JavaScript. So we do have a stack for our JavaScript, so we can just put that within the stack. Paste that down here, so right by my other import for Quill, I'm going to get rid of this comment here and just say imports, okay? And that should be all of our setup. We just need to create a new file input and then initialize FilePond. So there should be an example here.
Adding FilePond Input1:34
We just need to create a new input and then initialize FilePond. So there should be an example here. So we still make use of input type equals file, but we can initialize FilePond like this. So grab an element and then say FilePond.create with that element. So let's grab this. Let's make a new input type equals file, so we can just duplicate what we have here. So I'll just keep what we have here in the last video, and we'll just add a new one for FilePond image uploads. So let's duplicate all of this.
FilePond image uploads. So let's duplicate all of this. Let's name this ImageUploadFilePond instead. So let's grab these two as well. Let's say ImageUploadFilePond, same with the label here. And let's also give this an ID of ImageUploadFilePond as well. So we'll use that as the selector. So let's put it right here, ID equals this. We can still make use of this accept attribute to only accept certain files, in this case images.
We can still make use of this accept attribute to only accept certain files, in this case images. And we also have to add this field to our database. So ImageUploadFilePond. So we'll do that in a second. Let's go ahead and initialize FilePond down here. Let me just move this comment down here and change it to a JavaScript comment. And we'll put the code in here for FilePond. So init FilePond. So let's change our selector to the ID we gave it, so it was ImageUploadFilePond.
So init FilePond. So let's change our selector to the ID we gave it, so it was ImageUploadFilePond. And let's see if FilePond is rendering in the browser. So let's save this back to our browser, back to our code. Let's refresh this. And there is our FilePond image upload. So let's go ahead and try this. Let's browse for an image. It looks like the file validation didn't work. And I think we need a plugin for that.
Installing FilePond Plugins3:14
It looks like the file validation didn't work. And I think we need a plugin for that. But for now, let's try uploading this image and see how it looks. You can see it is trying to upload it here. And this is the default UI. But we can also add an image preview, which is one of the plugins that we'll use. So if we go to the documentation, there is a section here for plugins, right here. Take a look at the image preview right here. So let's go ahead and install it. Again, we'll use the CDN here.
Configuring Server Uploads5:21
Okay. And even if we try to drag and drop a non image here, it should reject that file. So let me try uploading a PDF here. And you can see this file type isn't valid. Now let's take a look at how we can actually upload files. So if you go to the server section, and if you scroll down a bit, you'll see the process for this. So with FilePond, as you select a file in here, after you select it, it's automatically going to hit an endpoint on your server, which allows you to upload the file. So we have to add an option for that within our code.
going to hit an endpoint on your server, which allows you to upload the file. So we have to add an option for that within our code. So let's go back here to our FilePond instance. And the second parameter here is an object with some options. So one of them is a server option, so we'll say server. And this is an object as well with a few options. And one of them is the endpoint you want to hit to upload your file. So we can say URL, and we can say we want to hit the /upload endpoint, which we have to create on our back end. And this endpoint will be responsible for uploading the file.
Let me just hard refresh and try again. So one more time, let's try this image. Let's open it. And now you can see it's trying to hit this endpoint here and we are getting a 404 because it doesn't exist yet. So let's create that endpoint on our back end. So let's go to our routes/web.php. Let's create an upload endpoint. Now put it right here. Let's say Route::call, and we'll say upload, it takes in the $request, so say $request.
Now put it right here. Let's say route, call, and we'll say upload, it takes in the request, so say request, request. And it should be a POST request, actually. So let me change this. And let's just return hi for now. Okay. So now let's try it out and see if we get a response. So back here, let's hard refresh again. Let's select that file. And you can see we do get a different error here.
Let's select that file. And you can see we do get a different error here. It's no longer a 404. So it did find that endpoint. But now we're getting a 419. So 419 usually have to do with CSRF tokens. So we have to make sure to pass that through as a header. So we can do that within the options within FilePond. So back to our FilePond options, we can pass through headers here. So say headers, this is an object, and we want to send through the X-CSRF-Token.
So back to our FilePond options, we can pass through headers here. So say headers, this is an object, and we want to send through the X-CSRF-Token. And we can make use of the helper in Laravel. So let's say double curlies, csrfToken as a method. Okay. Let's try that one more time. Back here. Let's hard refresh. Let's select an image here. Okay.
Let's select an image here. Okay. And now we are getting 200 here. And if you take a look at this, there is the response. So from here, we can actually add the code to upload the image. So let's go ahead and do that. But like I said earlier, we have to add that new field in our database. So let's start with that. So let's update our create_announcements table. Let's add a new field for Image Upload FilePond, which is also nullable.
Saving Uploads to Database8:31
So let's update our CreateAnnouncements table. Let's add a new field for Image Upload FilePond, which is also nullable. Okay. It's php artisan migrate:fresh --seed. Okay, we should have that column now. And now let's add the code for actually uploading, and it should be similar to the other endpoint. Back to our routes file. It should be similar to what I have commented out here. So let's grab this, paste it in here. And we also want the conditional check here.
So let's grab this, paste it in here. And we also want the conditional check here. So if there is an ImageUploadFilePond, then go ahead and try to upload that file. Let's put this in here, ImageUploadFilePond. Let's comment this back in, close that out. And this time we don't need this, we can just update the announcement. So let's grab this. Let's put this in here. We also need the announcement. So let's grab this as well.
We also need the announcement. So let's grab this as well. Put that right here. And we're updating the ImageUploadFilePond field. So we can just grab this and paste it here for our fields. And now it's ImageUploadFilePond. And the path is correct. So let me just delete this, save this. Let me just delete this folder here, so I don't get confused. Let's delete this.
And we do get the correct image in here. And of course, we can display that in the actual announcement page here. So let's do that. So within announcement.blade.php, let's just duplicate this one. So the first one will be the original one, and the second one will be the one from FilePond. So let me just select these. Image Upload FilePond, okay. Does that show? It does. Cool.
Handling Temporary Uploads11:02
It does. Cool. Okay, this is fine. And like I said, the image is still the full-size. We'll take a look at resizing that on the client in a second. But first, let's go back here. We don't always have the option to associate an existing model with the image that's uploaded right away. So say for example, this was a create form for creating a new Post, and you wanted to associate an image with that Post.
So say for example, this was a create form for creating a new Post, and you wanted to associate an image with that Post. So we add a title, we add our content, and now we want to make use of FilePond to add an image. So at this point, the Post model is not created yet. So when we go to upload a file, it can't associate it with that model. So in those cases, when you don't have access to a model yet, it's still going to upload the file somewhere on your server, but you have to put it in a temporary location. And once you do that, FilePond is going to add a hidden input on the form here with the location of that image.
And once you do that, FilePond is going to add a hidden input on the form here with the location of that image. And then once you hit submit to create that BlogPost, then you can move that file from the temporary location to the actual location you want it and also associate it with the newly created model. So let's see if we can do it that way. So I'm going to change the location. So within editAnnouncement, or sorry, or else web, instead of storing it in images, but we store it in temp, or TMP for now. And at this point, we don't even need to update the database.
but we store it in temp, or TMP for now. And at this point, we don't even need to update the database. So let's get rid of these two lines. So all we're doing here is uploading to a temporary location. But now we actually want to return the path here, so say return $path. And after we do this, FilePond is going to store this. So for example, it's going to store TMP/image.jpeg, it's going to store this as a hidden field on the form. So we know where this image is. And then we can move it from the temporary location to the actual location after we submit.
So back to our browser. Let's upload a new image here, stick with the same one. So open that up. Okay, that's uploading. And now it's done. So open up DevTools here. And if you drill down, you can see we have this new hidden field on the form. It's named imageUploadFilePond, and the value is what we returned in that method. So in this case, the location of the file. So it's tmp-kux.png.
So in this case, the location of the file. So it's TMP KUX.png. So that should be the location of our new file. So there it is TMP KUX. So now when we hit updateAnnouncement, we should have access to this value here. So we know where to move the file. So just to make that clear, let's go to our actual endpoint that handles the form submission. So this one right here. And let's just dd(request()->all()) for dd(request()->all()) okay. So let's go through that process again.
And let's just die and dump request all for dd request all okay. So let's go through that process again. That's hard refresh this. Let me just close DevTools here. Let's browse, select that file again. Let's upload that. And let's go ahead and submit this form. So we should have a new field that has the location of this file. And we do right here, it's image upload FilePond, but it looks like I have too much information here.
And we do right here, it's image upload FilePond, but it looks like I have too much information here. So all this extra stuff looks like it has to do with Laravel debug bar, and it looks like it's interfering with FilePond. So let me try to disable that. Let's go to our .env and say debug_bar_enabled equals false. And let's try that again. So let's go back here. The debug bar should be gone now. And let's try uploading one more time.
The bug bar should be gone now. And let's try uploading one more time. And let's see if the FilePond upload only has the information about the location of this file. And now it's better. So after we hit submit, we can move this file from this location into the actual location we want it and then associate it with our model. So let's go ahead and do that. Let's say imageUpload FilePond should be a string. So let's add some validation for that.
Let's say imageUpload FilePond should be a string. So let's add some validation for that. So within our validation rules, within our endpoint here, let's add that after imageUpload should be a string. And let's say nullable as well. Let's remove our request all up here. And let's do almost the same thing that we're doing in here. So let me grab this. Let's put that underneath here. So this is the original one.
Let's put that underneath here. So this is the original one. Let's put it right here. If image upload FilePond, we no longer need to upload it because it's already in a temporary location. So let's get rid of this. So let's grab the fileName. So we'll say newFileName. And we'll make use of the string helpers. So string after.
And we'll make use of the string helpers. So string after. So let's grab all of this. Let's paste that in. And we only want the portion after the tmp folder. So we'll say tmp /. So the request image upload FilePond should be a string like this. So tmp / file name .png or whatever. And we only want this section here. So that's what this new fileName is.
And we only want this section here. So that's what this new file name is. Let's make sure to import str. Okay, now we want to move the old file to the new location. So we can say, or we can make use of the Storage facade, Storage::move, the first param is the old location. So in this case, $request->file('image')->store('FilePond') is the old location. And the new location is wherever we want it to go. In this case, we want it to be, actually, let's specify the public disk here. So we'll say Storage::disk('public'), okay, and the location should be in images/new.
In this case, we want it to be, actually, let's specify the public disk here. So we'll say storage disk public, okay, and the location should be in images/new_file_name. Okay. Make sure to import the Storage facade. And now we want to update our fields. So let's grab this, paste that in here. Let's uncomment it. It's now imageUpload FilePond, and it's the same value as this. And you can store this in a variable if you like, or you can just duplicate it here.
It's now image upload FilePond, and it's the same value as this. And you can store this in a variable if you like, or you can just duplicate it here. Okay, so let's see if this works. Let me save this. Again, we're going to delete the temp folder. And let's try this out one more time. So back to the browser, let's hard refresh. Let's upload a file. Let's upload this one again. And that's uploading that should go into our temp folder.
Let's upload this one again. And that's uploading that should go into our temp folder. Let's check that first. There it is. Okay. So W8L, let's go ahead and submit. That should move the file. So if we go back here, you'll see the temp folder is empty, because it moved it into the images folder. And it is the same file.
the images folder. And it is the same file. Cool. And we can check our database to make sure it is the correct value in image upload FilePond. And it is cool. So it should show here and also within here. There it is. Cool. And the last thing I want to take a look at is resizing this image on the client. So in the last video, we did this on the server, which is fine.
Client-Side Image Resizing18:08
And the last thing I want to take a look at is resizing this image on the client. So in the last video, we did this on the server, which is fine. But that can take up resources if a lot of people are doing it. If you do this for a client side, then it doesn't take up any server resources. So let's see how we can do that. The plugin is named imageResize or something like that. So imageResize. But this requires the imageTransform plugin. Let's install that first. So again, we'll make use of the CDN.
Let's go ahead and install image-resize. So again, the CDN here, this one here. Paste that right here. Let's register the plugin here. And let's take a look at the options. So we can specify a width. And if we leave the height, it will just try to predict it from the width. Let's change the imageResize mode to contain and let's say imageResizeUpscale to false. So this will prevent upscaling. So let's set those properties on our config here.
So this will prevent upscaling. So let's set those properties on our config here. So the first one was imageResizeTargetWidth. So let's say let's resize our large image to 800 pixels. Next one is the mode. Let's say contain for this one. So this will sort of force it to the width you specify, but also maintain the aspect ratio. And let's make sure if we upload an image that's smaller than 800 in this case, we do not want to upscale it.
And let's make sure if we upload an image that's smaller than 800 in this case, we do not want to upscale it. Let's say false. And that should be it. Hopefully, if I did this right, the image we select should be processed on the client side. So let's save that. Back to our app. Let's go back here. Actually, I'm going to delete this images and temp folders.
There it is within the images folder. And it is the correct size. So yeah, if you want a better experience when it comes to uploading files, definitely make use of FilePond and all of the features and plugins that it has to offer. So as always, let's go ahead and make a commit here. Say git add, git commit. This is episode six. Let's say FilePond file upload.
