At Trailhead, we’ve been making the switch from Angular 1 to Angular 2 for our new web front-end projects. The selection of tools and components for Angular 2 has been slowly expanding, but it is still young and somewhat limited at times, which is why we’ve been very excitedly following the news from our friends at Progress (formerly Telerik) as they’ve been working on their Kendo suite of UI widgets for Angular 2.
Though still in beta, things are progressing quickly toward a May 2017 launch, so I decided to try out their latest version with Angular 2 and document the process I used for anyone else that wants to follow along.
Prerequisites
Before we can create our Angular app and add Kendo to it, we’ll need a few things. In this blog post I’ve made several decisions about the tools I used which you don’t have to make. In fact, you can do almost all of these things another way, but if you want to follow along with me, make sure you have the following items installed:
- Visual Studio Code editor
- Npm Package Manager
- An existing Telerik account (or you can sign up for a trial)
Project Creation Using Angular CLI
To create the project, I used a tool called Angular CLI (Command-Line Interface). If you don’t have it already, open a shell command window to install it using NPM.
npm install -g angular-cli
This will globally (-g) install the Angular CLI package on your machine, meaning it will be available in any directory. You can now run this command using its simple alias of “ng” which is a common abbreviation for Angular. Navigate in your command shell to a folder where you’d like to create your new project and execute the following command, which will create the project in a subfolder called ng-kendo:
ng new ng-kendo
Now you can change directory to the newly created project folder:
cd ng-kendo
The ng new command already should have restored your NPM packages, so now you should be able to run the application at https://localhost:4200 after running the following command:
npm start
If it worked correctly, you should see something like this in your browser.
Adding Kendo
Now that you’ve got a simple, working Angular 2 application set up, let’s add Kendo to the project. Kendo uses its own NPM registry, which you much log in to using a Progress/Telerik account to get access to these beta bits. You can enable the Progress NPM registry on your machine by associating the @progress
scope with the registry URL. Run the following command in your terminal:
npm login --registry=https://registry.npm.telerik.com/ --scope=@progress
You’ll be prompted for a few pieces of information. If your username for your Telerik/Progress account is an email address like mine is, just use the part before the @ symbol when prompted for your username. Enter your password, and finally, when prompted, enter your full email address.
You’ve now told NPM to get @progress packages from the Telerik/Progree registry listed above whenever it encounters one on this machine.
Adding the Grid Component
With the registry set up, we’re now ready to get the Kendo components using NPM. From the command prompt, enter the following command to install all 4 required Kendo components to be able to use the Kendo grid:
npm install --save @progress/kendo-angular-grid @progress/kendo-data-query @progress/kendo-angular-intl @progress/kendo-theme-default
This adds the latest versions of the grid, the data querying library, the kendo-angular library, and the default Kendo theme to your package.json file for you. Now tell NPM to update those packages in your project:
npm update
Open up your project in VS code. From the command prompt you can type “code .” to open the current folder in VS Code.
Under src/app, add a new TypeScript document called products.ts and paste the following sample data into it:
export const sampleProducts = [{ "ProductID" : 1, "ProductName" : "Chai", "SupplierID" : 1, "CategoryID" : 1, "QuantityPerUnit" : "10 boxes x 20 bags", "UnitPrice" : 18.0000, "UnitsInStock" : 39, "UnitsOnOrder" : 0, "ReorderLevel" : 10, "Discontinued" : false, "Category" : { "CategoryID" : 1, "CategoryName" : "Beverages", "Description" : "Soft drinks, coffees, teas, beers, and ales" } }, { "ProductID" : 2, "ProductName" : "Chang", "SupplierID" : 1, "CategoryID" : 1, "QuantityPerUnit" : "24 - 12 oz bottles", "UnitPrice" : 19.0000, "UnitsInStock" : 17, "UnitsOnOrder" : 40, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 1, "CategoryName" : "Beverages", "Description" : "Soft drinks, coffees, teas, beers, and ales" } }, { "ProductID" : 3, "ProductName" : "Aniseed Syrup", "SupplierID" : 1, "CategoryID" : 2, "QuantityPerUnit" : "12 - 550 ml bottles", "UnitPrice" : 10.0000, "UnitsInStock" : 13, "UnitsOnOrder" : 70, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 4, "ProductName" : "Chef Anton's Cajun Seasoning", "SupplierID" : 2, "CategoryID" : 2, "QuantityPerUnit" : "48 - 6 oz jars", "UnitPrice" : 22.0000, "UnitsInStock" : 53, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 5, "ProductName" : "Chef Anton's Gumbo Mix", "SupplierID" : 2, "CategoryID" : 2, "QuantityPerUnit" : "36 boxes", "UnitPrice" : 21.3500, "UnitsInStock" : 0, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 6, "ProductName" : "Grandma's Boysenberry Spread", "SupplierID" : 3, "CategoryID" : 2, "QuantityPerUnit" : "12 - 8 oz jars", "UnitPrice" : 25.0000, "UnitsInStock" : 120, "UnitsOnOrder" : 0, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 7, "ProductName" : "Uncle Bob's Organic Dried Pears", "SupplierID" : 3, "CategoryID" : 7, "QuantityPerUnit" : "12 - 1 lb pkgs.", "UnitPrice" : 30.0000, "UnitsInStock" : 15, "UnitsOnOrder" : 0, "ReorderLevel" : 10, "Discontinued" : false, "Category" : { "CategoryID" : 7, "CategoryName" : "Produce", "Description" : "Dried fruit and bean curd" } }, { "ProductID" : 8, "ProductName" : "Northwoods Cranberry Sauce", "SupplierID" : 3, "CategoryID" : 2, "QuantityPerUnit" : "12 - 12 oz jars", "UnitPrice" : 40.0000, "UnitsInStock" : 6, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 9, "ProductName" : "Mishi Kobe Niku", "SupplierID" : 4, "CategoryID" : 6, "QuantityPerUnit" : "18 - 500 g pkgs.", "UnitPrice" : 97.0000, "UnitsInStock" : 29, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 6, "CategoryName" : "Meat/Poultry", "Description" : "Prepared meats" } }, { "ProductID" : 10, "ProductName" : "Ikura", "SupplierID" : 4, "CategoryID" : 8, "QuantityPerUnit" : "12 - 200 ml jars", "UnitPrice" : 31.0000, "UnitsInStock" : 31, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 8, "CategoryName" : "Seafood", "Description" : "Seaweed and fish" } }]; export const products = [{ "ProductID" : 1, "ProductName" : "Chai", "SupplierID" : 1, "CategoryID" : 1, "QuantityPerUnit" : "10 boxes x 20 bags", "UnitPrice" : 18.0000, "UnitsInStock" : 39, "UnitsOnOrder" : 0, "ReorderLevel" : 10, "Discontinued" : false, "Category" : { "CategoryID" : 1, "CategoryName" : "Beverages", "Description" : "Soft drinks, coffees, teas, beers, and ales" } }, { "ProductID" : 2, "ProductName" : "Chang", "SupplierID" : 1, "CategoryID" : 1, "QuantityPerUnit" : "24 - 12 oz bottles", "UnitPrice" : 19.0000, "UnitsInStock" : 17, "UnitsOnOrder" : 40, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 1, "CategoryName" : "Beverages", "Description" : "Soft drinks, coffees, teas, beers, and ales" } }, { "ProductID" : 3, "ProductName" : "Aniseed Syrup", "SupplierID" : 1, "CategoryID" : 2, "QuantityPerUnit" : "12 - 550 ml bottles", "UnitPrice" : 10.0000, "UnitsInStock" : 13, "UnitsOnOrder" : 70, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 4, "ProductName" : "Chef Anton's Cajun Seasoning", "SupplierID" : 2, "CategoryID" : 2, "QuantityPerUnit" : "48 - 6 oz jars", "UnitPrice" : 22.0000, "UnitsInStock" : 53, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 5, "ProductName" : "Chef Anton's Gumbo Mix", "SupplierID" : 2, "CategoryID" : 2, "QuantityPerUnit" : "36 boxes", "UnitPrice" : 21.3500, "UnitsInStock" : 0, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 6, "ProductName" : "Grandma's Boysenberry Spread", "SupplierID" : 3, "CategoryID" : 2, "QuantityPerUnit" : "12 - 8 oz jars", "UnitPrice" : 25.0000, "UnitsInStock" : 120, "UnitsOnOrder" : 0, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 7, "ProductName" : "Uncle Bob's Organic Dried Pears", "SupplierID" : 3, "CategoryID" : 7, "QuantityPerUnit" : "12 - 1 lb pkgs.", "UnitPrice" : 30.0000, "UnitsInStock" : 15, "UnitsOnOrder" : 0, "ReorderLevel" : 10, "Discontinued" : false, "Category" : { "CategoryID" : 7, "CategoryName" : "Produce", "Description" : "Dried fruit and bean curd" } }, { "ProductID" : 8, "ProductName" : "Northwoods Cranberry Sauce", "SupplierID" : 3, "CategoryID" : 2, "QuantityPerUnit" : "12 - 12 oz jars", "UnitPrice" : 40.0000, "UnitsInStock" : 6, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 9, "ProductName" : "Mishi Kobe Niku", "SupplierID" : 4, "CategoryID" : 6, "QuantityPerUnit" : "18 - 500 g pkgs.", "UnitPrice" : 97.0000, "UnitsInStock" : 29, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 6, "CategoryName" : "Meat/Poultry", "Description" : "Prepared meats" } }, { "ProductID" : 10, "ProductName" : "Ikura", "SupplierID" : 4, "CategoryID" : 8, "QuantityPerUnit" : "12 - 200 ml jars", "UnitPrice" : 31.0000, "UnitsInStock" : 31, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 8, "CategoryName" : "Seafood", "Description" : "Seaweed and fish" } }, { "ProductID" : 11, "ProductName" : "Queso Cabrales", "SupplierID" : 5, "CategoryID" : 4, "QuantityPerUnit" : "1 kg pkg.", "UnitPrice" : 21.0000, "UnitsInStock" : 22, "UnitsOnOrder" : 30, "ReorderLevel" : 30, "Discontinued" : false, "Category" : { "CategoryID" : 4, "CategoryName" : "Dairy Products", "Description" : "Cheeses" } }, { "ProductID" : 12, "ProductName" : "Queso Manchego La Pastora", "SupplierID" : 5, "CategoryID" : 4, "QuantityPerUnit" : "10 - 500 g pkgs.", "UnitPrice" : 38.0000, "UnitsInStock" : 86, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 4, "CategoryName" : "Dairy Products", "Description" : "Cheeses" } }, { "ProductID" : 13, "ProductName" : "Konbu", "SupplierID" : 6, "CategoryID" : 8, "QuantityPerUnit" : "2 kg box", "UnitPrice" : 6.0000, "UnitsInStock" : 24, "UnitsOnOrder" : 0, "ReorderLevel" : 5, "Discontinued" : false, "Category" : { "CategoryID" : 8, "CategoryName" : "Seafood", "Description" : "Seaweed and fish" } }, { "ProductID" : 14, "ProductName" : "Tofu", "SupplierID" : 6, "CategoryID" : 7, "QuantityPerUnit" : "40 - 100 g pkgs.", "UnitPrice" : 23.2500, "UnitsInStock" : 35, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 7, "CategoryName" : "Produce", "Description" : "Dried fruit and bean curd" } }, { "ProductID" : 15, "ProductName" : "Genen Shouyu", "SupplierID" : 6, "CategoryID" : 2, "QuantityPerUnit" : "24 - 250 ml bottles", "UnitPrice" : 15.5000, "UnitsInStock" : 39, "UnitsOnOrder" : 0, "ReorderLevel" : 5, "Discontinued" : false, "Category" : { "CategoryID" : 2, "CategoryName" : "Condiments", "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings" } }, { "ProductID" : 16, "ProductName" : "Pavlova", "SupplierID" : 7, "CategoryID" : 3, "QuantityPerUnit" : "32 - 500 g boxes", "UnitPrice" : 17.4500, "UnitsInStock" : 29, "UnitsOnOrder" : 0, "ReorderLevel" : 10, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 17, "ProductName" : "Alice Mutton", "SupplierID" : 7, "CategoryID" : 6, "QuantityPerUnit" : "20 - 1 kg tins", "UnitPrice" : 39.0000, "UnitsInStock" : 0, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 6, "CategoryName" : "Meat/Poultry", "Description" : "Prepared meats" } }, { "ProductID" : 18, "ProductName" : "Carnarvon Tigers", "SupplierID" : 7, "CategoryID" : 8, "QuantityPerUnit" : "16 kg pkg.", "UnitPrice" : 62.5000, "UnitsInStock" : 42, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 8, "CategoryName" : "Seafood", "Description" : "Seaweed and fish" } }, { "ProductID" : 19, "ProductName" : "Teatime Chocolate Biscuits", "SupplierID" : 8, "CategoryID" : 3, "QuantityPerUnit" : "10 boxes x 12 pieces", "UnitPrice" : 9.2000, "UnitsInStock" : 25, "UnitsOnOrder" : 0, "ReorderLevel" : 5, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 20, "ProductName" : "Sir Rodney's Marmalade", "SupplierID" : 8, "CategoryID" : 3, "QuantityPerUnit" : "30 gift boxes", "UnitPrice" : 81.0000, "UnitsInStock" : 40, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 21, "ProductName" : "Sir Rodney's Scones", "SupplierID" : 8, "CategoryID" : 3, "QuantityPerUnit" : "24 pkgs. x 4 pieces", "UnitPrice" : 10.0000, "UnitsInStock" : 3, "UnitsOnOrder" : 40, "ReorderLevel" : 5, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 22, "ProductName" : "Gustaf's Knäckebröd", "SupplierID" : 9, "CategoryID" : 5, "QuantityPerUnit" : "24 - 500 g pkgs.", "UnitPrice" : 21.0000, "UnitsInStock" : 104, "UnitsOnOrder" : 0, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 5, "CategoryName" : "Grains/Cereals", "Description" : "Breads, crackers, pasta, and cereal" } }, { "ProductID" : 23, "ProductName" : "Tunnbröd", "SupplierID" : 9, "CategoryID" : 5, "QuantityPerUnit" : "12 - 250 g pkgs.", "UnitPrice" : 9.0000, "UnitsInStock" : 61, "UnitsOnOrder" : 0, "ReorderLevel" : 25, "Discontinued" : false, "Category" : { "CategoryID" : 5, "CategoryName" : "Grains/Cereals", "Description" : "Breads, crackers, pasta, and cereal" } }, { "ProductID" : 24, "ProductName" : "Guaraná Fantástica", "SupplierID" : 10, "CategoryID" : 1, "QuantityPerUnit" : "12 - 355 ml cans", "UnitPrice" : 4.5000, "UnitsInStock" : 20, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 1, "CategoryName" : "Beverages", "Description" : "Soft drinks, coffees, teas, beers, and ales" } }, { "ProductID" : 25, "ProductName" : "NuNuCa Nuß-Nougat-Creme", "SupplierID" : 11, "CategoryID" : 3, "QuantityPerUnit" : "20 - 450 g glasses", "UnitPrice" : 14.0000, "UnitsInStock" : 76, "UnitsOnOrder" : 0, "ReorderLevel" : 30, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 26, "ProductName" : "Gumbär Gummibärchen", "SupplierID" : 11, "CategoryID" : 3, "QuantityPerUnit" : "100 - 250 g bags", "UnitPrice" : 31.2300, "UnitsInStock" : 15, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 27, "ProductName" : "Schoggi Schokolade", "SupplierID" : 11, "CategoryID" : 3, "QuantityPerUnit" : "100 - 100 g pieces", "UnitPrice" : 43.9000, "UnitsInStock" : 49, "UnitsOnOrder" : 0, "ReorderLevel" : 30, "Discontinued" : false, "Category" : { "CategoryID" : 3, "CategoryName" : "Confections", "Description" : "Desserts, candies, and sweet breads" } }, { "ProductID" : 28, "ProductName" : "Rössle Sauerkraut", "SupplierID" : 12, "CategoryID" : 7, "QuantityPerUnit" : "25 - 825 g cans", "UnitPrice" : 45.6000, "UnitsInStock" : 26, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 7, "CategoryName" : "Produce", "Description" : "Dried fruit and bean curd" } }, { "ProductID" : 29, "ProductName" : "Thüringer Rostbratwurst", "SupplierID" : 12, "CategoryID" : 6, "QuantityPerUnit" : "50 bags x 30 sausgs.", "UnitPrice" : 123.7900, "UnitsInStock" : 0, "UnitsOnOrder" : 0, "ReorderLevel" : 0, "Discontinued" : true, "Category" : { "CategoryID" : 6, "CategoryName" : "Meat/Poultry", "Description" : "Prepared meats" } }, { "ProductID" : 30, "ProductName" : "Nord-Ost Matjeshering", "SupplierID" : 13, "CategoryID" : 8, "QuantityPerUnit" : "10 - 200 g glasses", "UnitPrice" : 25.8900, "UnitsInStock" : 10, "UnitsOnOrder" : 0, "ReorderLevel" : 15, "Discontinued" : false, "Category" : { "CategoryID" : 8, "CategoryName" : "Seafood", "Description" : "Seaweed and fish" } }];
Now open src/app/app.module.ts and add the following lines to define the Kendo grid component:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { GridModule } from '@progress/kendo-angular-grid'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpModule, GridModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Now open src/app/app.component.html and add the following lines to add a Kendo grid to the app’s template:
<h1> {{title}} </h1> <kendo-grid [data]="gridData" [height]="370"> <kendo-grid-column field="ProductID" title="ID" width="40"> </kendo-grid-column> <kendo-grid-column field="ProductName" title="Name" width="250"> </kendo-grid-column> <kendo-grid-column field="Category.CategoryName" title="Category"> </kendo-grid-column> <kendo-grid-column field="UnitPrice" title="Price" width="80"> </kendo-grid-column> <kendo-grid-column field="UnitsInStock" title="In stock" width="80"> </kendo-grid-column> <kendo-grid-column field="Discontinued" title="Discontinued" width="120"> <template kendoGridCellTemplate let-dataItem> <input type="checkbox" [checked]="dataItem.Discontinued" disabled/> </template> </kendo-grid-column> </kendo-grid>
In src/app/app.component.ts, add the following lines to import the sample data and expose it as a bindable property of the component:
import { Component } from '@angular/core'; import { products } from './products'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'It\'s Alive!'; private gridData: any[] = products; }
Now run it again with “npm start” and it should look something like this:
Looks good! We got it all now, except for some styling.
Styling the Kendo Grid
To style the grid, let’s add one line to angular-cli.json in the root directory of the project:
{ ... "apps": [ { ... "styles": [ "styles.css", "../node_modules/@progress/kendo-theme-default/dist/all.css" ], ... } ], ... }
And now we have a styled Kendo Grid in Angular2!
I’m including the complete code for download if you’d like to see the finished product.