@ -0,0 +1,313 @@ |
|||
## Using DevExtreme Angular Components With the ABP Framework |
|||
|
|||
Hello, this is a follow up on the article [Using DevExtreme Components With the ABP Framework](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) |
|||
|
|||
We will create the same application using Angular as the UI framework and integrate [DevExpress Angular components](https://js.devexpress.com/Documentation/Guide/Angular_Components/DevExtreme_Angular_Components/). |
|||
|
|||
## Create the Project |
|||
|
|||
For detail information about how to generate and start up a project, please refer to the [official docs](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No). For the scope of this post, we will not go into details of the backend applications. |
|||
|
|||
Let's create an application using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI#new) |
|||
|
|||
```shell |
|||
abp new DevExtremeAngular -u angular |
|||
``` |
|||
|
|||
After the project is created, you should run following projects in order |
|||
|
|||
 |
|||
|
|||
Firstly, run `DevExtremeAngular.DbMigrator` for db migration and then run `DevExtremeAngular.HttpApi.Host` for backend APIs. |
|||
|
|||
After the backend is ready, navigate to `angular` folder and run `yarn` or `npm install` based on which package you are using. |
|||
|
|||
After installation process is done, you can start your angular project by running `yarn start` or `npm start` |
|||
|
|||
Everything should run smoothly and when you go to http://localhost:4200 in the browser, you should see your application up and running. |
|||
|
|||
 |
|||
|
|||
You can login to the application by using following credentials |
|||
|
|||
> _Default admin username is **admin** and password is **1q2w3E\***_ |
|||
|
|||
 |
|||
|
|||
After successful login, you should be redirected to home page. |
|||
|
|||
## Install DevExtreme |
|||
|
|||
Let's start with installing DevExtreme into our project before writing any code. |
|||
|
|||
You can follow [the guide](https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started/Add_DevExtreme_to_an_Angular_CLI_Application/) provided by **DevExtreme** team or apply the following steps. |
|||
|
|||
* `npm install devextreme devextreme-angular` or `yarn add devextreme devextreme-angular` |
|||
* Import following two styles in `angular.json` |
|||
|
|||
```javascript |
|||
// ... |
|||
"styles": [ |
|||
// ... |
|||
"src/styles.scss", |
|||
"node_modules/devextreme/dist/css/dx.common.css", |
|||
"node_modules/devextreme/dist/css/dx.light.css" |
|||
] |
|||
``` |
|||
|
|||
* Add `dx-viewport` to classes of `body` in `index.html` |
|||
|
|||
```html |
|||
<body class="bg-light dx-viewport"> |
|||
<app-root> |
|||
<div class="donut centered"></div> |
|||
</app-root> |
|||
</body> |
|||
``` |
|||
|
|||
After completing these steps, you need to restart the angular application. |
|||
|
|||
## Create a lazy Angular Module for DevExtreme Demo |
|||
|
|||
Let's create a module which will be loaded lazily. |
|||
|
|||
Open up a terminal and navigate to `angular` to run following command. |
|||
|
|||
```shell |
|||
ng g m dev-extreme --route dev-extreme --module app |
|||
``` |
|||
|
|||
...or with `npx`, if you do not have `angular-cli` installed... |
|||
|
|||
```shell |
|||
npx ng g m dev-extreme --route dev-extreme --module app |
|||
``` |
|||
|
|||
Your terminal should log the following output: |
|||
|
|||
```shell |
|||
CREATE src/app/dev-extreme/dev-extreme-routing.module.ts (361 bytes) |
|||
CREATE src/app/dev-extreme/dev-extreme.module.ts (379 bytes) |
|||
CREATE src/app/dev-extreme/dev-extreme.component.scss (0 bytes) |
|||
CREATE src/app/dev-extreme/dev-extreme.component.html (26 bytes) |
|||
CREATE src/app/dev-extreme/dev-extreme.component.spec.ts (655 bytes) |
|||
CREATE src/app/dev-extreme/dev-extreme.component.ts (295 bytes) |
|||
UPDATE src/app/app-routing.module.ts (362 bytes) |
|||
``` |
|||
|
|||
The Angular CLI has created a module and configured it to lazy-load at `/dev-extreme` path. |
|||
|
|||
The last step to be able to see our newly created module in the browser, open `route.provider.ts` and edit the array being added into the routes. |
|||
|
|||
```typescript |
|||
// ... |
|||
routes.add([ |
|||
{ |
|||
path: '/', |
|||
name: '::Menu:Home', |
|||
iconClass: 'fas fa-home', |
|||
order: 1, |
|||
layout: eLayoutType.application, |
|||
}, |
|||
{ |
|||
path: '/dev-extreme', |
|||
name: 'Dev Extreme', |
|||
order: 2, |
|||
layout: eLayoutType.application, |
|||
}, |
|||
]); |
|||
// ... |
|||
``` |
|||
|
|||
After completing the steps above, you should be able to see `Dev Extreme` on the header and when you click on it, you should be redirected to `/dev-extreme` page and see the following message on the screen. |
|||
|
|||
 |
|||
|
|||
## Display users on the dev-extreme page |
|||
|
|||
For this demo, we will list users on the screen. We already have `admin` as our first user. |
|||
|
|||
Let's add couple of more to the list in `Administration -> Identity Management -> Users` page. |
|||
|
|||
 |
|||
|
|||
Now we are ready to fetch our users and display them on `/dev-extreme` page. |
|||
|
|||
Firstly, let's create a service for our component. |
|||
|
|||
Navigate to the `dev-extreme` folder and run following command. If you run this command at the root, the service will be generated next to `app.module.ts` |
|||
|
|||
```shell |
|||
ng g s dev-extreme |
|||
``` |
|||
|
|||
Following files should be created |
|||
|
|||
```shell |
|||
CREATE src/app/dev-extreme/dev-extreme.service.spec.ts (378 bytes) |
|||
CREATE src/app/dev-extreme/dev-extreme.service.ts (139 bytes) |
|||
``` |
|||
|
|||
Let's import and inject `IdentityService` as dependency in `dev-extreme.service.ts`. After then, let's create a stream called `users$` to retrieve the users. |
|||
|
|||
`identityService.getUsers` returns `ABP.PagedResponse` which contains two fields, `items` and `totalCount`. We are only interested in `items` for now. |
|||
|
|||
When we apply the steps described above, the final version of `dev-extreme.service` should be as follows |
|||
|
|||
```typescript |
|||
import { Injectable } from '@angular/core'; |
|||
import { map } from 'rxjs/operators'; |
|||
import { IdentityService } from '@abp/ng.identity'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class DevExtremeService { |
|||
users$ = this.service.getUsers().pipe(map((result) => result.items)); |
|||
|
|||
constructor(private service: IdentityService) {} |
|||
} |
|||
``` |
|||
|
|||
Now we can simply inject `DevExtremeService` as public and utilize `users$` stream in `dev-extreme.component.ts` as follows: |
|||
|
|||
```typescript |
|||
import { Component } from '@angular/core'; |
|||
import { DevExtremeService } from './dev-extreme.service'; |
|||
|
|||
@Component({ |
|||
selector: 'app-dev-extreme', |
|||
templateUrl: './dev-extreme.component.html', |
|||
styleUrls: ['./dev-extreme.component.scss'], |
|||
}) |
|||
export class DevExtremeComponent { |
|||
constructor(public service: DevExtremeService) {} |
|||
} |
|||
``` |
|||
|
|||
And use it within `dev-extreme.component.html` |
|||
|
|||
```html |
|||
<ng-container *ngIf="service.users$ | async as users"> |
|||
<ul> |
|||
<li *ngFor="let user of users"> |
|||
{{ user.name }} |
|||
</li> |
|||
</ul> |
|||
</ng-container> |
|||
``` |
|||
|
|||
This should list names of the users on the screen |
|||
|
|||
 |
|||
|
|||
## Use DxDataGrid to list the users |
|||
|
|||
You can take a look at [demo](https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/ColumnCustomization/Angular/Light/) provided by **DevExtreme** team or apply the following steps. |
|||
|
|||
Now, our application is ready to use `dx-data-grid` in `dev-extreme.component.ts` |
|||
|
|||
Firstly, we need to import `DxDataGridModule` in our module as follows. |
|||
|
|||
```typescript |
|||
// ... |
|||
|
|||
import { DxDataGridModule } from 'devextreme-angular'; |
|||
|
|||
@NgModule({ |
|||
// ... |
|||
imports: [ |
|||
// ... |
|||
DxDataGridModule |
|||
], |
|||
}) |
|||
export class DevExtremeModule {} |
|||
``` |
|||
|
|||
At this point `dx-data-grid` is avaliable within our module and we can use it in our template. |
|||
|
|||
Change `dev-extreme.component.html` to the following |
|||
|
|||
```html |
|||
<ng-container *ngIf="service.users$ | async as users"> |
|||
<dx-data-grid [dataSource]="users"></dx-data-grid> |
|||
</ng-container> |
|||
``` |
|||
|
|||
It should display a table on the screen |
|||
|
|||
 |
|||
|
|||
Since, we did not specify any columns, `dx-data-grid` displayed every column avaliable. Let's pick some columns to make it more readable. |
|||
|
|||
Change `dev-extreme.component.html` to the following |
|||
|
|||
```html |
|||
<ng-container *ngIf="service.users$ | async as users"> |
|||
<dx-data-grid [dataSource]="users"> |
|||
<dxi-column dataField="userName"></dxi-column> |
|||
<dxi-column dataField="name"></dxi-column> |
|||
<dxi-column dataField="surname"></dxi-column> |
|||
<dxi-column dataField="email"></dxi-column> |
|||
<dxi-column dataField="phoneNumber"></dxi-column> |
|||
</dx-data-grid> |
|||
</ng-container> |
|||
``` |
|||
|
|||
which will display following table on the screen |
|||
|
|||
 |
|||
|
|||
We can also utilize `abpLocalization` pipe to translate the headers of the table. To use `abpLocalization` pipe in our templates, we need to import `CoreModule` from `@abp/ng.core` into our module. |
|||
|
|||
```typescript |
|||
import { CoreModule } from '@abp/ng.core'; |
|||
|
|||
@NgModule({ |
|||
// ... |
|||
imports: [ |
|||
// ... |
|||
CoreModule |
|||
], |
|||
}) |
|||
export class DevExtremeModule {} |
|||
``` |
|||
|
|||
And change the template to the following |
|||
|
|||
```html |
|||
<ng-container *ngIf="service.users$ | async as users"> |
|||
<dx-data-grid [dataSource]="users"> |
|||
<dxi-column |
|||
dataField="userName" |
|||
[caption]="'AbpIdentity::DisplayName:UserName' | abpLocalization" |
|||
></dxi-column> |
|||
<dxi-column |
|||
dataField="name" |
|||
[caption]="'AbpIdentity::DisplayName:Name' | abpLocalization" |
|||
></dxi-column> |
|||
<dxi-column |
|||
dataField="surname" |
|||
[caption]="'AbpIdentity::DisplayName:Surname' | abpLocalization" |
|||
></dxi-column> |
|||
<dxi-column |
|||
dataField="email" |
|||
[caption]="'AbpIdentity::DisplayName:Email' | abpLocalization" |
|||
></dxi-column> |
|||
<dxi-column |
|||
dataField="phoneNumber" |
|||
[caption]="'AbpIdentity::DisplayName:PhoneNumber' | abpLocalization" |
|||
></dxi-column> |
|||
</dx-data-grid> |
|||
</ng-container> |
|||
``` |
|||
|
|||
The headers should change when a new language is selected |
|||
|
|||
 |
|||
|
|||
## Conclusion |
|||
|
|||
In this article, we have seen how to integrate `DevExtreme` angular components into a project generated by `ABP CLI` |
|||
|
|||
You can download the code of [the demo here](https://github.com/abpframework/abp-samples/tree/master/DevExtreme-Angular) |
|||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 828 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 42 KiB |