Need Dynamic Chart Params0:00
So we have our chart in place and this is fine if this is the only data you want to show. However, you'll often find that you want to pass params to your chart and have the data update accordingly as you change those params. So in this case, for example, if we wanted to change the years, we want the data to update accordingly. So there are a few ways we can do this, we can just provide another graph underneath, if you like. We can provide a query string for the year and have the graph update accordingly, depending on that query string, but that would require a full page refresh. And if your chart was somewhere on the bottom of the page, it would scroll back up to the top of the page, which is not the best user experience. Or we can have some sort of drop down here, and we can select the year. And as we do, the chart updates accordingly. So this would require some sort of Ajax request. And we can
Or we can have some sort of drop down here, and we can select the year. And as we do, the chart updates accordingly. So this would require some sort of Ajax request. And we can do this using JavaScript. Say, for example, a Vue component is probably a library that wraps chart.js and has support for updating the chart. So you could take this approach. And I would definitely do this if I were using something like Inertia with Vue. The other approach is to make use of Livewire as well as Alpine, which is what we'll do here. So I would take this approach if my app was mostly in Blade, and I needed some sort of Ajax functionality. So let's go ahead and do that. So before we install Livewire, let me just make a quick update here. I actually do want to put this year into a query scope. So let's go ahead and do that. So let me copy this. Let's put it on the same line, we can get rid of query here. And let's call the query scope getYear.
Add Year Query Scope1:10
put this year into a query scope. So let's go ahead and do that. So let me copy this. Let's put it on the same line, we can get rid of query here. And let's call the query scope getYearOrders, getYearOrders. And we'll pass in the current year. So date, y? And we can do the same for last year orders as well. But the year should be last year. So let's say minus one here. Okay, let's go to our Order model. And let's add that query scope. So I'm just going to duplicate this. I named it getYearOrders. So let's change this, getYearOrders takes in a year parameter here. And we can get rid of all of this and paste in what I have in my clipboard. And this should still work. So let's give that a try. Chart still works. And I forgot to update the year here should be the year being passed in. Okay. Now let's go ahead and install Livewire. So we'll convert most of our chart code into a Livewire component and also an Alpine component.
Install Livewire Component2:09
should be the year being passed in. Okay. Now let's go ahead and install Livewire. So we'll convert most of our chart code into a Livewire component and also an Alpine component. But we'll start with Livewire here. So let's composer require it. Okay, let's add the Livewire styles and scripts. So I'll put this in our app layout. So I'll put the styles right here, and the scripts down here. Okay, scripts. And let's go ahead and make a new Livewire component. How about we name it ChartOrders. So php artisan Livewire make ChartOrders. And for now, how about we just move over some of our code in our blade view into that Livewire component. So we'll start with this, but we'll eventually move the count of orders in there too. So let's start with this. Let's cut it out. Let's say Livewire ChartOrders. Okay,
Add Year Dropdown3:02
component. So we'll start with this, but we'll eventually move the count of orders in there too. So let's start with this. Let's cut it out. Let's say Livewire chart orders. Okay, let's save that. Let's go to our Livewire component. Let's go ahead and paste this in. Let me just reformat this. Okay, let's save that. Everything should still work. We just moved it into the Livewire component. Okay, let's start by adding a dropdown for our years here. So we'll go here, and we'll add it above our canvas element. So let's make a select. And I don't even think we need the name and ID, because we're using Livewire here, but we'll add one anyways, selected here, and same for the ID. So we will make use of Livewire here. But for now, let's just add some options. So let's say option, value are the different years here. So I'll add the current year.
So we will make use of Livewire here. But for now, let's just add some options. So let's say option, value are the different years here. So I'll add the current year. And that should show a select. Actually, I'm going to put a class on this as well, of border. Okay. Okay, there it is. Let's just put a label beside it. So I'll say span year. And we can hard code a few years in here, but I'm going to make it a bit more declarative and make this an array in our Livewire component. And we'll loop over them here. So say foreach, let's name it availableYears as year. And we can move this into the loop. And we can update this with the year. Okay. So let's go into our Livewire component and add this variable availableYears. So chartOrders. And this doesn't have to be reactive state. So I'll just add it here. And then we'll pass it into the component. So this is going to be an array.
Integrate Alpine with Chart4:43
this variable available years. So chart orders. And this doesn't have to be reactive state. So I'll just add it here. And then we'll pass it into the component. So this is going to be an array of years. So let's say dateY for the current year. And we'll add maybe three more years here. So minus one, minus two, and minus three. That should be fine. And there should be quotes around the y's here. Okay, let's pass that into our component. So availableYears is this variable. And this should render the four years. There we go. Okay, now let's install Alpine and move over our chart.js code into that. And then we'll work on communicating between Alpine and LiveWire. So let's install Alpine here with this script tag. So I'll grab this one here. And I'll put it in our layout as well. So appLayout. And this can go at the top. So put it right here. Okay, let's go back into our LiveWire component. And we're also going to make this an
And I'll put it in our layout as well. So app layout. And this can go at the top. So put it right here. Okay, let's go back into our Livewire component. And we're also going to make this an Alpine component. So let me just reformat this. And let's provide the x-data attribute to initialize this as an Alpine component. So let's say x-data equals, and it's an object. Okay. And I'm going to make use of the init method here. You can also make use of x-init. But you can do it this way as well if you want to run some code and also provide some reactive Alpine state. So let's grab all of our chart.js code within our charts.blade.php. So basically all of this. So let me just copy this, delete this, we'll leave the important here. Let's go to our Alpine component. Let's go ahead and paste this in. We don't need these script tags anymore. And as a side note, you can see I do have syntax highlighting within my Alpine component.
Let's go ahead and paste this in. We don't need these script tags anymore. And as a side note, you can see I do have syntax highlighting within my Alpine component. And if you're using VS Code, make sure you install this Alpine.js syntax highlighting plugin. Okay, let's go ahead and save this. This data is still coming from our controller, or our routes file in our case, but we'll move it into Livewire in a second. All of this is still fine. Let me just make this one line, but I'm going to make one change here. And instead of using getElementById, we'll make use of refs. So we can say this.$refs. And we'll make a ref named canvas. Okay. And for our canvas element down here, let's name it canvas. So x-ref equals canvas. And hopefully I did everything correctly. And this should still work. Let's refresh. And we actually don't have access to this variable right here. And also this
Move Data Into Livewire7:27
canvas. So xRef equals canvas. And hopefully I did everything correctly. And this should still work. Let's refresh. And we actually don't have access to this variable right here. And also this one. So let's move it from our routes file into our Livewire component. So let's go back to our routes file. Let's move these two into our Livewire component instead. So I'm going to remove these two. We don't need to pass it in anymore. Okay. And let's go to our ChartOrders. Let's define them as public properties up here, because we do want this to change. So let's say public $thisYearOrders. And also one for $lastYearOrders. And let's make a mount method, which is sort of like the constructor for Livewire components. mount. And we want to initialize these two variables. But I'm going to call a method for that. So this, let's name it updateOrdersCount. Okay, let's go ahead and make that method here. updateOrdersCount. No params. And let's paste
But I'm going to call a method for that. So this, let's name it updateOrdersCount. Okay, let's go ahead and make that method here. updateOrdersCount. No params. And let's paste in what I have here. Okay, let's save that. This should be the instance variable now. So this, this $yearOrders and same for this one. And let's make sure to import Order. Okay, hopefully that should fix our issue. Let's save that back into here. And now it's complaining because we can no longer sum up the orders, which is still in the normal Blade view. So let's actually move this in here into the Livewire component. So into here. So let me just put that right here. Let's save that. And let's give it another try. Refresh. And our chart is back. Okay, now we also need a piece of state in our Livewire component that keeps track of the selected year. So let's add that back to here. Let's add one for selected.
Refresh. And our chart is back. Okay, now we also need a piece of state in our Livewire component that keeps track of the selected year. So let's add that back to here. Let's add one for selectedYear. And let's give it a default value of the current year. So let's say this selectedYear is date('Y') for the current year. And we want this to update as we change the value in the drop down. So as we change this, we want the variable to update. So we can put a wire:model on the select. So within here, we can say wire:model equals selectedYear. And now every time we update the year, this variable should be updated. And we want our counts to update as well. So instead of using date('Y'), we're going to use selectedYear. So let's grab this and say this selectedYear. Okay. And let's go ahead and save that. But you'll notice when I change the year in the drop down, let me just scroll down a bit. You'll see that the page jumps up back to the top. So Livewire
Entangle State and Wire Ignore10:18
Okay. And let's go ahead and save that. But you'll notice when I change the year in the drop down, let me just scroll down a bit. You'll see that the page jumps up back to the top. So Livewire is doing some DOM diffing here. And whenever it detects changes, it tries to update the Livewire component. So that's what's causing this to sort of jump up to the top. And we can make this work actually had it working with the chart updating, but it kept jumping up to the top, which was not the best user experience. So we can get around that by wire ignoring the changes and just making use of Alpine for most of the dynamic data. So how about we define the same state we have in our Livewire component in our Alpine component. So selectedYear, thisYearOrders, and lastYearOrders. Let's define that in our Alpine component. So let's go back to chartOrders. And remember up here we have our xData, we can define our state here. So this is going to be reactive state.
orders. Let's define that in our Alpine component. So let's go back to chart orders. And remember up here we have our x-data, we can define our state here. So this is going to be reactive state. So let's say selectedYear, lastYearOrders and thisYearOrders. So let me just put something here for now. Let's say lastYearOrders and thisYearOrders. So what we want to do here is synchronize this state with the state in the Livewire components. So we can make use of the entangle directive to do that. So whenever the state changes, for example, in Livewire, it will automatically be synchronized to the state in Alpine. So it goes both ways. So let's make use of the entangle directive to do that. So say entangle or @entangle. And we want to synchronize it to the variable on the back end or on the Livewire side, name the same thing. So selectedYear. So now they should be synchronized whenever they change. So let's do the same thing for
it to the variable on the back end or on the Livewire side, name the same thing. So selectedYear. So now they should be synchronized whenever they change. So let's do the same thing for our orders here. And this one as well. So let me save this. And to make this more clear, let's just output the selectedYear underneath the dropdown here. So underneath our select, let's add a div. Let's say selected. And we can use the Livewire variable here. So we can say selectedYear. And that would work. But like I said, I'm actually going to wire ignore this Livewire component. So we don't get that issue of the page scrolling back to the top. So let me just refresh this. There's a selectedYear. And again, if I scroll down here, it will update, but it's going to scroll back to the top, which we're trying to avoid. And it did update, but it scrolled back.
There's a selected year. And again, if I scroll down here, it will update, but it's going to scroll back to the top, which we're trying to avoid. And it did update, but it scrolled back to the top. So since we use entangle here, this variable should be synchronized with the Alpine state. So let's do that instead. So let's say span here, x-text equals selectedYear. And how about we wire:ignore everything as well. So we no longer get that issue of the component scrolling back to the top after we make a change. So wire:ignore. Okay, save that. Let's refresh this. Let's scroll down a bit. And now it should still work, but it will no longer scroll back to the top. Cool. Let's update this as well to reflect the year that's selected. And also these labels here. If the year is 2020, like it is now, it should say 2020 orders instead of last year and this year. So let's start with this one here. Let's look for last year, the labels here. So
Emit Event and Update Chart15:16
where we have wire:model. So as we change the year, this selected year variable in our class gets updated with the selected year. But we also want to make sure that we update the ordersCount whenever the year changes. And you can see the query is using the selected year to grab that data. So we want to put a wire:change on this. So wire:change. And we want to call that method. So again, we're updating the selected year with wire:model. But we also want to call this updateOrdersCount method as we change the year as well. So let's say, updateOrdersCount. But that's still not enough to update our chart here. So we actually have to do that manually. So we can do that by emitting an event from within our class here. So after it updates, let's emit an event. And we can listen for it in our JavaScript or in our Alpine component, and then update the chart accordingly. So let's say this emit an event, let's call it update the
let's emit an event. And we can listen for it in our JavaScript or in our Alpine component, and then update the chart accordingly. So let's say this emit an event, let's call it updateChart. And if you want to pass data, you can add it as an array here. And the data we need access to are these two variables here. But remember, we're using entangle here. So we actually don't need to pass that data in. So again, you don't remember, we're using entangle up here for these pieces of state. So we can just grab it from here directly. And you can see our data is grabbing it from the livewire variable, we actually want to make use of these variables here. So this lastYearOrders, and same for this one, but for this year. So now we can listen for that event anywhere within this init method. So I will put it down here after we initialize our chart. And to listen, we can say livewire.on. And this is part of livewire's JavaScript,
anywhere within this init method. So I will put it down here after we initialize our chart. And to listen, we can say Livewire.on. And this is part of Livewire's JavaScript, we can listen for that event called updateChart. And if we were accepting data, we could accept it here and use it accordingly. But like I said, since we're using entangle, we don't need to accept that data. So we'll just make it a method or a callback. And for now, there's just console.log, updateChart. Okay, let's save this. And let's go through the entire flow again. So let's start in the browser, we have our select here. So that would correspond to our wire:select here, or the wire:model, I mean. So as we change this, this selectedYear property gets updated in the class. So this selectedYear gets updated. But we also call this updateOrdersCount, which updates the order count for this year and last year's orders. Based on the selectedYear,
in the class. So this selected year gets updated. But we also call this updateOrdersCount, which updates the order count for this year and last year's orders. Based on the selected year, we emit an event. And I forgot a semicolon here. And we actually don't need this array here. I'm not sure why there's a red squiggly, but hopefully that should work. So we're emitting that event within our JavaScript. We're listening for that event. Since we're using entangle, we should be able to make use of that data, which we'll do in a second to update the graph. But for now, we're just console.logging updateChart. So let's see if we get that console.log. Let me just refresh here. Let's change the year. And we do get the console.log. So now finally, after all of that, we should be able to update our chart data here to reflect the selected year. So we have this myChart variable up here, which is our chart
console log. So now finally, after all of that, we should be able to update our chart data here to reflect the selected year. So we have this myChart variable up here, which is our Chart.js instance, we can actually drill down into that instance and update the data manually. So let me show you what I mean. So we have myChart. And the config is just an object here. Which has the data which we can make use of. This data property is up here. And is an array of data sets. And this has a data field as well. So this is what we need to update. So back down here, we can say .data, .dataSets. The first one. So this is last year's data, .data again. And at this point, our Alpine state should be updated. So in this case, lastYearOrders. So we can just make use of that. Let's use that. So this .lastYearOrders, let's do the same for thisYearOrders. So let's duplicate this. It's the first one,
last year orders. So we can just make use of that. Let's use that. So this last year orders, let's do the same for this year orders. So let's duplicate this. It's the first one, or the second one in the array. And this is this year orders. And hopefully, with all of that work, our chart should be updated. And actually, we have to call an update method on the chart itself. So my chart.update(). Okay, so let's save that. And hopefully, everything is working. Let's refresh. Let's change the year to last year. And it does change. Cool. And you can see the label is not updating here, we have to do the same thing to update these labels. So let's do that. Let's grab one of these. Let's paste it up here. So instead of the data, we're updating the label here. And it's just going to be this selected year. In this case, it's minus one.
we're updating the label here. And it's just going to be this selected year. In this case, it's minus one orders. Okay, we can do the same for the current year. And hopefully our labels change as well. Let's refresh that. Let's double check if the labels change. And they do. Cool. Let's make sure the data is correct. So if we take a look at this value, 88, it should be the green value of the previous year. And it is cool. And the final thing we have to do is update the sum here. And we already have that variable within our Alpine component. So we just have to sum it up. So that should be down here somewhere, right here. We don't want to make use of the Livewire variable. So we're going to the Livewire variable, but we want to make use of the Alpine one. So let me just reformat this.
somewhere, right here. We don't want to make use of the livewire variable. So we're going to the livewire variable, but we want to make use of the Alpine one. So let me just reformat this. Let's get rid of this php variable. But we have to do the same thing within JavaScript. So we'll make a span, we'll use x-text. And in this case, we just want to sum up last year's orders. So we can just make use of reduce here to do that. So lastYearOrders, not reduce. And we can say a plus b, or sorry, this is a method a, b, and that should return a plus b. And let me just do the same for this year's orders as well. Okay, hopefully I did that correctly. And hopefully the sum should update. 2022 is the default, let's change the year, hopefully the sum changes. And it does cool. Let me just double check that. So 2020 is 1019 orders, I believe I have the query in here. 2020.
2022 is the default, let's change the year, hopefully the sum changes. And it does cool. Let me just double check that. So 2020 is 1019 orders, I believe I have the query in here. 2020. And that's correct. 2019 should be 1003. And everything is working. So yeah, that's how you would make use of Livewire and Alpine along with Chart.js to make your charts more dynamic in order to show more dynamic data to the user. It was quite a bit of steps. But that's just because we had to work with Chart.js and Alpine in order to get everything to work. So yeah, in the next video, we'll take a look at something similar, but simpler, and we only have to make use of Livewire. But for now, let's go ahead and make a commit. Let's git add git commit This is episode two. It's a dynamic charts with Livewire and Alpine.
This is episode two. It's a dynamic charts with Livewire and Alpine.
