mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
New tutorial about: Working with DataTable. (#3199)
New tutorial about: Working with DataTable
This commit is contained in:
committed by
Eugenio Romano
parent
782893838f
commit
0ff0573401
BIN
docs/docassets/images/data_table_action.png
Normal file
BIN
docs/docassets/images/data_table_action.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
BIN
docs/docassets/images/data_table_action2.png
Normal file
BIN
docs/docassets/images/data_table_action2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
BIN
docs/docassets/images/data_table_contentProjection.png
Normal file
BIN
docs/docassets/images/data_table_contentProjection.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
docs/docassets/images/data_table_dataSource.png
Normal file
BIN
docs/docassets/images/data_table_dataSource.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
docs/docassets/images/data_table_rowClick.png
Normal file
BIN
docs/docassets/images/data_table_rowClick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
docs/docassets/images/data_table_static.png
Normal file
BIN
docs/docassets/images/data_table_static.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@@ -15,6 +15,7 @@ The tutorials are graded as follows:
|
|||||||
| Name | Level | Abstract |
|
| Name | Level | Abstract |
|
||||||
| -- | -- | -- |
|
| -- | -- | -- |
|
||||||
| [**Preparing the development environment**](preparing-environment.md) | Beginner | In this content is shared all the prerequisites valid for all the tutorials and descriptions of the entire documentation. This content contains the development environment description, along with the details of the suggested versions for each tools, library or module. |
|
| [**Preparing the development environment**](preparing-environment.md) | Beginner | In this content is shared all the prerequisites valid for all the tutorials and descriptions of the entire documentation. This content contains the development environment description, along with the details of the suggested versions for each tools, library or module. |
|
||||||
| [**Adding a new component**](new-component.md) | | By definition a _component_ controls a patch of screen called a view. As an example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion of layout of an application. In this tutorial you will learn how to create a component using [Angular CLI](https://cli.angular.io/). After the creation you will learn how to add it to an existing application. |
|
| [**Adding a new component**](new-component.md) | Beginner | By definition a _component_ controls a patch of screen called a view. As an example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion of layout of an application. In this tutorial you will learn how to create a component using [Angular CLI](https://cli.angular.io/). After the creation you will learn how to add it to an existing application. |
|
||||||
| [**Adding a new component**](new-view.md) | Beginner | By definition a _component_ controls a patch of screen called a view. As an example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion of layout of an application. In this tutorial you will learn how to create a component using [Angular CLI](https://cli.angular.io/). After the creation you will learn how to add it to an existing application. |
|
| [**Adding a new view**](new-view.md) | Beginner | Every application developed in Angular is a single page application where the concepts of _view_ and _routing_ play a key role in the user experience. Being a single page application, the navigation between the different layouts (called _views_) is enabled through the _routing_. In this tutorial you will learn how to create a new view into your application and how to have access to it using a defined endpoint. |
|
||||||
| [**Using components**](using-components.md) | Beginner | There are three different ways to use, extend and configure an ADF component: configuration properties, event listeners, content projection / HTML extensions. In this tutorial you are going to see a practical example for each approach. As an example, the Login component will be used. |
|
| [**Using components**](using-components.md) | Beginner | There are three different ways to use, extend and configure an ADF component: configuration properties, event listeners, content projection / HTML extensions. In this tutorial you are going to see a practical example for each approach. As an example, the Login component will be used. |
|
||||||
|
| [**Working with a DataTable**](working-with-data-table.md) | Intermediate | In this tutorial you will learn how to populate a DataTable component, with custom data coming from a generic back-end service or third party API. |
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# Adding a new component
|
# Adding a new component
|
||||||
|
|
||||||
By definition a *component* controls a patch of screen called a view. As an example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion of layout of an application. In this tutorial you will learn how to create a component using [Angular CLI](https://cli.angular.io/). After the creation you will learn how to add it to an existing application.
|
By definition a *component* controls a patch of screen called a view. As an example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion of layout of an application. In this tutorial you will learn how to create a component using [Angular CLI](https://cli.angular.io/). After the creation you will learn how to add it to an existing application.
|
||||||
|
v
|
||||||
## Creating a component
|
## Creating a component
|
||||||
Starting from the root of your project, run the following command into a terminal.
|
Starting from the root of your project, run the following command into a terminal.
|
||||||
|
|
||||||
@@ -32,4 +32,4 @@ To make the component usable, one or more modules should declare it (or import i
|
|||||||
MyFirstComponentComponent
|
MyFirstComponentComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
These are the very basic information you should be know about your brand new component. All you have read here is standard Angular, not customised or valid for ADF applications only.
|
These are the very basic information you should know about your brand new component. All you have read here is standard Angular, not customised or valid for ADF applications only.
|
||||||
|
@@ -1,38 +1,112 @@
|
|||||||
---
|
---
|
||||||
Level: Beginner
|
Level: Beginner
|
||||||
---
|
---
|
||||||
# Adding a new component
|
# Adding a new view
|
||||||
|
|
||||||
By definition a *component* controls a patch of screen called a view. As an example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion of layout of an application. In this tutorial you will learn how to create a component using [Angular CLI](https://cli.angular.io/). After the creation you will learn how to add it to an existing application.
|
Every application developed in Angular is a single page application where the concepts of *view* and *routing* play a key role in the user experience. Being a single page application, the navigation between the different layouts (called *views*) is enabled through the *routing*. In this tutorial you will learn how to create a new view into your application and how to have access to it using a defined endpoint.
|
||||||
|
|
||||||
## Creating a component
|
## Creating a view
|
||||||
Starting from the root of your project, run the following command into a terminal.
|
Into an Angular application, a view is implemented by a regular component. A view can use other views (so other components), but a view can be used to implement the full layout of your application. This is the reason why creating a view is the task than creating a component.
|
||||||
|
|
||||||
ng generate component my-first-component
|
To create a view, run the following command into a terminal, starting from the root of your project.
|
||||||
|
|
||||||
If you are adding the component to an application with more than one module, you might want to specify it using the `--module` parameter. For example use `--module app` to add the new component to the root app of your application.
|
ng generate component my-first-view
|
||||||
|
|
||||||
## Using the component
|
For further details about creating a component, you can refer to the tutorial here (link to "Adding a new component").
|
||||||
Once done, wherever you will use `<app-my-first-component></app-my-first-component>` into the HTML file of another component, you will see the content of the new component rendered exactly in that place.
|
|
||||||
|
|
||||||
As an example, add `<app-my-first-component></app-my-first-component>` on top of the `app.component.html` file stored into the `src` folder, and run the application again. Directly in the browser you will see `my-first-component works!`, that shows exactly the place where the component is rendered in the layout.
|
## Routing the view
|
||||||
|
An Angular application has one singleton instance of the `Router` service that is used to match the browser's URL with the corresponding component to display. The `Router` service must be configured in a typescript file (usually in the , in with a syntax similar to the following source code.
|
||||||
|
|
||||||
## Anatomy of the component
|
const appRoutes: Routes = [
|
||||||
By default the new component is created into the `src/app` path and everything is stored in a folder named like the component itself. In this example a folder named with `my-first-component` is added to `src/app`, with inside the following content:
|
{ path: 'path-in-the-app', component: ExistingComponent },
|
||||||
|
{ path: '**', component: PageNotFoundComponent }
|
||||||
- `my-first-component.component.scss` containing the CSS used by the component. This file is created as empty.
|
];
|
||||||
- `my-first-component.component.html` containing the HTML used to render the component. This file is created with a very basic message rendering the name of the component included in a `p` tag.
|
|
||||||
- `my-first-component.component.spec.ts` containing the unit tests for the component.
|
|
||||||
- `my-first-component.component.ts` containing the `MyFirstComponentComponent` class implementing the business logic in typescript.
|
|
||||||
|
|
||||||
To make the component usable, one or more modules should declare it (or import it). In this example the `app.module.ts` file stored into the `src/app` folder contains the following code.
|
|
||||||
|
|
||||||
import { MyFirstComponentComponent } from './my-first-component/my-first-component.component';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
imports: [
|
||||||
...
|
RouterModule.forRoot(
|
||||||
MyFirstComponentComponent
|
appRoutes,
|
||||||
|
{ enableTracing: true } // <-- debugging purposes only.
|
||||||
|
)
|
||||||
|
// other imports here
|
||||||
],
|
],
|
||||||
|
...
|
||||||
|
})
|
||||||
|
|
||||||
|
To add the new view to the routing, change the `appRoutes` constant as follow.
|
||||||
|
|
||||||
|
const appRoutes: Routes = [
|
||||||
|
{ path: 'path-in-the-app', component: ExistingComponent },
|
||||||
|
{ path: 'my-first-view', component: MyFirstViewComponent }, // <-- Add this!
|
||||||
|
{ path: '**', component: PageNotFoundComponent }
|
||||||
|
];
|
||||||
|
|
||||||
|
And remember to import the component in the same file with the following syntax.
|
||||||
|
|
||||||
|
import { MyFirstViewComponent } from './my-first-view/my-first-view.component';
|
||||||
|
|
||||||
|
Be aware that the `Router` service can be declared in a file that can be stored in different places in the application's structure. Usually the place where the `Router` service is declared is closed to the file containing the root module.
|
||||||
|
|
||||||
|
## Testing the view
|
||||||
|
To render the new view through the application and check the user experience, restart the application and open a browser to the following URL.
|
||||||
|
|
||||||
|
http://<ip_address>:<port>/my-first-view
|
||||||
|
|
||||||
|
The result should be a very simple page with the following content.
|
||||||
|
|
||||||
|
my-first-view works!
|
||||||
|
|
||||||
|
## View parameters (optional)
|
||||||
|
|
||||||
|
In most of the use cases, you might want to add parameters to the view's endpoint. To develop this, change the `appRoutes` constant as follow.
|
||||||
|
|
||||||
|
const appRoutes: Routes = [
|
||||||
|
{ path: 'path-in-the-app', component: ExistingComponent },
|
||||||
|
{ path: 'my-first-view/:name', component: MyFirstViewComponent }, // <-- Add this!
|
||||||
|
{ path: '**', component: PageNotFoundComponent }
|
||||||
|
];
|
||||||
|
|
||||||
|
Then open the typescript controller for the `MyFirstViewComponent` stored into `src/app/my-first-view` (`my-first-view.component.ts`) where few things need to happen:
|
||||||
|
|
||||||
|
1. We need to `import` and `inject` the router into the class.
|
||||||
|
2. Subscribe to the router parameters and fetch the value.
|
||||||
|
3. Unsubscribe to the router parameters.
|
||||||
|
|
||||||
|
While #3 isn't strictly required, it would eventually cause a memory leak in your application: please remember to unsubscribe!
|
||||||
|
|
||||||
|
Modify the typescript controller `my-first-view.component.ts` to look like this:
|
||||||
|
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-my-first-view',
|
||||||
|
templateUrl: './my-first-view.component.html',
|
||||||
|
styleUrls: ['./my-first-view.component.scss']
|
||||||
|
})
|
||||||
|
export class MyFirstViewComponent implements OnInit {
|
||||||
|
|
||||||
|
private params: any;
|
||||||
|
name: String;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.params = this.route.params.subscribe(params => {
|
||||||
|
this.name = params['name'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.params.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Next open the template `my-first-view.component.html` in the same folder and print out the greeting like the following source code.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Hello {{ name }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
You can now navigate to `http://<ip_address>:<port>/my-first-view/sir` and see the nice message "Hello sir".
|
||||||
|
|
||||||
These are the very basic information you should be know about your brand new component. All you have read here is standard Angular, not customised or valid for ADF applications only.
|
|
||||||
|
108
docs/tutorials/using-conponents.md
Normal file
108
docs/tutorials/using-conponents.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
---
|
||||||
|
Level: Beginner
|
||||||
|
---
|
||||||
|
# Using components
|
||||||
|
In this tutorial you will learn the common basics on using ADF components and Angular components in general.
|
||||||
|
|
||||||
|
The best option you should consider when you plan to use an ADF component and want to learn the details of its usage, is always to check the documentation for the component you are looking to use. More in general, there are three different ways to use, extend and configure an ADF component:
|
||||||
|
1. Configuration properties.
|
||||||
|
2. Event listeners.
|
||||||
|
3. Content projection / HTML extensions.
|
||||||
|
|
||||||
|
In this tutorial you are going to see a practical example for each approach. As an example, the [Login component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) will be used.
|
||||||
|
|
||||||
|
## Configuration properties
|
||||||
|
Angular components can easily be configured via properties in the HTML template. In this example we will act on the "Remember me" check and "Need Help?" + "Register" links in the footer of the Login component.
|
||||||
|
|
||||||
|
To prepare the task, be sure you have an ADF application up and running by executing `npm start` in a terminal, from the root folder of the project. Access to the login page using your browser and edit the `login.component.html` file stored into the `src/app/.../login` folder. The content of the `login.component.html` file should look like the following source code.
|
||||||
|
|
||||||
|
<adf-login
|
||||||
|
copyrightText="© 2017 - 2018 Alfresco Software, Inc. All rights reserved."
|
||||||
|
providers="ECM"
|
||||||
|
...
|
||||||
|
>
|
||||||
|
</adf-login>
|
||||||
|
|
||||||
|
When reviewing the documentation you can see that the `<adf-login/>` component has a lot of different properties. As an example we will toggle `showRememberMe` and `showLoginActions` (all set to `true` by default). If not already specified, add both the properties both with the false value, using the syntax described below in the example. If the properties are defined in the HTML template, toggle the value according to what you see in the source code (set them to `true` if they have the `false` value and viceversa).
|
||||||
|
|
||||||
|
<adf-login
|
||||||
|
copyrightText="© 2017 - 2018 Alfresco Software, Inc. All rights reserved."
|
||||||
|
providers="ECM"
|
||||||
|
[showRememberMe]="..."
|
||||||
|
[showLoginActions]="..."
|
||||||
|
...
|
||||||
|
>
|
||||||
|
</adf-login>
|
||||||
|
|
||||||
|
Once saved the HTML template you will see the login page updated with a different layout accordingly with the property values.
|
||||||
|
|
||||||
|
**Notice:** The two new properties are specified with `[]` around them. There are three ways to configure a component.
|
||||||
|
|
||||||
|
1. `[property]=""` This will be an expression or property from the typescript controller. Use this for boolean expressions or variables.
|
||||||
|
2. `property=""` This will be passed in as raw text.
|
||||||
|
3. `[(property)]` This is called *banana in a box* and is used for two way binding.
|
||||||
|
|
||||||
|
## Event listeners
|
||||||
|
|
||||||
|
Now that you've successfully configured properties on the `<adf-login/>` component, it's time to look at the events.
|
||||||
|
|
||||||
|
As we did for the previous task, looking at the [Login component documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) we can see that it emits three events `success`, `error` and `executeSubmit`.
|
||||||
|
|
||||||
|
We can subscribe to these events and have our custom code executed once these events are emitted. Let's hook into the `executeSubmit` and do a simple `alert()` once the form is submitted.
|
||||||
|
|
||||||
|
Continue to edit the `login.component.html` file and add `(success)="mySuccessMethod($event)"` to the `<adf-login/>` component (the position is not relevant).
|
||||||
|
|
||||||
|
<adf-login
|
||||||
|
...
|
||||||
|
(executeSubmit)="myExecuteSubmitMethod($event)"
|
||||||
|
>
|
||||||
|
</adf-login>
|
||||||
|
|
||||||
|
Next you need to implement `myExecuteSubmitMethod` in the typescript class implementing the component. Edit the `login.component.ts` file stored in the same `src/app/.../login` folder and add the implementation of `myExecuteSubmitMethod` as follows.
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
...
|
||||||
|
})
|
||||||
|
export class LoginComponent {
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// Add this!
|
||||||
|
myExecuteSubmitMethod(event: any) {
|
||||||
|
alert('Form was submitted!');
|
||||||
|
console.log(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Save both the files and the login component will be refreshed in your browser. Enter random values for username and password and you should see the alert after pressing the submit button. Looking in the console of the browser, you'll see the `event` data containing all the details of the form.
|
||||||
|
|
||||||
|
**Bonus objective:** Add a custom logo and background to the login view.
|
||||||
|
|
||||||
|
## Content projection / HTML extensions
|
||||||
|
The last way a component can be configured or extended is through an approach called *Content projection*. This allows components to put placeholders in their template, allowing developers to "project" their own code or components into pre-defined locations within the component.
|
||||||
|
|
||||||
|
In regular HTML, elements can be nested, for example:
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<b>Here we have some bold text</b>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
We can use the same approach with ADF components to inject custom code or entire components into the ADF component. Going to the documentation you can find more details about which targets are in place.
|
||||||
|
|
||||||
|
The `<adf-login/>` component supports two targets: `login-header` and `login-footer`. Let's add a simple "Hello World" message in the footer. Edit the template `login.component.html` and add a new tag *inside* the `<adf-login/>` tag.
|
||||||
|
|
||||||
|
<adf-login
|
||||||
|
...
|
||||||
|
>
|
||||||
|
<login-footer>
|
||||||
|
<ng-template>
|
||||||
|
Hello World!
|
||||||
|
</ng-template>
|
||||||
|
</login-footer>
|
||||||
|
</adf-login>
|
||||||
|
|
||||||
|
Watch carefully that you place the `<login-footer/>` tag *inside* the `<adf-login/>` tag. Inside the `<login-footer/>` or `<login-header/>` tags you can put anything you want, as long as you wrap it inside an `<ng-template/>` tag. You can also source in custom or 3rd party components.
|
||||||
|
|
||||||
|
Once done, save the template and you should see a "Hello World!" message in the footer of your login page through your browser.
|
332
docs/tutorials/working-with-data-table.md
Normal file
332
docs/tutorials/working-with-data-table.md
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
---
|
||||||
|
Level: Intermediate
|
||||||
|
---
|
||||||
|
# Working with a Data Table
|
||||||
|
|
||||||
|
In this tutorial you will learn how to populate a [`DataTable` component](https://alfresco.github.io/adf-component-catalog/components/DataTableComponent.html), with custom data coming from a generic back-end service or third party API. As an example we are going to use the data coming from one of the available services on Alfresco Content Services, but nothing changes if you'd want to use an Alfresco Process Services endpoint or a third party API.
|
||||||
|
|
||||||
|
## Prerequisites and data source
|
||||||
|
|
||||||
|
Before diving deep into the technical description of the [`DataTable` component](https://alfresco.github.io/adf-component-catalog/components/DataTableComponent.html), let's start describing the development environment and its prerequisites.
|
||||||
|
|
||||||
|
In this tutorial we will start from an existing ADF application, developed to use (at least) Alfresco Content Services as service layer. To be faster and concentrated on the discussion about the Data Table, we suggest to use the [Alfresco Example Content Application](https://github.com/Alfresco/alfresco-content-app). The Alfresco Example Content Application is well documented [here](https://alfresco.github.io/alfresco-content-app/#/), and you can choose to [build it from the source code](https://alfresco.github.io/alfresco-content-app/#/build) or [run it in a Docker container](https://alfresco.github.io/alfresco-content-app/#/docker). If you'd prefer to create a brand new ADF application from scratch, nothing will really change and you should be able to follow the tutorial with success.
|
||||||
|
|
||||||
|
During the description of the current tutorial, the endpoint used to populate the Data Table component is the [`/people` service](https://api-explorer.alfresco.com/api-explorer/#!/people/listPeople) that lists all the users available into an Alfresco Content Services instance. The `/people` service is suitable for the purpose of this tutorial because it is available by default into the Alfresco Content Services REST API. As follow up, you could choose to use an Alfresco Process Services endpoint or a third party API. Below is shown the result of the [`/people` service](https://api-explorer.alfresco.com/api-explorer/#!/people/listPeople), as an example.
|
||||||
|
|
||||||
|
{
|
||||||
|
"list": {
|
||||||
|
"pagination": {
|
||||||
|
"count": 46,
|
||||||
|
"hasMoreItems": false,
|
||||||
|
"totalItems": 46,
|
||||||
|
"skipCount": 0,
|
||||||
|
"maxItems": 100
|
||||||
|
},
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"entry": {
|
||||||
|
"firstName": "Jay",
|
||||||
|
"lastName": "Veeru",
|
||||||
|
"emailNotificationsEnabled": true,
|
||||||
|
"company": {},
|
||||||
|
"id": "JayVeeru2",
|
||||||
|
"enabled": true,
|
||||||
|
"email": "JayVeeru@test.con"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## Adding a page using the `DataTable` component
|
||||||
|
|
||||||
|
Starting from the ADF application, let's add a new component, developing a new page and containing a basic `DataTable` component. Top add a new page to the application, open a terminal and move into the root of the application, then run the following command.
|
||||||
|
|
||||||
|
ng g c mydatatable -m app.module
|
||||||
|
|
||||||
|
Into the `src/app/mydatatable` folder you should find the four files with extension `html`, `scss`, `spec.ts` and `ts`, developing the new page.
|
||||||
|
|
||||||
|
To add the new page to the routing of the we application, edit the `Routes` instance into the `app.routes,ts` if you are using the Alfresco Example Content Application or directly into the `app.module.ts` if you built the application using the standard Angular-CLI.
|
||||||
|
|
||||||
|
To define the new routing, check the following import is included in the file.
|
||||||
|
|
||||||
|
import {MydatatableComponent} from './mydatatable/mydatatable.component';
|
||||||
|
|
||||||
|
Then add a new item to the `Routes` instance, as described below.
|
||||||
|
|
||||||
|
export const APP_ROUTES: Routes = [
|
||||||
|
...,
|
||||||
|
{
|
||||||
|
path: 'mydatatable',
|
||||||
|
component: MydatatableComponent
|
||||||
|
},
|
||||||
|
...
|
||||||
|
];
|
||||||
|
|
||||||
|
Since then, the page will be available at the URL `http://localhost:3000/#/mydatatable`, if you start from the Alfresco Example Content Application.
|
||||||
|
|
||||||
|
Now that the new page is correctly developed, let's add the `DataTable` component into it. To complete the task, open the `src/app/mydatatable/mydatatable.component.ts` file and add the following import.
|
||||||
|
|
||||||
|
import { ObjectDataTableAdapter } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
In a Data Table an instance of `ObjectDataTableAdapter` requires to be configured as data source. Below the source code to add to the `mydatatable` component, just before the constructor.
|
||||||
|
|
||||||
|
data = new ObjectDataTableAdapter(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
firstName: 'Name #1',
|
||||||
|
lastName: 'Lastname #1',
|
||||||
|
icon: 'material-icons://folder_open'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
firstName: 'Name #2',
|
||||||
|
lastName: 'Lastname #2',
|
||||||
|
icon: 'material-icons://accessibility'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
firstName: 'Name #3',
|
||||||
|
lastName: 'Lastname #3',
|
||||||
|
icon: 'material-icons://alarm'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
Next, we need to pull in the `<adf-datatable>` component in the template and bind the data property and configure the columns. To develop it, open `src/app/mydatatable/mydatatable.component.html` file and replace the content with the following.
|
||||||
|
|
||||||
|
<adf-datatable
|
||||||
|
[data]="data">
|
||||||
|
<data-columns>
|
||||||
|
<data-column
|
||||||
|
key="icon"
|
||||||
|
type="image"
|
||||||
|
[sortable]="false">
|
||||||
|
</data-column>
|
||||||
|
<data-column
|
||||||
|
key="firstName"
|
||||||
|
title="First Name">
|
||||||
|
</data-column>
|
||||||
|
<data-column
|
||||||
|
key="lastName"
|
||||||
|
title="Last Name"
|
||||||
|
class="full-width name-column">
|
||||||
|
</data-column>
|
||||||
|
</data-columns>
|
||||||
|
</adf-datatable>
|
||||||
|
|
||||||
|
Save the file and check the browser. You should now see a data table showing three rows, each row having three columns, as shown in the following picture.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Data Table configuration
|
||||||
|
|
||||||
|
The Data Table can be configured in many different ways. Because of this, the Data Table is the foundation for all list components across all of ADF. Both the Document List, Task List, Process List are extensions on top of the Data Table, and even smaller components like Attachment List, Comment List, Version List and Content Selector are all based on the Data Table.
|
||||||
|
|
||||||
|
Looking into the [documentation](https://alfresco.github.io/adf-component-catalog/components/DataTableComponent.html), we can see that it has a lot of different options. Ranging from single/multi selection, click events, context menus, actions and keyboard navigation.
|
||||||
|
|
||||||
|
Let's do a simple example and add a click event, so once a row is clicked it will display an alert. Open `src/app/mydatatable/mydatatable.component.html` and add the following:
|
||||||
|
|
||||||
|
<adf-datatable
|
||||||
|
(rowClick)="onRowClick($event)"
|
||||||
|
[data]="data">
|
||||||
|
.......
|
||||||
|
|
||||||
|
Next open `src/app/mydatatable/mydatatable.component.ts` and create the method `onRowClick` as described below.
|
||||||
|
|
||||||
|
onRowClick(event: any) {
|
||||||
|
alert('We just clicked row id: ' + event.value.obj.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Notice that we're passing in the `event` variable the entire row. This means that our method will have access to all the data in the method, if required. Once you click a row you should now see a nice alert.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Data Table columns
|
||||||
|
|
||||||
|
Let's dig a bit deeper into different options for rendering columns within the Data Table. The documentation for the [Data Column component](https://alfresco.github.io/adf-component-catalog/components/DataColumnComponent.html) is quite in-depth and has lots of examples. We highly suggest checking it out.
|
||||||
|
|
||||||
|
From the documentation we can see that the Data Column component has a few properties, the most important ones are `key`, `type`, `sortable`, `title` and `class`.
|
||||||
|
|
||||||
|
* `key` is the name of the property in the `ObjectDataTableAdapter` object.
|
||||||
|
* `type` indicates how to render. By default it will take the `text` from the matching key inthe data, but other modes can be configured:
|
||||||
|
* `image` will take a URI for a Material Icon or a URL for any image and display it.
|
||||||
|
* `date` will format a date/datetime string. Use the `format` property to override and define a custom time format.
|
||||||
|
* `fileSize` will convert into kb/mb/gb as needed.
|
||||||
|
* `location` assumes the value is a nodeId for ACS and will display the path.
|
||||||
|
* `sortable` set to true or false to configure if the column can be sorted.
|
||||||
|
* `title` sets the column title in the table header.
|
||||||
|
* `class` allows setting CSS classes on the column. Use `full-width` for the column to take as much width as it can while still leaving room for the remaining columns.
|
||||||
|
|
||||||
|
## Content projection
|
||||||
|
|
||||||
|
Sometimes it's not enough to simply render a text string or an image. For this, the Data Column supports Content projection to allow you to take control over what is being rendered in the column.
|
||||||
|
|
||||||
|
Let's change the example above and introduce a status field. In the data we define a new status field that can have the values `green` or `red`. Then we will use content projection to render the column with the color instead of the text.
|
||||||
|
|
||||||
|
Open `src/app/mydatatable/mydatatable.component.ts` and change the data to this.
|
||||||
|
|
||||||
|
data = new ObjectDataTableAdapter(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Name #1',
|
||||||
|
createdBy: 'User #1',
|
||||||
|
status: 'green',
|
||||||
|
icon: 'material-icons://folder_open'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Name #2',
|
||||||
|
createdBy: 'User #2',
|
||||||
|
status: 'red',
|
||||||
|
icon: 'material-icons://accessibility'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'Name #3',
|
||||||
|
createdBy: 'User #3',
|
||||||
|
status: 'green',
|
||||||
|
icon: 'material-icons://alarm'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
Next we need to define a new column in the template and use `<ng-template/>` to project our own content into the column. Open the template and add what follows.
|
||||||
|
|
||||||
|
<data-column key="status" title="Status">
|
||||||
|
<ng-template let-entry="$implicit">
|
||||||
|
<span *ngIf="entry.data.getValue(entry.row, entry.col) == 'red'" style="background-color: red; width: 20px; height: 20px"></span>
|
||||||
|
<span *ngIf="entry.data.getValue(entry.row, entry.col) == 'green'" style="background-color: green; width: 20px; height: 20px"></span>
|
||||||
|
</ng-template>
|
||||||
|
</data-column>
|
||||||
|
|
||||||
|
While this might not be best practises for how you set the background, it does illustrate how to take control over the rendition of the content within a table cell. In the picture below you can see how the user experience looks like.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Playing with the data source
|
||||||
|
|
||||||
|
Now that you know how to control you Data Table, let's add another piece, changing the data source to integrate an external API (in this example the [`/people` service](https://api-explorer.alfresco.com/api-explorer/#!/people/listPeople) that lists all the users available into an Alfresco Content Services instance).
|
||||||
|
|
||||||
|
As explained above, the solution is to populate the `ObjectDataTableAdapter` object, implementing the data source of the `DataTable` component. To reach the goal, open the `src/app/mydatatable/mydatatable.component.ts` file and replace the content with the following.
|
||||||
|
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||||
|
import { ObjectDataTableAdapter, ObjectDataRow } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-mydatatable',
|
||||||
|
templateUrl: './mydatatable.component.html',
|
||||||
|
styleUrls: ['./mydatatable.component.scss']
|
||||||
|
})
|
||||||
|
export class MydatatableComponent implements OnInit {
|
||||||
|
|
||||||
|
data = new ObjectDataTableAdapter([],[]);
|
||||||
|
|
||||||
|
constructor(private apiService: AlfrescoApiService) {
|
||||||
|
|
||||||
|
this.apiService.getInstance().webScript.executeWebScript(
|
||||||
|
'GET',
|
||||||
|
'people',
|
||||||
|
[],
|
||||||
|
null,
|
||||||
|
'api/-default-/public/alfresco/versions/1',
|
||||||
|
null
|
||||||
|
).then(
|
||||||
|
(response: any) => {
|
||||||
|
let results = [];
|
||||||
|
for (var entry of response.list.entries) {
|
||||||
|
results.push({
|
||||||
|
id: entry.entry.id,
|
||||||
|
firstName: entry.entry.firstName,
|
||||||
|
lastName: entry.entry.lastName,
|
||||||
|
status: 'green',
|
||||||
|
icon: 'material-icons://accessibility'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.data.setRows(results.map(item => { return new ObjectDataRow(item); }));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick(event: any) {
|
||||||
|
alert('We just clicked row id: ' + event.value.obj.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
As you can see, the major changes are in the constructor where the external API is invoked and the `this.data` object id dynamically populate with the response of the services (supposed to be in JSON but it could be in every format).
|
||||||
|
|
||||||
|
Saving the file, the following picture shows the result that the user can see in his/her browser.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Adding an action
|
||||||
|
|
||||||
|
One of the most common things you could do with a Data Table, is adding an action to each row (according to some conditions). To develop one (or more) custom action, the [`DataTable` component](https://alfresco.github.io/adf-component-catalog/components/DataTableComponent.html) offers you a straightforward solution.
|
||||||
|
|
||||||
|
Below you can find the changes to develop into the `src/app/mydatatable/mydatatable.component.html` file.
|
||||||
|
|
||||||
|
<adf-datatable
|
||||||
|
...
|
||||||
|
[actions]="true"
|
||||||
|
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||||
|
(executeRowAction)="onExecuteRowAction($event)">
|
||||||
|
</adf-datatable>
|
||||||
|
|
||||||
|
And the `src/app/mydatatable/mydatatable.component.ts` file.
|
||||||
|
|
||||||
|
import { DataCellEvent, DataRowActionEvent } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
onShowRowActionsMenu(event: DataCellEvent) {
|
||||||
|
event.value.actions = [
|
||||||
|
{
|
||||||
|
title: 'Greetings'
|
||||||
|
// Put here your custom metadata.
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
onExecuteRowAction(event: DataRowActionEvent) {
|
||||||
|
console.log(event.value.row);
|
||||||
|
alert('${event.value.action.title} ${event.value.row.obj.firstName}');
|
||||||
|
}
|
||||||
|
|
||||||
|
Once saved the two files, the following picture shows how the user experience looks like when pressing the three dots column and selecting `Greetings` for the first row.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can note that in the browser's console, a log describing the row object is shown for debugging purpose.
|
||||||
|
|
||||||
|
To make the example more real, let's add the interaction with an external service. In this case we are going to use the [`/people/{personId}` service](https://api-explorer.alfresco.com/api-explorer/#!/people/getPerson) to show the complete profile data, retrieved in a JSON response. To make it simple, we will extract the data in a string, shown to the user through the usual `alert` command. In your final application you might want to use a more sexy modal window, maybe the standard [Material Dialog](https://material.angular.io/components/dialog/overview).
|
||||||
|
|
||||||
|
To develop the enhancement, edit the `src/app/mydatatable/mydatatable.component.html` file, replacing the `onExecuteRowAction` method as follow.
|
||||||
|
|
||||||
|
onExecuteRowAction(event: DataRowActionEvent) {
|
||||||
|
|
||||||
|
if (event.value.action.title = "Greetings") {
|
||||||
|
|
||||||
|
this.apiService.getInstance().webScript.executeWebScript(
|
||||||
|
'GET',
|
||||||
|
'people/' + event['value']['row']['obj']['id'],
|
||||||
|
[],
|
||||||
|
null,
|
||||||
|
'api/-default-/public/alfresco/versions/1',
|
||||||
|
null
|
||||||
|
).then(
|
||||||
|
(response: any) => {
|
||||||
|
alert(JSON.stringify(response.entry));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Once saved, the application will be updated automatically and your browser should present something similar to the following result, when the `Greetings` action is selected for each row.
|
||||||
|
|
||||||
|

|
||||||
|
|
@@ -10,7 +10,8 @@
|
|||||||
{ "title": "Preparing the development environment", "file": "preparing-environment.md"},
|
{ "title": "Preparing the development environment", "file": "preparing-environment.md"},
|
||||||
{ "title": "Adding a new component", "file": "new-component.md"},
|
{ "title": "Adding a new component", "file": "new-component.md"},
|
||||||
{ "title": "Adding a new view", "file": "new-view.md"},
|
{ "title": "Adding a new view", "file": "new-view.md"},
|
||||||
{ "title": "Using components", "file": "using-components.md"}
|
{ "title": "Using components", "file": "using-components.md"},
|
||||||
|
{ "title": "Working with a DataTable", "file": "working-with-data-table.md"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Reference in New Issue
Block a user