Build reactive data tables with the Angular Component Development Kit (CDK) in this tutorial. Full article   https://medium.com/@zackderose/angular-cdk-tables-1537774d7c99

- Zack DeRose  https://angularfirebase.com/contributors/zack-de-rose/
- CDK Docs https://material.angular.io/cdk/table/overview
- Angular Firebase PRO https://angularfirebase.com/pro
2024-02-04T07:25:55.000Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
3d411304-24ee-4b5b-906d-5a41a13cb6dc
2081a5023cb4e15376e45057f62611f9500316922d8172bbf22315f28ea391b9
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
What if there is a way that you could capture all the benefits of Angular Material, but customize the behavior and styling in an unopinionated way?
Well, that's exactly what Angular's component development kit does.
In today's video, you'll learn how to build a reactive CDK data table that implements its own custom behaviors and also uses Bootstrap could pour for its CSS styling?
If you're new to the channel, make sure to like and subscribe.
And the code for this video is produced by Zach DeRose who is a seen your team lead working on Angular over at Swampfox Inc?
Make sure to check out his full article on Medium because it goes into some advanced stuff that I don't cover could hear such as searching, sorting, and applying styles on a cell by cell basis?
I'm starting out from just a regular Angular 6 app, and the first thing I'll do is install the component development kit which is at angular /cdk?
Then I'll generate a component called table.
From there, I'll jump over to the app module and we'll want to import the data table from Angular CDK, then add the CDK table module to the imports array.
Can?
The first table we'll build is pretty basic and ugly, but what it's doing under the hood is pretty powerful.
And without the CDK, this would take a lot more code than it does in this video.
Go?
I'll be working with some dummy data throughout this video, which I have saved in this data dot ts file.
First, we have an array of column names, which just define the names of the columns in the table?
And then we have the actual data which is a map of various heroes, and each hero has a set of properties that match these column names?
So, basically, this simulates some initial data that you might pull from a back end database or API.
Can now let's jump into the component and start putting together this table.
I'm going to go pretty slow through this code because I wanna talk about behavior subjects can observeables because they're very powerful structures when working with tables?
A behavior subject is really useful when you have a value that you want to manually change over time.
They work just like an observable, but they always have a current value and you can push new values to them?
And you can always get the current value in place, switch means you kind of have the best of both worlds between observables and just regular JavaScript?
What's also really cool is that you can use your behavior subject as a single source truth that gets mapped to other observables?
For example, we'll be able to map this hero's dictionary down to an array of data that we can loop over in our data cable for each row?
And we'll build up to some more advanced use cases with that concept later in the video.
So if you want to take your single source of truth can map it to just a regular observable?
You can do that by just calling pipe and then adding some operators to structure it in the way that you need for the UI.
In this case, we just want to map the dictionary down to an array of values, which we can do with Object dot values.
So now we have an observable array of data that we can loop over in the table?
You may have noticed that I was clicking a button in the table that was changing the values for a given row.
That's also made possible by the reactive nature of behavior subjects and observables.
We can grab the value of our behavior subject by simply calling value on it.
And because it's an object, we can then grab the hero name that's being clicked on and update its values.
To level up the hero, we'll simply increment each one of its properties by 1.
From there, we can compose a new object by using the spread syntax and taking that current value from the behavior subject, then overwrite the value for the clicked hero?
So that'll be the next value for our behavior subject and everything else that depends on it will react accordingly.
And we can simply push that into the stream by calling next?
Now we can jump into the component HTML, and we'll see that the CDK gives us a whole bunch of different could divs that we can use to bind our data to the table?
The most important one is the data source which is that observable that we mapped our behavior subject to in the TypeScript.
The next thing we'll do is define the header row.
And because we already have an array of the column names, we can just pass that in as the CDK header row definition.
After that, we will make a definition for each actual row in the table.
And that's going to automatically loop over every item in our data source array.
Came?
Now the last major step is to define the logic for each cell in the row.
You could loop over each cell or you can define them 1 by 1.
Since we have some custom behavior, we'll just go ahead and declare each one of our cells 1 by 1.
All we have to do is define what the header should look like.
Then we have access to the underlying data object, which is in the template variable of row.
So this cell will have a header of hero name, and then the actual value will be the row name?
Then we'll just go ahead and repeat this logic over and over again until we get to the actual cell that has the clickable button.
The special thing about this cell is that we're not actually displaying a value, but instead we'll have a clickable button that will trigger that level up event handler that we define in the TypeScript.
To level up a hero, we need to know its name, which we have access to through the row template variable, which we can then pass in to our level up method as the argument.
And just like that, we have a data table that relies on a single source of truth for its input, which is a pattern that you really want if you're going to scale up in complex could be?
Just imagine trying to apply the same pattern in plain JavaScript or jQuery.
You'd have a lot more code to write.
But for your end users, this is still a pretty ugly table.
Let's see how we might add some better styling to it.
For that, we'll use Bootstrap 4, but you could use any other CSS framework or your own styles completely.
You can grab the CSS for Bootstrap from the website and then paste it into the head of the document in the index HTML file in Angular?
Then back in the Bootstrap docs, you'll see a variety of different styles for tables.
Pick whichever one you like, and you'll also want a style for the button in that table as well.
So as you might imagine, adding styles to our CDK table is easy as any other HTML table.
We simply add the class name, and we're good to go.
So now we have a table that behaves like Angular Material but looks like Bootstrap.
But I wanna take this a step further, and I want to highlight the hero with the highest and lowest health rating?
And I want that style to be updated reactively whenever the values change in this table.
Let's see how we can leverage our existing behavior subject to handle this for us.
I'm also going to install the max by and min by methods from Lodash to make this code a little bit more concise.
Guys?
These functions are really useful if you have an array of objects and you need to calculate some statistics about a certain property on those objects, which in this case, we want to find the heroes with the min and max health?
From there, we'll go ahead and define a new observable called min max, and this will be tied to our hero source behavior subject.
But this time, we want to map it down to just the 2 heroes, 1 with the min and 1 with the max health.
So what we're doing here is computing a value based on a single source of truth that will update reactively.
Inside of map, we can simply use Lodash to find the hero with the max health and then a hero with the min health?
And then we'll just return the names of those 2 heroes so we can use them in our HTML.
Now Angular has a built in ng class directive that we can use to easily update the styles based on this logic.
We pass ng class an object where the key of that object is the CSS class that we want to apply?
This class is from Bootstrap, which is BG success, which will give the row a green highlight, and then we'll unwrap the min max observable.
And if the max equals this row name, then we'll go ahead and highlight it.
Then we'll do the same exact ping for the min value, except this time we'll apply the bg danger, which will give it a red highlight?
And that's all there is to it.
We now have reactive CSS is being applied to our data table?
If your tables have huge amounts of data, then you'll probably need to paginate it.
So let's look into how we can further leverage RxJS to make a reactive pagination system?
To simplify the UI elements, I'm going to use ng bootstrap, but you could definitely do this from scratch as well.
First will install it via npm, then go into the app module and add it to the imports array there?
It gives us access to a pagination component, and we just need to pass it a few input variables to make it work?
It needs to know the total size of our collection, which is just the length of our data source array.
Then it needs to know how many items we wanna show on each page.
It also needs to know the current page, which will also be a behavior subject when we get to the TypeScript.
And lastly, it needs an event handler, so when the user clicks on a new page, it updates to the correct page.
And a little trick when you're using a behavior subject is instead of writing an event handler, you can just call current page next with that event as long as the event is what you actually need to send in the stream.
And the last change we'll make is set the data source to a new observable called data on pages, which is a slice of the actual values that we wanna show.
So we'll need to add a couple of new properties to our component to make all this work.
The first one is the current page which is a behavior subject, and it's a behavior subject because we want to react to it and we also want to change it dynamically?
From there, we have a data on page observable which will react to changes in the data source of heroes and also the current page.
And lastly, the page size, which is just a number.
The hardest part is defining the slice of data that we want to show for each page.
We need to react to page changes?
So we'll go ahead and pipe an observable that's based off the current page behavior subject.
But the actual data source is the hero's behavior subject so we can use the switch map operator to switch to that data source?
So at this point we know the current page as well as the array of heroes and we just need to map it down to a slice to display on that page.
We can figure out which items to display on the page by taking that current page value, subtracting 1, and then multiplying it by the page size?
That's the starting index.
Then the ending index is just that starting index plus the page size?
And those are the 2 arguments that we'll use to slice the pay?
If we go back to our data table, you'll see that it's only displaying 2 items per page, but it's also maintaining the styling logic that we set up in the previous step?
And again, this is possible because we're using a single data source and having everything else react to it accordingly.
I'm gonna go ahead and wrap things up there.
This video helped you?
Please like and subscribe.
And if you're serious about building Angular apps, consider becoming a pro member at angularfirebase.com.
You'll get a free copy of my book as well as 1 on 1 project support?
Thanks for watching, and I'll talk to you soon.

Speaker 0: What if there is a way that you could capture all the benefits of Angular Material, but customize the behavior and styling in an unopinionated way? Well, that's exactly what Angular's component development kit does. In today's video, you'll learn how to build a reactive CDK data table that implements its own custom behaviors and also uses Bootstrap could pour for its CSS styling? If you're new to the channel, make sure to like and subscribe. And the code for this video is produced by Zach DeRose who is a seen your team lead working on Angular over at Swampfox Inc?

Make sure to check out his full article on Medium because it goes into some advanced stuff that I don't cover could hear such as searching, sorting, and applying styles on a cell by cell basis? I'm starting out from just a regular Angular 6 app, and the first thing I'll do is install the component development kit which is at angular /cdk? Then I'll generate a component called table. From there, I'll jump over to the app module and we'll want to import the data table from Angular CDK, then add the CDK table module to the imports array. Can?

The first table we'll build is pretty basic and ugly, but what it's doing under the hood is pretty powerful. And without the CDK, this would take a lot more code than it does in this video. Go? I'll be working with some dummy data throughout this video, which I have saved in this data dot ts file. First, we have an array of column names, which just define the names of the columns in the table?

And then we have the actual data which is a map of various heroes, and each hero has a set of properties that match these column names? So, basically, this simulates some initial data that you might pull from a back end database or API. Can now let's jump into the component and start putting together this table. I'm going to go pretty slow through this code because I wanna talk about behavior subjects can observeables because they're very powerful structures when working with tables? A behavior subject is really useful when you have a value that you want to manually change over time.

They work just like an observable, but they always have a current value and you can push new values to them? And you can always get the current value in place, switch means you kind of have the best of both worlds between observables and just regular JavaScript? What's also really cool is that you can use your behavior subject as a single source truth that gets mapped to other observables? For example, we'll be able to map this hero's dictionary down to an array of data that we can loop over in our data cable for each row? And we'll build up to some more advanced use cases with that concept later in the video.

So if you want to take your single source of truth can map it to just a regular observable? You can do that by just calling pipe and then adding some operators to structure it in the way that you need for the UI. In this case, we just want to map the dictionary down to an array of values, which we can do with Object dot values. So now we have an observable array of data that we can loop over in the table? You may have noticed that I was clicking a button in the table that was changing the values for a given row.

That's also made possible by the reactive nature of behavior subjects and observables. We can grab the value of our behavior subject by simply calling value on it. And because it's an object, we can then grab the hero name that's being clicked on and update its values. To level up the hero, we'll simply increment each one of its properties by 1. From there, we can compose a new object by using the spread syntax and taking that current value from the behavior subject, then overwrite the value for the clicked hero?

So that'll be the next value for our behavior subject and everything else that depends on it will react accordingly. And we can simply push that into the stream by calling next? Now we can jump into the component HTML, and we'll see that the CDK gives us a whole bunch of different could divs that we can use to bind our data to the table? The most important one is the data source which is that observable that we mapped our behavior subject to in the TypeScript. The next thing we'll do is define the header row.

And because we already have an array of the column names, we can just pass that in as the CDK header row definition. After that, we will make a definition for each actual row in the table. And that's going to automatically loop over every item in our data source array. Came? Now the last major step is to define the logic for each cell in the row.

You could loop over each cell or you can define them 1 by 1. Since we have some custom behavior, we'll just go ahead and declare each one of our cells 1 by 1. All we have to do is define what the header should look like. Then we have access to the underlying data object, which is in the template variable of row. So this cell will have a header of hero name, and then the actual value will be the row name?

Then we'll just go ahead and repeat this logic over and over again until we get to the actual cell that has the clickable button. The special thing about this cell is that we're not actually displaying a value, but instead we'll have a clickable button that will trigger that level up event handler that we define in the TypeScript. To level up a hero, we need to know its name, which we have access to through the row template variable, which we can then pass in to our level up method as the argument. And just like that, we have a data table that relies on a single source of truth for its input, which is a pattern that you really want if you're going to scale up in complex could be? Just imagine trying to apply the same pattern in plain JavaScript or jQuery.

You'd have a lot more code to write. But for your end users, this is still a pretty ugly table. Let's see how we might add some better styling to it. For that, we'll use Bootstrap 4, but you could use any other CSS framework or your own styles completely. You can grab the CSS for Bootstrap from the website and then paste it into the head of the document in the index HTML file in Angular?

Then back in the Bootstrap docs, you'll see a variety of different styles for tables. Pick whichever one you like, and you'll also want a style for the button in that table as well. So as you might imagine, adding styles to our CDK table is easy as any other HTML table. We simply add the class name, and we're good to go. So now we have a table that behaves like Angular Material but looks like Bootstrap.

But I wanna take this a step further, and I want to highlight the hero with the highest and lowest health rating? And I want that style to be updated reactively whenever the values change in this table. Let's see how we can leverage our existing behavior subject to handle this for us. I'm also going to install the max by and min by methods from Lodash to make this code a little bit more concise. Guys?

These functions are really useful if you have an array of objects and you need to calculate some statistics about a certain property on those objects, which in this case, we want to find the heroes with the min and max health? From there, we'll go ahead and define a new observable called min max, and this will be tied to our hero source behavior subject. But this time, we want to map it down to just the 2 heroes, 1 with the min and 1 with the max health. So what we're doing here is computing a value based on a single source of truth that will update reactively. Inside of map, we can simply use Lodash to find the hero with the max health and then a hero with the min health?

And then we'll just return the names of those 2 heroes so we can use them in our HTML. Now Angular has a built in ng class directive that we can use to easily update the styles based on this logic. We pass ng class an object where the key of that object is the CSS class that we want to apply? This class is from Bootstrap, which is BG success, which will give the row a green highlight, and then we'll unwrap the min max observable. And if the max equals this row name, then we'll go ahead and highlight it.

Then we'll do the same exact ping for the min value, except this time we'll apply the bg danger, which will give it a red highlight? And that's all there is to it. We now have reactive CSS is being applied to our data table? If your tables have huge amounts of data, then you'll probably need to paginate it. So let's look into how we can further leverage RxJS to make a reactive pagination system?

To simplify the UI elements, I'm going to use ng bootstrap, but you could definitely do this from scratch as well. First will install it via npm, then go into the app module and add it to the imports array there? It gives us access to a pagination component, and we just need to pass it a few input variables to make it work? It needs to know the total size of our collection, which is just the length of our data source array. Then it needs to know how many items we wanna show on each page.

It also needs to know the current page, which will also be a behavior subject when we get to the TypeScript. And lastly, it needs an event handler, so when the user clicks on a new page, it updates to the correct page. And a little trick when you're using a behavior subject is instead of writing an event handler, you can just call current page next with that event as long as the event is what you actually need to send in the stream. And the last change we'll make is set the data source to a new observable called data on pages, which is a slice of the actual values that we wanna show. So we'll need to add a couple of new properties to our component to make all this work.

The first one is the current page which is a behavior subject, and it's a behavior subject because we want to react to it and we also want to change it dynamically? From there, we have a data on page observable which will react to changes in the data source of heroes and also the current page. And lastly, the page size, which is just a number. The hardest part is defining the slice of data that we want to show for each page. We need to react to page changes?

So we'll go ahead and pipe an observable that's based off the current page behavior subject. But the actual data source is the hero's behavior subject so we can use the switch map operator to switch to that data source? So at this point we know the current page as well as the array of heroes and we just need to map it down to a slice to display on that page. We can figure out which items to display on the page by taking that current page value, subtracting 1, and then multiplying it by the page size? That's the starting index.

Then the ending index is just that starting index plus the page size? And those are the 2 arguments that we'll use to slice the pay? If we go back to our data table, you'll see that it's only displaying 2 items per page, but it's also maintaining the styling logic that we set up in the previous step? And again, this is possible because we're using a single data source and having everything else react to it accordingly. I'm gonna go ahead and wrap things up there.

This video helped you? Please like and subscribe. And if you're serious about building Angular apps, consider becoming a pro member at angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support? Thanks for watching, and I'll talk to you soon.
What if there is a way that you could capture all the benefits of Angular Material, but customize the behavior and styling in an unopinionated way? Well, that's exactly what Angular's component development kit does. In today's video, you'll learn how to build a reactive CDK data table that implements its own custom behaviors and also uses Bootstrap could pour for its CSS styling?
If you're new to the channel, make sure to like and subscribe. And the code for this video is produced by Zach DeRose who is a seen your team lead working on Angular over at Swampfox Inc? Make sure to check out his full article on Medium because it goes into some advanced stuff that I don't cover could hear such as searching, sorting, and applying styles on a cell by cell basis?
youtube
streaming
television
I'm starting out from just a regular Angular 6 app, and the first thing I'll do is install the component development kit which is at angular /cdk? Then I'll generate a component called table. From there, I'll jump over to the app module and we'll want to import the data table from Angular CDK, then add the CDK table module to the imports array. Can? The first table we'll build is pretty basic and ugly, but what it's doing under the hood is pretty powerful. And without the CDK, this would take a lot more code than it does in this video.
Go? I'll be working with some dummy data throughout this video, which I have saved in this data dot ts file. First, we have an array of column names, which just define the names of the columns in the table? And then we have the actual data which is a map of various heroes, and each hero has a set of properties that match these column names? So, basically, this simulates some initial data that you might pull from a back end database or API. Can now let's jump into the component and start putting together this table. I'm going to go pretty slow through this code because I wanna talk about behavior subjects can observeables because they're very powerful structures when working with tables? A behavior subject is really useful when you have a value that you want to manually change over time. They work just like an observable, but they always have a current value and you can push new values to them?
databases
modeling
data
programming
And you can always get the current value in place, switch means you kind of have the best of both worlds between observables and just regular JavaScript? What's also really cool is that you can use your behavior subject as a single source truth that gets mapped to other observables? For example, we'll be able to map this hero's dictionary down to an array of data that we can loop over in our data cable for each row?
data
logic
artificial intelligence
And we'll build up to some more advanced use cases with that concept later in the video. So if you want to take your single source of truth can map it to just a regular observable? You can do that by just calling pipe and then adding some operators to structure it in the way that you need for the UI. In this case, we just want to map the dictionary down to an array of values, which we can do with Object dot values. So now we have an observable array of data that we can loop over in the table?
You may have noticed that I was clicking a button in the table that was changing the values for a given row. That's also made possible by the reactive nature of behavior subjects and observables. We can grab the value of our behavior subject by simply calling value on it.
data
And because it's an object, we can then grab the hero name that's being clicked on and update its values. To level up the hero, we'll simply increment each one of its properties by 1. From there, we can compose a new object by using the spread syntax and taking that current value from the behavior subject, then overwrite the value for the clicked hero?
So that'll be the next value for our behavior subject and everything else that depends on it will react accordingly. And we can simply push that into the stream by calling next? Now we can jump into the component HTML, and we'll see that the CDK gives us a whole bunch of different could divs that we can use to bind our data to the table? The most important one is the data source which is that observable that we mapped our behavior subject to in the TypeScript.
databases
data
The next thing we'll do is define the header row. And because we already have an array of the column names, we can just pass that in as the CDK header row definition. After that, we will make a definition for each actual row in the table.
And that's going to automatically loop over every item in our data source array. Came? Now the last major step is to define the logic for each cell in the row. You could loop over each cell or you can define them 1 by 1. Since we have some custom behavior, we'll just go ahead and declare each one of our cells 1 by 1.
logic
programming
All we have to do is define what the header should look like. Then we have access to the underlying data object, which is in the template variable of row. So this cell will have a header of hero name, and then the actual value will be the row name? Then we'll just go ahead and repeat this logic over and over again until we get to the actual cell that has the clickable button. The special thing about this cell is that we're not actually displaying a value, but instead we'll have a clickable button that will trigger that level up event handler that we define in the TypeScript. To level up a hero, we need to know its name, which we have access to through the row template variable, which we can then pass in to our level up method as the argument.
And just like that, we have a data table that relies on a single source of truth for its input, which is a pattern that you really want if you're going to scale up in complex could be? Just imagine trying to apply the same pattern in plain JavaScript or jQuery. You'd have a lot more code to write. But for your end users, this is still a pretty ugly table. Let's see how we might add some better styling to it. For that, we'll use Bootstrap 4, but you could use any other CSS framework or your own styles completely. You can grab the CSS for Bootstrap from the website and then paste it into the head of the document in the index HTML file in Angular?
data
fashion
Then back in the Bootstrap docs, you'll see a variety of different styles for tables. Pick whichever one you like, and you'll also want a style for the button in that table as well. So as you might imagine, adding styles to our CDK table is easy as any other HTML table. We simply add the class name, and we're good to go. So now we have a table that behaves like Angular Material but looks like Bootstrap. But I wanna take this a step further, and I want to highlight the hero with the highest and lowest health rating? And I want that style to be updated reactively whenever the values change in this table. Let's see how we can leverage our existing behavior subject to handle this for us. I'm also going to install the max by and min by methods from Lodash to make this code a little bit more concise. Guys? These functions are really useful if you have an array of objects and you need to calculate some statistics about a certain property on those objects, which in this case, we want to find the heroes with the min and max health?
From there, we'll go ahead and define a new observable called min max, and this will be tied to our hero source behavior subject. But this time, we want to map it down to just the 2 heroes, 1 with the min and 1 with the max health. So what we're doing here is computing a value based on a single source of truth that will update reactively.
logic
Inside of map, we can simply use Lodash to find the hero with the max health and then a hero with the min health? And then we'll just return the names of those 2 heroes so we can use them in our HTML. Now Angular has a built in ng class directive that we can use to easily update the styles based on this logic. We pass ng class an object where the key of that object is the CSS class that we want to apply? This class is from Bootstrap, which is BG success, which will give the row a green highlight, and then we'll unwrap the min max observable. And if the max equals this row name, then we'll go ahead and highlight it. Then we'll do the same exact ping for the min value, except this time we'll apply the bg danger, which will give it a red highlight? And that's all there is to it. We now have reactive CSS is being applied to our data table? If your tables have huge amounts of data, then you'll probably need to paginate it. So let's look into how we can further leverage RxJS to make a reactive pagination system? To simplify the UI elements, I'm going to use ng bootstrap, but you could definitely do this from scratch as well. First will install it via npm, then go into the app module and add it to the imports array there? It gives us access to a pagination component, and we just need to pass it a few input variables to make it work? It needs to know the total size of our collection, which is just the length of our data source array. Then it needs to know how many items we wanna show on each page. It also needs to know the current page, which will also be a behavior subject when we get to the TypeScript. And lastly, it needs an event handler, so when the user clicks on a new page, it updates to the correct page.
And a little trick when you're using a behavior subject is instead of writing an event handler, you can just call current page next with that event as long as the event is what you actually need to send in the stream. And the last change we'll make is set the data source to a new observable called data on pages, which is a slice of the actual values that we wanna show. So we'll need to add a couple of new properties to our component to make all this work. The first one is the current page which is a behavior subject, and it's a behavior subject because we want to react to it and we also want to change it dynamically? From there, we have a data on page observable which will react to changes in the data source of heroes and also the current page. And lastly, the page size, which is just a number. The hardest part is defining the slice of data that we want to show for each page.
data
data management
data analysis
modeling
We need to react to page changes? So we'll go ahead and pipe an observable that's based off the current page behavior subject. But the actual data source is the hero's behavior subject so we can use the switch map operator to switch to that data source? So at this point we know the current page as well as the array of heroes and we just need to map it down to a slice to display on that page.
We can figure out which items to display on the page by taking that current page value, subtracting 1, and then multiplying it by the page size? That's the starting index. Then the ending index is just that starting index plus the page size? And those are the 2 arguments that we'll use to slice the pay?
earnings
If we go back to our data table, you'll see that it's only displaying 2 items per page, but it's also maintaining the styling logic that we set up in the previous step? And again, this is possible because we're using a single data source and having everything else react to it accordingly.
data
data management
I'm gonna go ahead and wrap things up there.
This video helped you? Please like and subscribe. And if you're serious about building Angular apps, consider becoming a pro member at angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support? Thanks for watching, and I'll talk to you soon.
youtube
What if there is a way that you could capture all the benefits of Angular Material, but customize the behavior and styling in an unopinionated way? Well, that's exactly what Angular's component development kit does. In today's video, you'll learn how to build a reactive CDK data table that implements its own custom behaviors and also uses Bootstrap could pour for its CSS styling? If you're new to the channel, make sure to like and subscribe. And the code for this video is produced by Zach DeRose who is a seen your team lead working on Angular over at Swampfox Inc? Make sure to check out his full article on Medium because it goes into some advanced stuff that I don't cover could hear such as searching, sorting, and applying styles on a cell by cell basis? I'm starting out from just a regular Angular 6 app, and the first thing I'll do is install the component development kit which is at angular /cdk? Then I'll generate a component called table. From there, I'll jump over to the app module and we'll want to import the data table from Angular CDK, then add the CDK table module to the imports array. Can? The first table we'll build is pretty basic and ugly, but what it's doing under the hood is pretty powerful. And without the CDK, this would take a lot more code than it does in this video. Go? I'll be working with some dummy data throughout this video, which I have saved in this data dot ts file. First, we have an array of column names, which just define the names of the columns in the table? And then we have the actual data which is a map of various heroes, and each hero has a set of properties that match these column names? So, basically, this simulates some initial data that you might pull from a back end database or API. Can now let's jump into the component and start putting together this table. I'm going to go pretty slow through this code because I wanna talk about behavior subjects can observeables because they're very powerful structures when working with tables? A behavior subject is really useful when you have a value that you want to manually change over time. They work just like an observable, but they always have a current value and you can push new values to them? And you can always get the current value in place, switch means you kind of have the best of both worlds between observables and just regular JavaScript? What's also really cool is that you can use your behavior subject as a single source truth that gets mapped to other observables? For example, we'll be able to map this hero's dictionary down to an array of data that we can loop over in our data cable for each row? And we'll build up to some more advanced use cases with that concept later in the video. So if you want to take your single source of truth can map it to just a regular observable? You can do that by just calling pipe and then adding some operators to structure it in the way that you need for the UI. In this case, we just want to map the dictionary down to an array of values, which we can do with Object dot values. So now we have an observable array of data that we can loop over in the table? You may have noticed that I was clicking a button in the table that was changing the values for a given row. That's also made possible by the reactive nature of behavior subjects and observables. We can grab the value of our behavior subject by simply calling value on it. And because it's an object, we can then grab the hero name that's being clicked on and update its values. To level up the hero, we'll simply increment each one of its properties by 1. From there, we can compose a new object by using the spread syntax and taking that current value from the behavior subject, then overwrite the value for the clicked hero? So that'll be the next value for our behavior subject and everything else that depends on it will react accordingly. And we can simply push that into the stream by calling next? Now we can jump into the component HTML, and we'll see that the CDK gives us a whole bunch of different could divs that we can use to bind our data to the table? The most important one is the data source which is that observable that we mapped our behavior subject to in the TypeScript. The next thing we'll do is define the header row. And because we already have an array of the column names, we can just pass that in as the CDK header row definition. After that, we will make a definition for each actual row in the table. And that's going to automatically loop over every item in our data source array. Came? Now the last major step is to define the logic for each cell in the row. You could loop over each cell or you can define them 1 by 1. Since we have some custom behavior, we'll just go ahead and declare each one of our cells 1 by 1. All we have to do is define what the header should look like. Then we have access to the underlying data object, which is in the template variable of row. So this cell will have a header of hero name, and then the actual value will be the row name? Then we'll just go ahead and repeat this logic over and over again until we get to the actual cell that has the clickable button. The special thing about this cell is that we're not actually displaying a value, but instead we'll have a clickable button that will trigger that level up event handler that we define in the TypeScript. To level up a hero, we need to know its name, which we have access to through the row template variable, which we can then pass in to our level up method as the argument. And just like that, we have a data table that relies on a single source of truth for its input, which is a pattern that you really want if you're going to scale up in complex could be? Just imagine trying to apply the same pattern in plain JavaScript or jQuery. You'd have a lot more code to write. But for your end users, this is still a pretty ugly table. Let's see how we might add some better styling to it. For that, we'll use Bootstrap 4, but you could use any other CSS framework or your own styles completely. You can grab the CSS for Bootstrap from the website and then paste it into the head of the document in the index HTML file in Angular? Then back in the Bootstrap docs, you'll see a variety of different styles for tables. Pick whichever one you like, and you'll also want a style for the button in that table as well. So as you might imagine, adding styles to our CDK table is easy as any other HTML table. We simply add the class name, and we're good to go. So now we have a table that behaves like Angular Material but looks like Bootstrap. But I wanna take this a step further, and I want to highlight the hero with the highest and lowest health rating? And I want that style to be updated reactively whenever the values change in this table. Let's see how we can leverage our existing behavior subject to handle this for us. I'm also going to install the max by and min by methods from Lodash to make this code a little bit more concise. Guys? These functions are really useful if you have an array of objects and you need to calculate some statistics about a certain property on those objects, which in this case, we want to find the heroes with the min and max health? From there, we'll go ahead and define a new observable called min max, and this will be tied to our hero source behavior subject. But this time, we want to map it down to just the 2 heroes, 1 with the min and 1 with the max health. So what we're doing here is computing a value based on a single source of truth that will update reactively. Inside of map, we can simply use Lodash to find the hero with the max health and then a hero with the min health? And then we'll just return the names of those 2 heroes so we can use them in our HTML. Now Angular has a built in ng class directive that we can use to easily update the styles based on this logic. We pass ng class an object where the key of that object is the CSS class that we want to apply? This class is from Bootstrap, which is BG success, which will give the row a green highlight, and then we'll unwrap the min max observable. And if the max equals this row name, then we'll go ahead and highlight it. Then we'll do the same exact ping for the min value, except this time we'll apply the bg danger, which will give it a red highlight? And that's all there is to it. We now have reactive CSS is being applied to our data table? If your tables have huge amounts of data, then you'll probably need to paginate it. So let's look into how we can further leverage RxJS to make a reactive pagination system? To simplify the UI elements, I'm going to use ng bootstrap, but you could definitely do this from scratch as well. First will install it via npm, then go into the app module and add it to the imports array there? It gives us access to a pagination component, and we just need to pass it a few input variables to make it work? It needs to know the total size of our collection, which is just the length of our data source array. Then it needs to know how many items we wanna show on each page. It also needs to know the current page, which will also be a behavior subject when we get to the TypeScript. And lastly, it needs an event handler, so when the user clicks on a new page, it updates to the correct page. And a little trick when you're using a behavior subject is instead of writing an event handler, you can just call current page next with that event as long as the event is what you actually need to send in the stream. And the last change we'll make is set the data source to a new observable called data on pages, which is a slice of the actual values that we wanna show. So we'll need to add a couple of new properties to our component to make all this work. The first one is the current page which is a behavior subject, and it's a behavior subject because we want to react to it and we also want to change it dynamically? From there, we have a data on page observable which will react to changes in the data source of heroes and also the current page. And lastly, the page size, which is just a number. The hardest part is defining the slice of data that we want to show for each page. We need to react to page changes? So we'll go ahead and pipe an observable that's based off the current page behavior subject. But the actual data source is the hero's behavior subject so we can use the switch map operator to switch to that data source? So at this point we know the current page as well as the array of heroes and we just need to map it down to a slice to display on that page. We can figure out which items to display on the page by taking that current page value, subtracting 1, and then multiplying it by the page size? That's the starting index. Then the ending index is just that starting index plus the page size? And those are the 2 arguments that we'll use to slice the pay? If we go back to our data table, you'll see that it's only displaying 2 items per page, but it's also maintaining the styling logic that we set up in the previous step? And again, this is possible because we're using a single data source and having everything else react to it accordingly. I'm gonna go ahead and wrap things up there. This video helped you? Please like and subscribe. And if you're serious about building Angular apps, consider becoming a pro member at angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support? Thanks for watching, and I'll talk to you soon.
What
what
if
if
there
there
is
is
a
a
way
way
that
that
you
you
could
could
capture
capture
all
all
the
the
benefits
benefits
of
of
Angular
angular
Material,
material
but
but
customize
customize
the
the
behavior
behavior
and
and
styling
styling
in
in
an
an
unopinionated
unopinionated
way?
way
Well,
well
that's
that's
exactly
exactly
what
what
Angular's
angular's
component
component
development
development
kit
kit
does.
does
In
in
today's
today's
video,
video
you'll
you'll
learn
learn
how
how
to
to
build
build
a
a
reactive
reactive
CDK
cdk
data
data
table
table
that
that
implements
implements
its
its
own
own
custom
custom
behaviors
behaviors
and
and
also
also
uses
uses
Bootstrap
bootstrap
could
could
pour
pour
for
for
its
its
CSS
css
styling?
styling
If
if
you're
you're
new
new
to
to
the
the
channel,
channel
make
make
sure
sure
to
to
like
like
and
and
subscribe.
subscribe
And
and
the
the
code
code
for
for
this
this
video
video
is
is
produced
produced
by
by
Zach
zach
DeRose
derose
who
who
is
is
a
a
seen
seen
your
your
team
team
lead
lead
working
working
on
on
Angular
angular
over
over
at
at
Swampfox
swampfox
Inc?
inc
Make
make
sure
sure
to
to
check
check
out
out
his
his
full
full
article
article
on
on
Medium
medium
because
because
it
it
goes
goes
into
into
some
some
advanced
advanced
stuff
stuff
that
that
I
i
don't
don't
cover
cover
could
could
hear
hear
such
such
as
as
searching,
searching
sorting,
sorting
and
and
applying
applying
styles
styles
on
on
a
a
cell
cell
by
by
cell
cell
basis?
basis
I'm
i'm
starting
starting
out
out
from
from
just
just
a
a
regular
regular
Angular
angular
6
6
app,
app
and
and
the
the
first
first
thing
thing
I'll
i'll
do
do
is
is
install
install
the
the
component
component
development
development
kit
kit
which
which
is
is
at
at
angular
angular
/cdk?
/cdk
Then
then
I'll
i'll
generate
generate
a
a
component
component
called
called
table.
table
From
from
there,
there
I'll
i'll
jump
jump
over
over
to
to
the
the
app
app
module
module
and
and
we'll
we'll
want
want
to
to
import
import
the
the
data
data
table
table
from
from
Angular
angular
CDK,
cdk
then
then
add
add
the
the
CDK
cdk
table
table
module
module
to
to
the
the
imports
imports
array.
array
Can?
can
The
the
first
first
table
table
we'll
we'll
build
build
is
is
pretty
pretty
basic
basic
and
and
ugly,
ugly
but
but
what
what
it's
it's
doing
doing
under
under
the
the
hood
hood
is
is
pretty
pretty
powerful.
powerful
And
and
without
without
the
the
CDK,
cdk
this
this
would
would
take
take
a
a
lot
lot
more
more
code
code
than
than
it
it
does
does
in
in
this
this
video.
video
Go?
go
I'll
i'll
be
be
working
working
with
with
some
some
dummy
dummy
data
data
throughout
throughout
this
this
video,
video
which
which
I
i
have
have
saved
saved
in
in
this
this
data
data
dot
dot
ts
ts
file.
file
First,
first
we
we
have
have
an
an
array
array
of
of
column
column
names,
names
which
which
just
just
define
define
the
the
names
names
of
of
the
the
columns
columns
in
in
the
the
table?
table
And
and
then
then
we
we
have
have
the
the
actual
actual
data
data
which
which
is
is
a
a
map
map
of
of
various
various
heroes,
heroes
and
and
each
each
hero
hero
has
has
a
a
set
set
of
of
properties
properties
that
that
match
match
these
these
column
column
names?
names
So,
so
basically,
basically
this
this
simulates
simulates
some
some
initial
initial
data
data
that
that
you
you
might
might
pull
pull
from
from
a
a
back
back
end
end
database
database
or
or
API.
api
Can
can
now
now
let's
let's
jump
jump
into
into
the
the
component
component
and
and
start
start
putting
putting
together
together
this
this
table.
table
I'm
i'm
going
going
to
to
go
go
pretty
pretty
slow
slow
through
through
this
this
code
code
because
because
I
i
wanna
wanna
talk
talk
about
about
behavior
behavior
subjects
subjects
can
can
observeables
observeables
because
because
they're
they're
very
very
powerful
powerful
structures
structures
when
when
working
working
with
with
tables?
tables
A
a
behavior
behavior
subject
subject
is
is
really
really
useful
useful
when
when
you
you
have
have
a
a
value
value
that
that
you
you
want
want
to
to
manually
manually
change
change
over
over
time.
time
They
they
work
work
just
just
like
like
an
an
observable,
observable
but
but
they
they
always
always
have
have
a
a
current
current
value
value
and
and
you
you
can
can
push
push
new
new
values
values
to
to
them?
them
And
and
you
you
can
can
always
always
get
get
the
the
current
current
value
value
in
in
place,
place
switch
switch
means
means
you
you
kind
kind
of
of
have
have
the
the
best
best
of
of
both
both
worlds
worlds
between
between
observables
observables
and
and
just
just
regular
regular
JavaScript?
javascript
What's
what's
also
also
really
really
cool
cool
is
is
that
that
you
you
can
can
use
use
your
your
behavior
behavior
subject
subject
as
as
a
a
single
single
source
source
truth
truth
that
that
gets
gets
mapped
mapped
to
to
other
other
observables?
observables
For
for
example,
example
we'll
we'll
be
be
able
able
to
to
map
map
this
this
hero's
hero's
dictionary
dictionary
down
down
to
to
an
an
array
array
of
of
data
data
that
that
we
we
can
can
loop
loop
over
over
in
in
our
our
data
data
cable
cable
for
for
each
each
row?
row
And
and
we'll
we'll
build
build
up
up
to
to
some
some
more
more
advanced
advanced
use
use
cases
cases
with
with
that
that
concept
concept
later
later
in
in
the
the
video.
video
So
so
if
if
you
you
want
want
to
to
take
take
your
your
single
single
source
source
of
of
truth
truth
can
can
map
map
it
it
to
to
just
just
a
a
regular
regular
observable?
observable
You
you
can
can
do
do
that
that
by
by
just
just
calling
calling
pipe
pipe
and
and
then
then
adding
adding
some
some
operators
operators
to
to
structure
structure
it
it
in
in
the
the
way
way
that
that
you
you
need
need
for
for
the
the
UI.
ui
In
in
this
this
case,
case
we
we
just
just
want
want
to
to
map
map
the
the
dictionary
dictionary
down
down
to
to
an
an
array
array
of
of
values,
values
which
which
we
we
can
can
do
do
with
with
Object
object
dot
dot
values.
values
So
so
now
now
we
we
have
have
an
an
observable
observable
array
array
of
of
data
data
that
that
we
we
can
can
loop
loop
over
over
in
in
the
the
table?
table
You
you
may
may
have
have
noticed
noticed
that
that
I
i
was
was
clicking
clicking
a
a
button
button
in
in
the
the
table
table
that
that
was
was
changing
changing
the
the
values
values
for
for
a
a
given
given
row.
row
That's
that's
also
also
made
made
possible
possible
by
by
the
the
reactive
reactive
nature
nature
of
of
behavior
behavior
subjects
subjects
and
and
observables.
observables
We
we
can
can
grab
grab
the
the
value
value
of
of
our
our
behavior
behavior
subject
subject
by
by
simply
simply
calling
calling
value
value
on
on
it.
it
And
and
because
because
it's
it's
an
an
object,
object
we
we
can
can
then
then
grab
grab
the
the
hero
hero
name
name
that's
that's
being
being
clicked
clicked
on
on
and
and
update
update
its
its
values.
values
To
to
level
level
up
up
the
the
hero,
hero
we'll
we'll
simply
simply
increment
increment
each
each
one
one
of
of
its
its
properties
properties
by
by
1.
1
From
from
there,
there
we
we
can
can
compose
compose
a
a
new
new
object
object
by
by
using
using
the
the
spread
spread
syntax
syntax
and
and
taking
taking
that
that
current
current
value
value
from
from
the
the
behavior
behavior
subject,
subject
then
then
overwrite
overwrite
the
the
value
value
for
for
the
the
clicked
clicked
hero?
hero
So
so
that'll
that'll
be
be
the
the
next
next
value
value
for
for
our
our
behavior
behavior
subject
subject
and
and
everything
everything
else
else
that
that
depends
depends
on
on
it
it
will
will
react
react
accordingly.
accordingly
And
and
we
we
can
can
simply
simply
push
push
that
that
into
into
the
the
stream
stream
by
by
calling
calling
next?
next
Now
now
we
we
can
can
jump
jump
into
into
the
the
component
component
HTML,
html
and
and
we'll
we'll
see
see
that
that
the
the
CDK
cdk
gives
gives
us
us
a
a
whole
whole
bunch
bunch
of
of
different
different
could
could
divs
divs
that
that
we
we
can
can
use
use
to
to
bind
bind
our
our
data
data
to
to
the
the
table?
table
The
the
most
most
important
important
one
one
is
is
the
the
data
data
source
source
which
which
is
is
that
that
observable
observable
that
that
we
we
mapped
mapped
our
our
behavior
behavior
subject
subject
to
to
in
in
the
the
TypeScript.
typescript
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
define
define
the
the
header
header
row.
row
And
and
because
because
we
we
already
already
have
have
an
an
array
array
of
of
the
the
column
column
names,
names
we
we
can
can
just
just
pass
pass
that
that
in
in
as
as
the
the
CDK
cdk
header
header
row
row
definition.
definition
After
after
that,
that
we
we
will
will
make
make
a
a
definition
definition
for
for
each
each
actual
actual
row
row
in
in
the
the
table.
table
And
and
that's
that's
going
going
to
to
automatically
automatically
loop
loop
over
over
every
every
item
item
in
in
our
our
data
data
source
source
array.
array
Came?
came
Now
now
the
the
last
last
major
major
step
step
is
is
to
to
define
define
the
the
logic
logic
for
for
each
each
cell
cell
in
in
the
the
row.
row
You
you
could
could
loop
loop
over
over
each
each
cell
cell
or
or
you
you
can
can
define
define
them
them
1
1
by
by
1.
1
Since
since
we
we
have
have
some
some
custom
custom
behavior,
behavior
we'll
we'll
just
just
go
go
ahead
ahead
and
and
declare
declare
each
each
one
one
of
of
our
our
cells
cells
1
1
by
by
1.
1
All
all
we
we
have
have
to
to
do
do
is
is
define
define
what
what
the
the
header
header
should
should
look
look
like.
like
Then
then
we
we
have
have
access
access
to
to
the
the
underlying
underlying
data
data
object,
object
which
which
is
is
in
in
the
the
template
template
variable
variable
of
of
row.
row
So
so
this
this
cell
cell
will
will
have
have
a
a
header
header
of
of
hero
hero
name,
name
and
and
then
then
the
the
actual
actual
value
value
will
will
be
be
the
the
row
row
name?
name
Then
then
we'll
we'll
just
just
go
go
ahead
ahead
and
and
repeat
repeat
this
this
logic
logic
over
over
and
and
over
over
again
again
until
until
we
we
get
get
to
to
the
the
actual
actual
cell
cell
that
that
has
has
the
the
clickable
clickable
button.
button
The
the
special
special
thing
thing
about
about
this
this
cell
cell
is
is
that
that
we're
we're
not
not
actually
actually
displaying
displaying
a
a
value,
value
but
but
instead
instead
we'll
we'll
have
have
a
a
clickable
clickable
button
button
that
that
will
will
trigger
trigger
that
that
level
level
up
up
event
event
handler
handler
that
that
we
we
define
define
in
in
the
the
TypeScript.
typescript
To
to
level
level
up
up
a
a
hero,
hero
we
we
need
need
to
to
know
know
its
its
name,
name
which
which
we
we
have
have
access
access
to
to
through
through
the
the
row
row
template
template
variable,
variable
which
which
we
we
can
can
then
then
pass
pass
in
in
to
to
our
our
level
level
up
up
method
method
as
as
the
the
argument.
argument
And
and
just
just
like
like
that,
that
we
we
have
have
a
a
data
data
table
table
that
that
relies
relies
on
on
a
a
single
single
source
source
of
of
truth
truth
for
for
its
its
input,
input
which
which
is
is
a
a
pattern
pattern
that
that
you
you
really
really
want
want
if
if
you're
you're
going
going
to
to
scale
scale
up
up
in
in
complex
complex
could
could
be?
be
Just
just
imagine
imagine
trying
trying
to
to
apply
apply
the
the
same
same
pattern
pattern
in
in
plain
plain
JavaScript
javascript
or
or
jQuery.
jquery
You'd
you'd
have
have
a
a
lot
lot
more
more
code
code
to
to
write.
write
But
but
for
for
your
your
end
end
users,
users
this
this
is
is
still
still
a
a
pretty
pretty
ugly
ugly
table.
table
Let's
let's
see
see
how
how
we
we
might
might
add
add
some
some
better
better
styling
styling
to
to
it.
it
For
for
that,
that
we'll
we'll
use
use
Bootstrap
bootstrap
4,
4
but
but
you
you
could
could
use
use
any
any
other
other
CSS
css
framework
framework
or
or
your
your
own
own
styles
styles
completely.
completely
You
you
can
can
grab
grab
the
the
CSS
css
for
for
Bootstrap
bootstrap
from
from
the
the
website
website
and
and
then
then
paste
paste
it
it
into
into
the
the
head
head
of
of
the
the
document
document
in
in
the
the
index
index
HTML
html
file
file
in
in
Angular?
angular
Then
then
back
back
in
in
the
the
Bootstrap
bootstrap
docs,
docs
you'll
you'll
see
see
a
a
variety
variety
of
of
different
different
styles
styles
for
for
tables.
tables
Pick
pick
whichever
whichever
one
one
you
you
like,
like
and
and
you'll
you'll
also
also
want
want
a
a
style
style
for
for
the
the
button
button
in
in
that
that
table
table
as
as
well.
well
So
so
as
as
you
you
might
might
imagine,
imagine
adding
adding
styles
styles
to
to
our
our
CDK
cdk
table
table
is
is
easy
easy
as
as
any
any
other
other
HTML
html
table.
table
We
we
simply
simply
add
add
the
the
class
class
name,
name
and
and
we're
we're
good
good
to
to
go.
go
So
so
now
now
we
we
have
have
a
a
table
table
that
that
behaves
behaves
like
like
Angular
angular
Material
material
but
but
looks
looks
like
like
Bootstrap.
bootstrap
But
but
I
i
wanna
wanna
take
take
this
this
a
a
step
step
further,
further
and
and
I
i
want
want
to
to
highlight
highlight
the
the
hero
hero
with
with
the
the
highest
highest
and
and
lowest
lowest
health
health
rating?
rating
And
and
I
i
want
want
that
that
style
style
to
to
be
be
updated
updated
reactively
reactively
whenever
whenever
the
the
values
values
change
change
in
in
this
this
table.
table
Let's
let's
see
see
how
how
we
we
can
can
leverage
leverage
our
our
existing
existing
behavior
behavior
subject
subject
to
to
handle
handle
this
this
for
for
us.
us
I'm
i'm
also
also
going
going
to
to
install
install
the
the
max
max
by
by
and
and
min
min
by
by
methods
methods
from
from
Lodash
lodash
to
to
make
make
this
this
code
code
a
a
little
little
bit
bit
more
more
concise.
concise
Guys?
guys
These
these
functions
functions
are
are
really
really
useful
useful
if
if
you
you
have
have
an
an
array
array
of
of
objects
objects
and
and
you
you
need
need
to
to
calculate
calculate
some
some
statistics
statistics
about
about
a
a
certain
certain
property
property
on
on
those
those
objects,
objects
which
which
in
in
this
this
case,
case
we
we
want
want
to
to
find
find
the
the
heroes
heroes
with
with
the
the
min
min
and
and
max
max
health?
health
From
from
there,
there
we'll
we'll
go
go
ahead
ahead
and
and
define
define
a
a
new
new
observable
observable
called
called
min
min
max,
max
and
and
this
this
will
will
be
be
tied
tied
to
to
our
our
hero
hero
source
source
behavior
behavior
subject.
subject
But
but
this
this
time,
time
we
we
want
want
to
to
map
map
it
it
down
down
to
to
just
just
the
the
2
2
heroes,
heroes
1
1
with
with
the
the
min
min
and
and
1
1
with
with
the
the
max
max
health.
health
So
so
what
what
we're
we're
doing
doing
here
here
is
is
computing
computing
a
a
value
value
based
based
on
on
a
a
single
single
source
source
of
of
truth
truth
that
that
will
will
update
update
reactively.
reactively
Inside
inside
of
of
map,
map
we
we
can
can
simply
simply
use
use
Lodash
lodash
to
to
find
find
the
the
hero
hero
with
with
the
the
max
max
health
health
and
and
then
then
a
a
hero
hero
with
with
the
the
min
min
health?
health
And
and
then
then
we'll
we'll
just
just
return
return
the
the
names
names
of
of
those
those
2
2
heroes
heroes
so
so
we
we
can
can
use
use
them
them
in
in
our
our
HTML.
html
Now
now
Angular
angular
has
has
a
a
built
built
in
in
ng
ng
class
class
directive
directive
that
that
we
we
can
can
use
use
to
to
easily
easily
update
update
the
the
styles
styles
based
based
on
on
this
this
logic.
logic
We
we
pass
pass
ng
ng
class
class
an
an
object
object
where
where
the
the
key
key
of
of
that
that
object
object
is
is
the
the
CSS
css
class
class
that
that
we
we
want
want
to
to
apply?
apply
This
this
class
class
is
is
from
from
Bootstrap,
bootstrap
which
which
is
is
BG
bg
success,
success
which
which
will
will
give
give
the
the
row
row
a
a
green
green
highlight,
highlight
and
and
then
then
we'll
we'll
unwrap
unwrap
the
the
min
min
max
max
observable.
observable
And
and
if
if
the
the
max
max
equals
equals
this
this
row
row
name,
name
then
then
we'll
we'll
go
go
ahead
ahead
and
and
highlight
highlight
it.
it
Then
then
we'll
we'll
do
do
the
the
same
same
exact
exact
ping
ping
for
for
the
the
min
min
value,
value
except
except
this
this
time
time
we'll
we'll
apply
apply
the
the
bg
bg
danger,
danger
which
which
will
will
give
give
it
it
a
a
red
red
highlight?
highlight
And
and
that's
that's
all
all
there
there
is
is
to
to
it.
it
We
we
now
now
have
have
reactive
reactive
CSS
css
is
is
being
being
applied
applied
to
to
our
our
data
data
table?
table
If
if
your
your
tables
tables
have
have
huge
huge
amounts
amounts
of
of
data,
data
then
then
you'll
you'll
probably
probably
need
need
to
to
paginate
paginate
it.
it
So
so
let's
let's
look
look
into
into
how
how
we
we
can
can
further
further
leverage
leverage
RxJS
rxjs
to
to
make
make
a
a
reactive
reactive
pagination
pagination
system?
system
To
to
simplify
simplify
the
the
UI
ui
elements,
elements
I'm
i'm
going
going
to
to
use
use
ng
ng
bootstrap,
bootstrap
but
but
you
you
could
could
definitely
definitely
do
do
this
this
from
from
scratch
scratch
as
as
well.
well
First
first
will
will
install
install
it
it
via
via
npm,
npm
then
then
go
go
into
into
the
the
app
app
module
module
and
and
add
add
it
it
to
to
the
the
imports
imports
array
array
there?
there
It
it
gives
gives
us
us
access
access
to
to
a
a
pagination
pagination
component,
component
and
and
we
we
just
just
need
need
to
to
pass
pass
it
it
a
a
few
few
input
input
variables
variables
to
to
make
make
it
it
work?
work
It
it
needs
needs
to
to
know
know
the
the
total
total
size
size
of
of
our
our
collection,
collection
which
which
is
is
just
just
the
the
length
length
of
of
our
our
data
data
source
source
array.
array
Then
then
it
it
needs
needs
to
to
know
know
how
how
many
many
items
items
we
we
wanna
wanna
show
show
on
on
each
each
page.
page
It
it
also
also
needs
needs
to
to
know
know
the
the
current
current
page,
page
which
which
will
will
also
also
be
be
a
a
behavior
behavior
subject
subject
when
when
we
we
get
get
to
to
the
the
TypeScript.
typescript
And
and
lastly,
lastly
it
it
needs
needs
an
an
event
event
handler,
handler
so
so
when
when
the
the
user
user
clicks
clicks
on
on
a
a
new
new
page,
page
it
it
updates
updates
to
to
the
the
correct
correct
page.
page
And
and
a
a
little
little
trick
trick
when
when
you're
you're
using
using
a
a
behavior
behavior
subject
subject
is
is
instead
instead
of
of
writing
writing
an
an
event
event
handler,
handler
you
you
can
can
just
just
call
call
current
current
page
page
next
next
with
with
that
that
event
event
as
as
long
long
as
as
the
the
event
event
is
is
what
what
you
you
actually
actually
need
need
to
to
send
send
in
in
the
the
stream.
stream
And
and
the
the
last
last
change
change
we'll
we'll
make
make
is
is
set
set
the
the
data
data
source
source
to
to
a
a
new
new
observable
observable
called
called
data
data
on
on
pages,
pages
which
which
is
is
a
a
slice
slice
of
of
the
the
actual
actual
values
values
that
that
we
we
wanna
wanna
show.
show
So
so
we'll
we'll
need
need
to
to
add
add
a
a
couple
couple
of
of
new
new
properties
properties
to
to
our
our
component
component
to
to
make
make
all
all
this
this
work.
work
The
the
first
first
one
one
is
is
the
the
current
current
page
page
which
which
is
is
a
a
behavior
behavior
subject,
subject
and
and
it's
it's
a
a
behavior
behavior
subject
subject
because
because
we
we
want
want
to
to
react
react
to
to
it
it
and
and
we
we
also
also
want
want
to
to
change
change
it
it
dynamically?
dynamically
From
from
there,
there
we
we
have
have
a
a
data
data
on
on
page
page
observable
observable
which
which
will
will
react
react
to
to
changes
changes
in
in
the
the
data
data
source
source
of
of
heroes
heroes
and
and
also
also
the
the
current
current
page.
page
And
and
lastly,
lastly
the
the
page
page
size,
size
which
which
is
is
just
just
a
a
number.
number
The
the
hardest
hardest
part
part
is
is
defining
defining
the
the
slice
slice
of
of
data
data
that
that
we
we
want
want
to
to
show
show
for
for
each
each
page.
page
We
we
need
need
to
to
react
react
to
to
page
page
changes?
changes
So
so
we'll
we'll
go
go
ahead
ahead
and
and
pipe
pipe
an
an
observable
observable
that's
that's
based
based
off
off
the
the
current
current
page
page
behavior
behavior
subject.
subject
But
but
the
the
actual
actual
data
data
source
source
is
is
the
the
hero's
hero's
behavior
behavior
subject
subject
so
so
we
we
can
can
use
use
the
the
switch
switch
map
map
operator
operator
to
to
switch
switch
to
to
that
that
data
data
source?
source
So
so
at
at
this
this
point
point
we
we
know
know
the
the
current
current
page
page
as
as
well
well
as
as
the
the
array
array
of
of
heroes
heroes
and
and
we
we
just
just
need
need
to
to
map
map
it
it
down
down
to
to
a
a
slice
slice
to
to
display
display
on
on
that
that
page.
page
We
we
can
can
figure
figure
out
out
which
which
items
items
to
to
display
display
on
on
the
the
page
page
by
by
taking
taking
that
that
current
current
page
page
value,
value
subtracting
subtracting
1,
1
and
and
then
then
multiplying
multiplying
it
it
by
by
the
the
page
page
size?
size
That's
that's
the
the
starting
starting
index.
index
Then
then
the
the
ending
ending
index
index
is
is
just
just
that
that
starting
starting
index
index
plus
plus
the
the
page
page
size?
size
And
and
those
those
are
are
the
the
2
2
arguments
arguments
that
that
we'll
we'll
use
use
to
to
slice
slice
the
the
pay?
pay
If
if
we
we
go
go
back
back
to
to
our
our
data
data
table,
table
you'll
you'll
see
see
that
that
it's
it's
only
only
displaying
displaying
2
2
items
items
per
per
page,
page
but
but
it's
it's
also
also
maintaining
maintaining
the
the
styling
styling
logic
logic
that
that
we
we
set
set
up
up
in
in
the
the
previous
previous
step?
step
And
and
again,
again
this
this
is
is
possible
possible
because
because
we're
we're
using
using
a
a
single
single
data
data
source
source
and
and
having
having
everything
everything
else
else
react
react
to
to
it
it
accordingly.
accordingly
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
This
this
video
video
helped
helped
you?
you
Please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you're
you're
serious
serious
about
about
building
building
Angular
angular
apps,
apps
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
angularfirebase.com.
angularfirebase.com
You'll
you'll
get
get
a
a
free
free
copy
copy
of
of
my
my
book
book
as
as
well
well
as
as
1
1
on
on
1
1
project
project
support?
support
Thanks
thanks
for
for
watching,
watching
and
and
I'll
i'll
talk
talk
to
to
you
you
soon.
soon
success
The speaker explains how the Angular component development kit can customize behavior and styling in an unistorted way by mapping a dictionary to an array and creating a new object for each row. They also discuss the logic for each cell in the row and define the logic for each cell. The speaker explains how to update a function for a row, use the RxJS tool to make a reactive denies system, and use the RxJS tool to update the data source for a new variables and add a new class for the hero. They also mention a free book and a project support page.
Angular CDK Data Tables
What if there is a way that you could capture all the benefits of Angular Material, but customize the behavior and styling in an unopinionated way? Well, that's exactly what Angular's component development kit does. In today's video, you'll learn how to build a reactive CDK data table that implements its own custom behaviors and also uses Bootstrap could pour for its CSS styling? If you're new to the channel, make sure to like and subscribe. And the code for this video is produced by Zach DeRose who is a seen your team lead working on Angular over at Swampfox Inc? Make sure to check out his full article on Medium because it goes into some advanced stuff that I don't cover could hear such as searching, sorting, and applying styles on a cell by cell basis? I'm starting out from just a regular Angular 6 app, and the first thing I'll do is install the component development kit which is at angular /cdk? Then I'll generate a component called table. From there, I'll jump over to the app module and we'll want to import the data table from Angular CDK, then add the CDK table module to the imports array. Can? The first table we'll build is pretty basic and ugly, but what it's doing under the hood is pretty powerful. And without the CDK, this would take a lot more code than it does in this video. Go? I'll be working with some dummy data throughout this video, which I have saved in this data dot ts file. First, we have an array of column names, which just define the names of the columns in the table? And then we have the actual data which is a map of various heroes, and each hero has a set of properties that match these column names? So, basically, this simulates some initial data that you might pull from a back end database or API. Can now let's jump into the component and start putting together this table. I'm going to go pretty slow through this code because I wanna talk about behavior subjects can observeables because they're very powerful structures when working with tables? A behavior subject is really useful when you have a value that you want to manually change over time. They work just like an observable, but they always have a current value and you can push new values to them? And you can always get the current value in place, switch means you kind of have the best of both worlds between observables and just regular JavaScript? What's also really cool is that you can use your behavior subject as a single source truth that gets mapped to other observables? For example, we'll be able to map this hero's dictionary down to an array of data that we can loop over in our data cable for each row? And we'll build up to some more advanced use cases with that concept later in the video. So if you want to take your single source of truth can map it to just a regular observable? You can do that by just calling pipe and then adding some operators to structure it in the way that you need for the UI. In this case, we just want to map the dictionary down to an array of values, which we can do with Object dot values. So now we have an observable array of data that we can loop over in the table? You may have noticed that I was clicking a button in the table that was changing the values for a given row. That's also made possible by the reactive nature of behavior subjects and observables. We can grab the value of our behavior subject by simply calling value on it. And because it's an object, we can then grab the hero name that's being clicked on and update its values. To level up the hero, we'll simply increment each one of its properties by 1. From there, we can compose a new object by using the spread syntax and taking that current value from the behavior subject, then overwrite the value for the clicked hero? So that'll be the next value for our behavior subject and everything else that depends on it will react accordingly. And we can simply push that into the stream by calling next? Now we can jump into the component HTML, and we'll see that the CDK gives us a whole bunch of different could divs that we can use to bind our data to the table? The most important one is the data source which is that observable that we mapped our behavior subject to in the TypeScript. The next thing we'll do is define the header row. And because we already have an array of the column names, we can just pass that in as the CDK header row definition. After that, we will make a definition for each actual row in the table. And that's going to automatically loop over every item in our data source array. Came? Now the last major step is to define the logic for each cell in the row. You could loop over each cell or you can define them 1 by 1. Since we have some custom behavior, we'll just go ahead and declare each one of our cells 1 by 1. All we have to do is define what the header should look like. Then we have access to the underlying data object, which is in the template variable of row. So this cell will have a header of hero name, and then the actual value will be the row name? Then we'll just go ahead and repeat this logic over and over again until we get to the actual cell that has the clickable button. The special thing about this cell is that we're not actually displaying a value, but instead we'll have a clickable button that will trigger that level up event handler that we define in the TypeScript. To level up a hero, we need to know its name, which we have access to through the row template variable, which we can then pass in to our level up method as the argument. And just like that, we have a data table that relies on a single source of truth for its input, which is a pattern that you really want if you're going to scale up in complex could be? Just imagine trying to apply the same pattern in plain JavaScript or jQuery. You'd have a lot more code to write. But for your end users, this is still a pretty ugly table. Let's see how we might add some better styling to it. For that, we'll use Bootstrap 4, but you could use any other CSS framework or your own styles completely. You can grab the CSS for Bootstrap from the website and then paste it into the head of the document in the index HTML file in Angular? Then back in the Bootstrap docs, you'll see a variety of different styles for tables. Pick whichever one you like, and you'll also want a style for the button in that table as well. So as you might imagine, adding styles to our CDK table is easy as any other HTML table. We simply add the class name, and we're good to go. So now we have a table that behaves like Angular Material but looks like Bootstrap. But I wanna take this a step further, and I want to highlight the hero with the highest and lowest health rating? And I want that style to be updated reactively whenever the values change in this table. Let's see how we can leverage our existing behavior subject to handle this for us. I'm also going to install the max by and min by methods from Lodash to make this code a little bit more concise. Guys? These functions are really useful if you have an array of objects and you need to calculate some statistics about a certain property on those objects, which in this case, we want to find the heroes with the min and max health? From there, we'll go ahead and define a new observable called min max, and this will be tied to our hero source behavior subject. But this time, we want to map it down to just the 2 heroes, 1 with the min and 1 with the max health. So what we're doing here is computing a value based on a single source of truth that will update reactively. Inside of map, we can simply use Lodash to find the hero with the max health and then a hero with the min health? And then we'll just return the names of those 2 heroes so we can use them in our HTML. Now Angular has a built in ng class directive that we can use to easily update the styles based on this logic. We pass ng class an object where the key of that object is the CSS class that we want to apply? This class is from Bootstrap, which is BG success, which will give the row a green highlight, and then we'll unwrap the min max observable. And if the max equals this row name, then we'll go ahead and highlight it. Then we'll do the same exact ping for the min value, except this time we'll apply the bg danger, which will give it a red highlight? And that's all there is to it. We now have reactive CSS is being applied to our data table? If your tables have huge amounts of data, then you'll probably need to paginate it. So let's look into how we can further leverage RxJS to make a reactive pagination system? To simplify the UI elements, I'm going to use ng bootstrap, but you could definitely do this from scratch as well. First will install it via npm, then go into the app module and add it to the imports array there? It gives us access to a pagination component, and we just need to pass it a few input variables to make it work? It needs to know the total size of our collection, which is just the length of our data source array. Then it needs to know how many items we wanna show on each page. It also needs to know the current page, which will also be a behavior subject when we get to the TypeScript. And lastly, it needs an event handler, so when the user clicks on a new page, it updates to the correct page. And a little trick when you're using a behavior subject is instead of writing an event handler, you can just call current page next with that event as long as the event is what you actually need to send in the stream. And the last change we'll make is set the data source to a new observable called data on pages, which is a slice of the actual values that we wanna show. So we'll need to add a couple of new properties to our component to make all this work. The first one is the current page which is a behavior subject, and it's a behavior subject because we want to react to it and we also want to change it dynamically? From there, we have a data on page observable which will react to changes in the data source of heroes and also the current page. And lastly, the page size, which is just a number. The hardest part is defining the slice of data that we want to show for each page. We need to react to page changes? So we'll go ahead and pipe an observable that's based off the current page behavior subject. But the actual data source is the hero's behavior subject so we can use the switch map operator to switch to that data source? So at this point we know the current page as well as the array of heroes and we just need to map it down to a slice to display on that page. We can figure out which items to display on the page by taking that current page value, subtracting 1, and then multiplying it by the page size? That's the starting index. Then the ending index is just that starting index plus the page size? And those are the 2 arguments that we'll use to slice the pay? If we go back to our data table, you'll see that it's only displaying 2 items per page, but it's also maintaining the styling logic that we set up in the previous step? And again, this is possible because we're using a single data source and having everything else react to it accordingly. I'm gonna go ahead and wrap things up there. This video helped you? Please like and subscribe. And if you're serious about building Angular apps, consider becoming a pro member at angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support? Thanks for watching, and I'll talk to you soon.
The speaker explains how the Angular component development kit can customize behavior and styling in an unistorted way by mapping a dictionary to an array and creating a new object for each row. They also discuss the logic for each cell in the row and define the logic for each cell. The speaker explains how to update a function for a row, use the RxJS tool to make a reactive denies system, and use the RxJS tool to update the data source for a new variables and add a new class for the hero. They also mention a free book and a project support page.