This episode is for members only

Sign up to access "Crop and Upload Profile Photos with Livewire" right now.

Get started
Already a member? Sign in to continue
Playing
06. Cropping and dispatching

Transcript

00:00
So next up, we want to listen to the crop event while we're cropping. Grab the position on the x and y-axis that this starts and ends,
00:10
and also grab the crop values. And then when we go ahead and hit that button that we saw from the introduction, we want to pass them back over, or we want to crop the image first of all, grab the image blob, and then we want to pass that back over to this component here,
00:24
so we can fill in a preview of the cropped image. Now, what we're then going to do is go ahead and crop this on the back end, which will go ahead and actually physically resize this image, and then we're good to go. Now, there are a ton of different ways that we could do this.
00:37
We could just crop this with cropper.js and then store the image, but this way is a lot easier. Cropping it on your back end means you're always going to end up with a smaller file. Okay, let's go ahead and get started with this and see what we can do.
00:49
So we're going to come back over to our profile photo modal component, and we're going to set in a crop region in here, and we're going to set that to a default of null. We're not going to define the object down in here,
01:01
because a bit later on in the course, if we cancel this modal off, we don't want a crop region. We just want to keep the image at the size that it's been uploaded and then resize it in a different way.
01:12
So we set the crop region here, and then what we can do is just listen to this crop event. So we can do that directly within the cropper instance that we've created here, and we can listen to this event.
01:24
Let's go ahead and just console log on that event just to see what we get. So let's pull up our console and choose a photo, and let's go ahead and just start to resize this. And as you can see, we get a bunch of events fired,
01:36
and inside of these events within the detail, you can see we get all of the measurements. So we've got the x-axis, the width, so on and so forth. So we can use these to sort of build up this crop region object.
01:50
So let's just start to assign this a new object in here, and we'll set the x-axis, the y-axis, and the width and the height. So let's change all of these over, and then we'll pull all of that data out. Okay, so x is e detail and x,
02:09
and these are all pretty self-explanatory. y, e detail width, and finally e detail and height. Great, so now we have that crop region in there. Let's go down and create a button that when we click this,
02:24
it goes ahead and grabs that cropped image. So since we're using Breeze, we can just go ahead and grab a secondary button component from our components list. If we just look under resources, views, and components,
02:37
this comes with all these components, and we're just using this secondary button here. And let's go ahead and set this to a type of button, and let's go ahead and just style this up really quickly. We'll set a width of full, we'll set justify center,
02:51
and we'll give this a margin top so it sits away from it, and then in here we'll just say done. Okay, let's take a look at what this looks like. And if we just have a look here, there we go.
03:03
Okay, so we've got a little bit of issue with the sizing here. Let's go ahead and just move that outside of that div, because remember this div wrapper needs to determine how cropper works. Okay, great, yeah, that looks fine.
03:16
So when we hit done, we want to take the crop region, crop this, get the blob image back that we can use directly within the browser, and then we want to put that back into the image. So let's go and set an event on this button for when we click it.
03:32
So we'll say X on click, and let's invoke a dispatch cropped image method, and let's go up to the top here within data and define that out. Okay, so to grab the cropped canvas, we want to reference our cropper instance that we have here,
03:49
and we want to say get cropped canvas. We want to convert this to a blob because we want the blob data to put back into the image that we have over here, and inside of here we'll get that blob back.
04:04
So once again, let's just console log out on that data, and let's take a look. Okay, so let's open up our console, hit done once we've cropped this, and there we go. So we have our blob which represents the cropped image that we have here.
04:19
So now what we're going to go ahead and do is using Alpine dispatch, which we can pick up within Livewire, a cropped image ready event, and then the data that we want to pass through to this is the object URL itself, so the actual cropped image itself,
04:36
plus we want to dispatch the cropped region, so we can use these on the back end to resize this. The blob that we're using here is just for display purposes only. We're not going to be storing that in the database or using that to create a file.
04:49
We're going to be dispatching that as a preview, and then we're going to be using the cropped region that we've got from cropper to physically crop this on the back end. So to grab an actual URL from this blob, we use create object URL,
05:05
which is just a native browser way to take that and create out something that we can use in an image, and then we want to grab the crop region and dispatch that as well. Okay, so where are we going to pick up this crop image ready event?
05:18
Well, that's going to be directly in our profile photo field. So let's go ahead and listen for this event inside of here. So let's call the method that we're going to call handle cropped image, kind of makes sense,
05:30
and then let's go ahead and hook into this event with on the attribute, and then say cropped image ready. Now into this, we know we're passing two things. We're passing the cropped blob, which we can use as the preview,
05:45
and the crop regions, which we can use to physically resize this. So I'm just going to go ahead and die dump on these just to make sure we've got everything hooked up properly, and then we can go ahead and move on.
05:56
Okay, let's go ahead and check this out and choose a photo, and let's go ahead and crop this down, hit done, and there we go. Great. So ignore the error that we've got here. That's just because we're dying and dumping.
06:07
We've got the blob here, which we can use to put back into that image field, and we've got all of the cropped regions as well. X and Y are zero because I just cropped this to the very top left, but of course that would change.
06:19
Okay, so finally, let's just go ahead and preview the cropped image just over here. So inside of here, let's ignore the crop regions. Now we're going to cover that in the next episode. Let's set the cropped blob into a string property inside of our component.
06:37
So let's just do that for now. So the crop blob is now going to be that blob image, and now with this, what we can do now that we've got that back is we can come over to our profile photo field component,
06:49
and we can switch this out and do this based on if we have a crop blob, we're going to make that a priority. Otherwise, we're going to grab the temporary URL that we've uploaded. Otherwise, we're going to fall back to our profile photo URL.
07:02
So let's go ahead and just take this out for now, and we'll say if we have a cropped blob, that's the most important thing. We're going to output that cropped blob inside of here. Otherwise, we're going to do everything that we just done inside of another ternary.
07:17
Now it's a little bit messy, and we could create a helper method for this, but I think for something like this, it's not too bad. Okay, let's go over and just try this whole thing out, and we should be done.
07:26
So let's choose a photo. Let's go ahead and crop this. I'm going to crop this slightly down here now, and hit done, and there we go. Now we haven't closed the modal yet, but you can see that that did change
07:38
because we're dispatching that, replacing out the photo, and we can see the cropped preview in there before we go ahead and save this. Okay, so finally, let's go ahead and close that modal. So let's go over to our profile photo modal blade file,
07:52
and then in here, we can dispatch an event to close this. So because we're within that component, we're going to go ahead and use at and this to reference the actual live wire component itself, and then we're going to say close modal,
08:03
and that will invoke the method over on here that exists within this base modal component. So let's go ahead and try this out really quickly, and let's go ahead and crop this down, hit done, and there we go. It gets closed off.
08:18
Now again, just before we go, there are a couple of other things that we can add to this modal component. For example, to prevent people clicking outside to close it, we are going to be dealing with if people do want to close this,
08:29
but I'm going to give you a couple of options here depending on what you want to do. So as an example, what we could do is create out a static function in here called close modal on click away, and that comes from that package, and we can just return false from here,
08:44
or you could have some condition in here if you wanted to. So now what's going to happen is when we click away, and I'm clicking on the outside of here, nothing happens. We can use the escape key, and we're going to be dealing with that scenario a little bit later,
08:58
but there we go. We've cropped this. We have passed this back down to our component, and we're showing a preview of the cropped image.
10 episodes 43 mins

Overview

Using Livewire, Alpine and Cropper.js (or any cropping library), we’ll create an embeddable form field for users (or any other model) to upload profile photos.

The form element will launch a modal, where users can crop and adjust their profile photo, before being able to preview and save the cropped image — or clear everything out and start again.

You’ll learn:

  • How to launch modals in Livewire
  • How to use Cropper.js with Alpine
  • How to resize images on the backend with the spatie/image package
  • How to pass data between Livewire components
Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Comments

No comments, yet. Be the first to leave a comment.