You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
abp/docs/en/Community-Articles/2020-08-18-DevExtreme-With-ABP/Using-DevExtreme-In-ABP-Bas...

303 lines
11 KiB

## Using DevExtreme with ABP Based Applications
Hi, in this step by step article, I will show you how to integrate DevExtreme components into ABP Framework based applications.
![both-example-result](both-example-result.png)
## Create the Project
4 years ago
ABP Framework offers startup templates to get into the business faster. We can download a new startup template using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI):
4 years ago
````bash
abp new DevExtremeSample
````
4 years ago
After the download is finished, open the solution in the Visual Studio (or your favorite IDE):
4 years ago
![initial-project](initial-project.png)
Run the `DevExtremeSample.DbMigrator` application to create the database and seed initial data (which creates the admin user, admin role, related permissions, etc). Then we can run the `DevExtremeSample.Web` project to see our application working.
> _Default admin username is **admin** and password is **1q2w3E\***_
4 years ago
## Install DevExtreme
You can follow [this documentation](https://js.devexpress.com/Documentation/17_1/Guide/ASP.NET_MVC_Controls/Prerequisites_and_Installation/) to install DevExpress packages into your computer.
> Don't forget to add _"DevExpress NuGet Feed"_ to your **Nuget Package Sources**.
### Adding DevExtreme NuGet Packages
Add the `DevExtreme.AspNet.Core` NuGet package to the `DevExtremeSample.Application.Contracts` project.
4 years ago
```
Install-Package DevExtreme.AspNet.Core
4 years ago
```
Add the `DevExtreme.AspNet.Data` package to your `DevExtremeSample.Web` project.
```
Install-Package DevExtreme.AspNet.Data
4 years ago
```
### Adding DevExtreme NPM Dependencies
4 years ago
Open your `DevExtremeSample.Web` project folder with a command line and add `devextreme` and `devextreme-aspnet-data` NPM packages:
4 years ago
````bash
npm install devextreme
````
4 years ago
````bash
npm install devextreme-aspnet-data
````
4 years ago
### Adding Resource Mappings
The `devextreme` and `devextreme-aspnet-data` NPM packages are saved under `node_modules` folder. We need to move the needed files in our `wwwroot/libs` folder to use them in our web project. We can do it using the ABP [client side resource mapping](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Client-Side-Package-Management) system.
4 years ago
Open the `abp.resourcemapping.js` file in your `DevExtremeSample.Web` project and add the following definitions to inside `mappings` object.
4 years ago
````json
"@node_modules/devextreme/dist/**/*": "@libs/devextreme/",
"@node_modules/devextreme-aspnet-data/js/dx.aspnet.data.js": "@libs/devextreme/js/"
````
4 years ago
The final `abp.resourcemapping.js` file should look like below:
4 years ago
```
module.exports = {
aliases: {},
mappings: {
"@node_modules/devextreme/dist/**/*": "@libs/devextreme/",
"@node_modules/devextreme-aspnet-data/js/dx.aspnet.data.js": "@libs/devextreme/"
4 years ago
},
};
```
Open your `DevExtremeSample.Web` project folder with a command line and run the `gulp` command. This command will copy the needed library files into the ``/wwwroot/libs/devextreme/` folder.
4 years ago
![gulp](gulp.png)
You can see `devextreme` folder inside the `wwwroot/libs`:
4 years ago
![wwwroot-lib](wwwroot-lib.png)
### Adding DevExtremeStyleContributor
We will add DevExtreme CSS files to the global bundle by creating a [bundle contributor](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Bundling-Minification).
4 years ago
Create a `Bundling` folder in the `DevExtremeSample.Web` project and a `DevExtremeStyleContributor.cs` file with the following content:
4 years ago
```csharp
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace DevExtremeSample.Web.Bundling
{
public class DevExtremeStyleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/devextreme/css/dx.common.css");
context.Files.AddIfNotContains("/libs/devextreme/css/dx.light.css");
}
}
}
```
> You can choose another theme than the light theme. Check the `/libs/devextreme/css/` folder and the DevExtreme documentation for other themes.
Open your `DevExtremeSampleWebModule.cs` file in your `DevExtremeSample.Web` project and add following code into the `ConfigureServices` method:
4 years ago
```csharp
Configure<AbpBundlingOptions>(options =>
{
options
.StyleBundles
.Get(StandardBundles.Styles.Global)
.AddContributors(typeof(DevExtremeStyleContributor));
});
```
### Adding DevExtremeScriptContributor
We can not add DevExtreme js packages to Global Script Bundles, just like done for the CSS files. Because DevExtreme requires to add its JavaScript files into the `<head>` section of the HTML document, while ABP Framework adds all JavaScript files to the end of the `<body>` (as a best practice).
4 years ago
Fortunately, ABP Framework has a [layout hook system](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-User-Interface#layout-hooks) that allows you to add any code into some specific positions in the HTML document. All you need to do is to create a `ViewComponent` and configure the layout hooks.
4 years ago
Let's begin by creating a `DevExtremeScriptContributor.cs` file in the `Bundling` folder by copying the following code inside it:
4 years ago
```csharp
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery;
using Volo.Abp.Modularity;
namespace DevExtremeSample.Web.Bundling
{
[DependsOn(
typeof(JQueryScriptContributor)
)]
public class DevExtremeScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/devextreme/js/dx.all.js");
context.Files.AddIfNotContains("/libs/devextreme/js/dx.aspnet.mvc.js");
context.Files.AddIfNotContains("/libs/devextreme/js/dx.aspnet.data.js");
}
}
}
```
As you see, the `DevExtremeScriptContributor` is depends on `JQueryScriptContributor` which adds JQuery related files before the DevExpress packages (see the [bundling system](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Bundling-Minification) for details).
4 years ago
#### Create DevExtremeJsViewComponent
Create a new view component, named `DevExtremeJsViewComponent` inside the `/Components/DevExtremeJs` folder of the Web project, by following the steps below:
4 years ago
1) Create a `DevExtremeJsViewComponent` class inside the `/Components/DevExtremeJs` (create the folders first):
4 years ago
```csharp
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
4 years ago
namespace DevExtremeSample.Web.Components.DevExtremeJs
{
public class DevExtremeJsViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
{
return View("/Components/DevExtremeJs/Default.cshtml");
}
}
}
```
2) Create `Default.cshtml` file in the same folder with the following content:
```csharp
@using DevExtremeSample.Web.Bundling
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
<abp-script type="typeof(DevExtremeScriptContributor)" />
```
Your final Web project should be like as the following:
4 years ago
![devextreme-js](devextreme-js.png)
3) Now, we can add this view component to `<head>` section by using the layout hooks.
4 years ago
Open your `DevExtremeSampleWebModule.cs` file in your `DevExtremeSample.Web` project and add following code into the `ConfigureServices` method:
4 years ago
```csharp
Configure<AbpLayoutHookOptions>(options =>
{
options.Add(
LayoutHooks.Head.Last, //The hook name
typeof(DevExtremeJsViewComponent) //The component to add
);
});
```
#### Known Issue: Uncaught TypeError: MutationObserver.observe: Argument 1 is not an object.
> This issue does exists in the ABP Framework v3.0 and earlier versions. If you are using ABP Framework v3.1 or a latter version, you can skip this section.
When you run your `*.Web` project, you will see an exception (`Uncaught TypeError: MutationObserver.observe: Argument 1 is not an object.`) at your console.
To fix that issue, download this file [abp.jquery.js](https://github.com/abpframework/abp/blob/dev/npm/packs/jquery/src/abp.jquery.js) and replace with the `wwwroot/libs/abp/jquery/abp.jquery.js` file of your Web project.
4 years ago
### Result
The installation step was done. You can use any DevExtreme component in your application.
4 years ago
Example: A button and a progress bar component:
4 years ago
![devexp-result](devexp-result.gif)
4 years ago
This example has been created by following [this documentation](https://js.devexpress.com/Demos/WidgetsGallery/Demo/ProgressBar/Overview/NetCore/Light/).
4 years ago
## The Sample Application
4 years ago
We have created a sample application with [Tree List](https://demos.devexpress.com/ASPNetCore/Demo/TreeList/Overview/) and [Data Grid](https://demos.devexpress.com/ASPNetCore/Demo/DataGrid/Overview/) examples.
### The Source Code
4 years ago
You can download the source code from [here](https://github.com/abpframework/abp-samples/tree/master/DevExtreme-Mvc).
### Data Grid
4 years ago
You can see the full working example of [Data Grid](https://demos.devexpress.com/ASPNetCore/Demo/DataGrid/Overview/).
![data-grid-final](data-grid-final.png)
The related files for this example are highlighted at the following screenshots.
![data-grid-app-contract](data-grid-app-contract.png)
![data-grid-application](data-grid-application.png)
![data-grid-web](data-grid-web.png)
### Tree List
You can see the full working example of [Tree List](https://demos.devexpress.com/ASPNetCore/Demo/TreeList/Overview/).
![tree-list-final](tree-list-final.png)
The related files for this example are highlighted at the following screenshots.
![tree-list-app-contract](tree-list-app-contract.png)
![tree-list-application](tree-list-application.png)
![tree-list-web](tree-list-web.png)
### Additional Notes
#### Data Storage
I've used an in-memory list to store data for this example, instead of a real database. Because it is not related to DevExpress usage. There is a `SampleDataService.cs` file in `Data` folder at `.Application.Contracts` project. All the data is stored here.
#### JSON Serialization
You can see some `JsonProperty` attributes on the DTO properties. I uses these attributes because DevExtreme example expects `PascalCase` property names in the serialized JSON that is sent to the client. But ABP Framework & ASP.NET Core conventionally uses `camelCase` property names on JSON serialization. Adding these `JsonProperty` attributes ensures that the related properties are serialized as `PascalCase`.
#### DevExtreme Components vs Application Service Methods
ABP Framework conventionally converts application services to API Controllers. For example, see the application service below:
````csharp
public class OrderAppService : DevExtremeSampleAppService, IOrderAppService
{
public async Task<LoadResult> GetOrdersAsync(DataSourceLoadOptions loadOptions)
{
...
}
public async Task<Order> InsertOrder(string values)
{
...
}
...
}
````
You can use these service methods for your DevExtreme components as shown below:
```csharp
Html.DevExtreme().DataGrid<Order>()
.DataSource(d => d.Mvc()
.Controller("Order") // Application Service Name without 'AppService'
.LoadAction("GetOrders") // Method Name without 'Async'
.InsertAction("InsertOrder")
.UpdateAction("UpdateOrder")
.DeleteAction("DeleteOrder")
.Key("OrderID")
)
```