تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Install Vue scaffolding0:00

Okay, let's convert our weather widget to a Vue component so whenever we change the city, it refreshes itself. So note that I am in a new branch here called Vue if you're following along. So let's go ahead and composer require laravel/ui so we can pull in Vue. And before I pull in Vue, make sure to backup your webpack.mix.js or in this case, I'm just going to copy this because when we do the php artisan ui vue command, then this is going to get overwritten. Okay, now we can run php artisan ui vue. And let's add the auth scaffolding even though we're probably not going to use it. And let's run npm install.

And let's add the auth scaffolding even though we're probably not going to use it. And let's run npm install. And now you can see that our webpack file is back to the original. So let's paste in the Tailwind stuff again. Okay. And let's run npm run dev to compile everything. Okay, that's done. Let's see if Vue is working now. So we have this components folder, and we have an Example Component and you can see it being declared here.

Mount Vue in Blade1:02

So we have this components folder, and we have an example component and you can see it being declared here. So let's see if this works. So we have to add, let's go into our welcome.blade.php. And we have to add a wrapper with an ID of app. So Vue can mount itself. So let's put it on this div. Now we have to make sure to import the script file. So I'll put it right here, <script src="js/app.js">. Okay, and let's put the example component right here.

So I'll put it right here, script, source, js, app.js. Okay, and let's put the ExampleComponent right here. So ExampleComponent, and let's close that. Just to see if it renders. And there it is down there. So I'm going to run my watcher here, since we're using Vue now, and we need to compile it every time we make changes. And I'm going to change, actually, let me wait for that to finish first. Okay. So I'm going to change the ExampleComponent to a WeatherComponent, so say, WeatherWidget.

Create WeatherWidget component2:05

Okay. So I'm going to change the example component to a WeatherWidget, so say, WeatherWidget. And let's change the declaration here to WeatherWidget. Okay. And now let's change this down here, or this example component, WeatherWidget. Okay. See if this still works. Okay. So now we have to move everything in the Blade component into our Vue component. So let's do that.

So now we have to move everything in the Blade component into our Vue component. So let's do that. So let's open up our weather widget.blade.php component, so this one, and let's just copy everything here, and let's put it into the Vue component. So it's weather widget.vue. So I'm going to remove this and paste this in. And this doesn't have a single root div, and I'm still using Vue 2 here, so we still need to do that. So I am going to, actually, let me just comment this out for now, and we'll add this later on.

So I am going to, actually, let me just comment this out for now, and we'll add this later on. So now it should be one root div, and we just need to remove all the PHP stuff here, and convert it to Vue. So I'm going to remove the foreach, and this is the day. For this, I'll just hard code this. This is the icon, say, 01D. This is the description for the future weather. This is the high and the low, so let's say 25, let's say 16 for the low. And let's change this to, say, 01D.

Fetch weather with Axios4:40

I thought I commented out. I guess I didn't. So yeah, let's comment out the Blade component. Okay, so now this is all within Vue, and now we want to make the HTTP request within Vue using Axios instead of from within Laravel. So let's convert that over. So back to my Vue component, so WeatherWidget.vue. Let's go and make a mounted hook, or you can do it in the created hook. Let's use this one since it's already here, and I'm going to make a new method here called fetchCurrentWeather, and let's make another one for fetchFutureWeather, and let's do

Let's use this one since it's already here, and I'm going to make a new method here called fetchCurrentWeather, and let's make another one for fetchFutureWeather, and let's do currentWeather first. So I'm going to do methods, fetchCurrentWeather, and I'm going to make use of Axios, which is already installed in Laravel. So I'm going to do axios.get, and we'll grab the URL in a second, and let's just console.log the response here. So let's say then response, console.log response, okay? So let's grab the URL from the routes file. I believe that's where we call the API.

So let's grab the URL from the routes file. I believe that's where we call the API. So yeah, it's in here. So let's grab this. This is the current weather, and let's paste it in here, and I'm going to make it a template string, and for the location, I'm going to make that a piece of state in our Vue component, and for the API key, I'll just grab that and hard code it because we're going to move this to the backend in a second. So let me just paste that in. Location is going to be a piece of state.

Proxy API through backend7:34

Okay, try again. Okay, and now you see we are getting the data back. And here is the information about the weather in here. Okay, so now let's move the logic of calling the weather API to the backend. So like I said before, this is generally what you want to do with APIs that expose an API key, because everything can be seen on the client side. So let's make a new endpoint here, and we'll call it /weather. And we also want to pass in the location. So let's do that, this.location. And this endpoint will be responsible for calling the API.

So let's do that, this.location. And this.endpoint will be responsible for calling the API. So let's go into our routes file, and let's do that. So I'm going to make a new endpoint here, and it's going to do everything in the routes file. Definitely put this in a controller for any real apps. And let's make a new route. Let's call it weather. And I'm just going to use the global request method like I'm using up here, and the location will be the same.

And I'm just going to use the global request method like I'm using up here, and the location will be the same. Actually, let's grab everything here. It's going to be mostly the same. So let's grab these and space it down here. And I just want to return a JSON response. So let's say return response()->json(). And it's going to be the response()->json() from the request. And it's going to be a 200. And let's see if this works.

So what you want to do is maybe make a middleware that only takes requests from the IP of where your app is hosted. So I'm not going to do that here, but you can take that approach to secure your web app. Okay. So now everything is on the front end, and we can start filling in the information. So let's first expand our state here and add a piece of state for the current weather. So that's going to be actual. Let's make it an empty string. Say feels.

Let's make it an empty string. Say feels. Make an empty string as well, one for description. And let's say loading by default, or you can make an empty string as well. And we need one for the icon, and we also need an array for the futureWeather. So let's make it an empty array to start. Okay. So let me save that. And then now we can start populating that data in here. So for the actual weather, you can do this currentWeatherActual equals.

And then now we can start populating that data in here. So for the actual weather, you can do this currentWeather actual equals. And we want to round it just like we did on the back end. And it's response data, data, main temp. So again, that's just what we get here. So response data, main and temp right here and temp. Okay. So I'm not going to make you watch me do it for the rest. So I'll just paste the rest in. So one for feelsLike, description and the icon.

So I'll just paste the rest in. So one for feels like description and the icon. And now we should be able to use this in our template. So up here. So for the current weather, we can do this currentWeather, not actual. So this currentWeather, not actual. Okay. This one will be this currentWeather feels. This will be this currentWeather description. This currentWeather description.

Oh, yes. Sorry. So if you saw this, I added this UC first method, which I'm just copying from php because JavaScript doesn't have one. So we have to add this method. So I'm just going to paste it in. So that should do the trick. There we go. Cool. And there's the icon.

Render future weather forecast13:43

Cool. And there's the icon. Okay. Now we can do the same thing for the futureWeather. So let's start from the front end and make a new route in the back end as well. So let's start here. Say fetchFutureWeather. And let's duplicate this. Let's call it futureWeather. Okay.

Let's call it futureWeather. Okay. And let's call the endpoint futureWeather. And we don't need all of this. And just console.log response. Okay, let's go into our backEnd. And let's add that route. So almost the same thing as this. It's called futureWeather.

It's called future weather. Okay. And we're just copying this. Pretty much the same thing. Actually, I just need the responseFuture. Okay. And this is responseFuture. And that should do it. Let's see if we get a response. Open DevTools.

Let's see if we get a response. Open DevTools. And there we go. We're getting the future weather. So we're interested in data and list. Right here, you see the five results for the next five days. So we just have to assign that in here. So we have to add a new piece of state for futureWeather. So actually, I have that ready. So we can just do this futureWeather = response.data.list.

So actually, I have that ready. So we can just do this futureWeather equals response.data.list. So now we have this futureWeather array. We can loop over that in our futureWeather section down here or up here. Let me re-indent this first. And now we can loop over this using v-for. So let's say weather in futureWeather. And for the key, I guess I'll just use the timestamp. So that's weather.dt. And let's just fill this out for now.

So that's weather.dt. And let's just fill this out for now. I'll convert this to a day in a second. Let's just output it for now. This is the image. And let me just output the URL for now. And again, look at the response coming back. So it'll be weather, weather again. So this will be a weather. Each one of these is the weather variable.

So this will be a weather. Each one of these is the weather variable. So weather, weather again. And it's an array, the first one. So weather, weather zero. And then the icon. Okay, let's do that. So weather.weather, first one, .icon. And for these two, it's just weather.temp.max. And we have to round that as well.

And for these two, it's just weather.temp.max. And we have to round that as well. So let's say math.round, weather.temp.max. Okay, and I'm going to grab this. And let's say the same thing, but for the minimum or the low. Okay, did I do that correctly? We still have some work to do, but let's see if it actually renders it in a loop. It does, cool. And I think I forgot the description.

It does, cool. And I think I forgot the description. So let's add that. Yeah, right here. So it's the same as the icon, but now it's a description. So let's do that. Okay. And I want to use the ucfirst method that I made. So ucfirst.

So UC first. Okay. So now we just need to convert the image or the icon and the timestamp. So let's start with the icon here. So I'm going to say convertToImage. I'm going to make a method like this. And let's add that down here. Actually, let's grab this because that's the URL. And let's say convertToImage. Say icon.

And let's say convert to image. Say icon. And we're just returning this. I'm going to put it in template strings. And the thing I want to replace is this piece right here. So it's a $icon. Okay, let's see if that works. And, oh yeah, it has to be an img tag. So let's change this. So it should be an image.

So let's change this. So it should be an image. source equals this. Let's bind that. Okay. And we can self-close that. See if this works. And it does. Cool. And we can do something similar for the day. So let's make a method called convertToDay for the timestamp.

And we can do something similar for the day. So let's make a method called convertToDay for the timestamp. So right here. convertToDay takes in the timestamp as a parameter. Let's change this or add this method. convertToDay And it takes in a timestamp. And if your app had a lot of processing with dates, then I would definitely pull in a library like Moment, or I like to use one called DateFNS.

then I would definitely pull in a library like Moment, or I like to use one called DateFNS. So it's just a bunch of functions that you can use. But in this case, since we only have this one operation that we need, I am just going to paste some code that I found on Stack Overflow that does what we want. So it just makes a new date instance. And we have this days array of the days we want returned, and it just grabs the correct one. So now this should be correct.

Move Algolia Places to Vue19:47

and it just grabs the correct one. So now this should be correct. And it is. Cool. So now we can re-add Algolia places. Let's do that. Let's go into our welcome.blade.php. And I'm going to grab this code. So I'm going to leave the import for the library. But I'm going to grab all of this code that initializes places here. All of this.

But I'm going to grab all of this code that initializes places here. All of this. And then I am going to comment this out. Because now we're going to do it within view. So I believe the import has to be underneath because we need it first. OK. And let's move this into the mounted hook. So right here above the fetchWeather. So I'm going to paste that in. And we have to re-add the stuff I commented out here.

So I'm going to paste that in. And we have to re-add the stuff I commented out here. So let me re-add this. And then we have to make a root div. So let me just select everything here. And let's put a root div here. OK. And I no longer want to do the query string stuff, so we can remove this stuff here. OK.

And it still works. So now when I select one of these, I want two things to happen. I want the location to change. And I want the API to run again. So in our case, we want the two methods, fetchCurrentWeather and fetchFutureWeather to run again. So we already have this piece of state for location. So all we have to do is within this callback, we have to update that piece of state. So I'm going to move this, too,

we have to update that piece of state. So I'm going to move this, too, because that had to do with the query string. So now I just want to set the location. Like I said, we have that piece of state already to e.suggestion.value, which is whatever we selected. But note that since it's using the function keyword here, it's going to change the context of this. And we don't want that to happen.

it's going to change the context of this. And we don't want that to happen. We want this to be the view instance. So to do that, let's just make it an arrow function. Let's do this. OK. And I'm going to move the semicolons here. And let's see if the location changes in our weather widget. So let me refresh. Change this.

So let me refresh. Change this. And it does not change. What did I do wrong? Oh, yeah, sorry. I'm not using it in my template. So let's go ahead and use that location. And this should change as we select a new city. So let me refresh again and say Montreal. And there it is.

Watch location for refresh22:37

So let me refresh again and say Montreal. And there it is. Cool. But now this is not the weather for Montreal. This is still the default weather for

So let's add a watcher here. So let's say watch. And the property I want to watch is location. So let's say watch location. And when that happens or when that changes, then just call those methods. Let's grab these two. And we can paste it in here. And now that should refetch the new information based on the new location. And this should work. And I defined watch incorrectly.

Toggle forecast visibility24:20

So for example, if you want to toggle this futureWeather, since we already have this view component, it should be really easy. So let's quickly do that and then we'll call it a day. So let's add a piece of state called isFutureWeatherVisible. And let's say false by default or make it true. Let's say false. And let's look for that button. So it's this button right here. And let's just say addClick. Let's just say isFutureWeatherVisible is the opposite. Okay.

weather visible is the opposite. Okay. And now for this entire future weather section, we can just do $show equals $isFutureWeatherVisible. And now that should be off or hidden by default. And we can toggle that on or off. Cool. So this is probably one of the most common ways to add interactivity if you like using Vue within Laravel. And I still personally do this a lot in my applications.

to add interactivity if you like using view within Laravel. And I still personally do this a lot in my applications. In the next video, we'll take a look at using Livewire to do this and also adding Alpine for any DOM manipulation.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟