[ADF-2679] Reviewed tutorials (#3254)

* [ADF_2679] Reviewed tutorial text

* [ADF-2679] Reviewed tutorials

* [ADF-2679] Fixed glitches in index page
This commit is contained in:
Andy Stark
2018-05-02 16:43:47 +01:00
committed by Eugenio Romano
parent ebfc40b1c8
commit 8037d4c76c
8 changed files with 681 additions and 470 deletions

View File

@@ -14,11 +14,10 @@ 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 | This tutorial explains how to get set up to use ADF so you can tackle the other tutorials. It covers the basic development environment with suggested versions for each tool, library and module. |
| [**Creating your ADF application using Yeoman**](creating-the-app-using-yeoman.md) | Beginner | In this tutorial you are going to see how to create an ADF application from scratch, using the [Yeoman scaffolding tool](http://yeoman.io/). | | [**Creating your ADF application using Yeoman**](creating-the-app-using-yeoman.md) | Basic | Learn how to create an ADF application from scratch, using the [Yeoman scaffolding tool](http://yeoman.io/). This task is recommended to get started before developing your ADF 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-component.md) | Basic | By definition, a _component_ controls a patch of screen called a _view_. For example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion ofan application's layout. In this tutorial, you will learn how to create a component using [Angular CLI](https://cli.angular.io/) within 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. | | [**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 in your application and how to access 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, and content projection / HTML extensions. In this tutorial you will see a practical example of each approach using the Login component. |
| [**Customising the Login component**](customising-login.md) | Intermediate | In this tutorial you will learn how to customise the [`Login` component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) assuming that you read the [technical documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html). | | [**Customizing the Login component**](customising-login.md) | Intermediate | In this tutorial you will learn how to customize the [\`Login\` component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) following the [technical documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html). The task will be very simple. See the documentation for further details about customizing this component, along with examples. |
| [**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. | | [**Working with a Data Table**](working-with-data-table.md) | Intermediate | 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 from a generic back-end service or third party API. As an example we are going to use data from one of the available services on Alfresco Content Services. However, the procedure is much the same if want to use an Alfresco Process Services endpoint or a third party API. |

View File

@@ -1,37 +1,42 @@
--- ---
Level: Basic Level: Basic
--- ---
# Creating your ADF application using Yeoman # Creating your ADF application using Yeoman
In this tutorial you are going to see how to create an ADF application from scratch, using the [Yeoman scaffolding tool](http://yeoman.io/). This is a "getting started" task that should enable you to start developing your own ADF application. Learn how to create an ADF application from scratch, using the [Yeoman scaffolding tool](http://yeoman.io/). This task is recommended to get started before developing your ADF application.
## Prerequisites ## Prerequisites
Before any further task, be sure you executed the optional section described in [the preparation of the development environment](./preparing-the-development-environment.html), dedicated to the installation of the ADF Yeoman generator. This is a requested prerequisite to complete this tutorial with success.
Before proceeding, make sure you have set up the Yeoman generator as described in
[Preparing the development environment](./preparing-the-development-environment.html). You will need
the generator to complete this tutorial successfully.
## Creating the ADF application ## Creating the ADF application
The creation of a brand new application is straightforward using the [Yeoman generator](http://yeoman.io/). Open a terminal and execute the following command.
Creating a new application is straightforward using the [Yeoman generator](http://yeoman.io/). Open a terminal and execute the following command.
yo alfresco-adf-app yo alfresco-adf-app
After the execution, the generator asks few questions: mainly the name of your app (in this example we are going to use `myApp`) and which blueprint you want to use. below the picture showing how the wizard looks like. The generator will ask you a few questions as it runs, mainly the name of your app (in this example we
are going to use "myApp") and which blueprint you want to use:
![yeoman_creation](../docassets/images/yeoman_creation.png) ![yeoman_creation](../docassets/images/yeoman_creation.png)
You can select one of the three following blueprints. The following blueprints are available:
**Process Services** - **Process Services:** This will generate an application for Alfresco Process Services. The main
components it contains are Login, App List, Task List, Form and Start Process.
This will generate an application for Alfresco Process Services. It mainly contains the following components: Login, App List, Task List, Form and Start Process. - **Content Services:** This will generate an application for Alfresco Content Services. The main
components it contains are Login, Document List, and Viewer.
**Content Services** - **Process and Content Services:** This will generate an application for both Alfresco Process and
Content Services using a combination of the two blueprints above.
This will generate an application for Alfresco Content Services. It mainly contains the following components: Login, Document List, Viewer. When you have made your selection, the generator will ask if you want to install dependencies right away.
Type "`Y`" and hit enter. This can take a minute or two depending on your internet connection. You might
**Process and Content Services** see a few warnings at the end like this:
This will generate an application for both Alfresco Process and Content Services and will be a combination of the two blueprints above.
Select your preferred one and the generator asks if you want to install dependencies right away. Enter "`Y`" and hit enter. This can take a minute or two depending on your internet connection. You might see a few warnings at the end like this:
npm notice created a lockfile as package-lock.json. You should commit this file. npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN @mat-datetimepicker/core@1.0.4 requires a peer of @angular/core@^5.2.3 but none is installed. You must install peer dependencies yourself. npm WARN @mat-datetimepicker/core@1.0.4 requires a peer of @angular/core@^5.2.3 but none is installed. You must install peer dependencies yourself.
@@ -43,15 +48,21 @@ Select your preferred one and the generator asks if you want to install dependen
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents): npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
These warnings are normal. Unfortunately they happen within the Angular Flex Layout package that ADF depends on. You can safely ignore them. These warnings are normal. Unfortunately they are not under the ADF team's control (they happen within the
Angular Flex Layout package that ADF depends on) but you can safely ignore them.
Once done, you will find a folder named `myApp` where you can find all the ADF application already created and completed. Once done, you will find a folder named `myApp` containing the new ADF application ready for
development.
## Configuring the application ## Configuring the application
To configure the ADF application, you only need to point on the correct Alfresco Content Services and Alfresco Process Services, accordingly with the blueprint you decided to use during the creation. To configure the ADF application, you only need to point to the correct Alfresco Content Services and/or
Alfresco Process Services, depending on which blueprint you used to create the project.
To setup the correct back-end services, change into the directory of your app (`myApp` in our case) and inspect the `proxy.conf.json` file. This file will tell Angular Webpack to create a proxy for your backend (Content or Process services). Change the URLs and ports to reflect where they are currently running. Below an example of how the `proxy.conf.json` file should look like. To set up the back-end services correctly, `cd` into the directory of your app (`myApp` in our case)
and open the `proxy.conf.json` file. This file will tell Angular Webpack to create a proxy for your backend
services (Content or Process services). Change the URLs and ports to reflect where these services are
currently running. Below is an example of how the `proxy.conf.json` file should look:
{ {
"/alfresco": { "/alfresco": {
@@ -64,13 +75,17 @@ To setup the correct back-end services, change into the directory of your app (`
"secure": false, "secure": false,
"changeOrigin": true "changeOrigin": true
} }
}
## Using the application ## Using the application
Now that you ADF application is correctly configured, start it running the `npm start` command from a terminal, double checking you are located into the project folder (in our case `myApp`). The execution of the command takes a couple of seconds and a browser will automatically open at `http://localhost:4200/`. Now that your ADF application is correctly configured, you can run it using the `npm start` command from
a terminal (check that you are in the project folder `myApp` before doing this). The execution of the
command takes a couple of seconds, after which the browser will automatically open at
`http://localhost:4200/`.
As you can see from the user interface, the Alfresco ADF application is really straightforward and basic. This is a precise requirement for this example, because it focuses the attention on the comprehension of the basis, instead of containing complex features that will be part of an intermediate/expert learning path. Below a screenshot of how the home page looks like. As you can see from the user interface, the Alfresco ADF application is very basic to begin with. This is
exactly what we need for this example, because it emphasizes the basics rather than complex features that
will be covered in intermediate/expert tutorials to follow. Below is a screenshot of the home page:
![yeoman_start](../docassets/images/yeoman_start.png) ![yeoman_start](../docassets/images/yeoman_start.png)

View File

@@ -1,31 +1,44 @@
--- ---
Level: Intermediate Level: Intermediate
--- ---
# Customising the Login component
In this tutorial you will learn how to customise the [`Login` component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) assuming that you read the [technical documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html). In this tutorial we are going to describe a very simple task, considering that the technical documentation is complete and it is presented in form of examples and tutorial. # Customizing the Login component
In this tutorial you will learn how to customize the [`Login` component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) following the [technical documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html). The task will be very simple. See the documentation for further details about customizing this component, along with examples.
## Locating the component into your application ## Locating the component into your application
Starting from an existing ADF application, the `Login` component, like any other component, is stored in a subfolder of the `app` folder: in [Alfresco Content App](https://github.com/Alfresco/alfresco-content-app) it is stored into the `/src/app/components/login` path, in an ADF app created with [Yeoman](http://yeoman.io/) it is stored into the `/src/app/login` path. Starting from an existing ADF application, the `Login` component, like any other component, is stored in a subfolder of the `app` folder. In the
[Alfresco Content App](https://github.com/Alfresco/alfresco-content-app)
it is stored in the `/src/app/components/login` path. In an ADF app created with [Yeoman](http://yeoman.io/)
it is stored in the `/src/app/login` path.
As an example, locate the `Login` component for your application and proceed to customise it as described below. Once you have located the `Login` component for your application, you can customize it as described below.
## Changing the header ## Changing the header
As every regular [Angular Component](https://angular.io/guide/architecture-components), the `Login` component can be customised through the CSS, HTML and Typescript. In this simple example we are going to customise the header (as described also into the [technical documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html)). As with every regular
[Angular Component](https://angular.io/guide/architecture-components),
you can customize the `Login` component can be customised via CSS, HTML and Typescript. In this simple
example, we will customize the header (as described also in the
[technical documentation](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html)).
To complete the task, edit the login.component.html file and change the content accordingly to the following source code. Open the `login.component.html` file and change the content to match the following source code:
```html
<adf-login ...> <adf-login ...>
<login-header><ng-template>My custom HTML for the header</ng-template></login-header> <login-header><ng-template>My custom HTML for the header</ng-template></login-header>
</adf-login> </adf-login>
```
After saving the file, the login form will look like the following picture. After saving the file, the login form will look like this:
![login_header](../docassets/images/login_header.png) ![login_header](../docassets/images/login_header.png)
## More examples ## More examples
As introduced above in this tutorial, this is a very basic example and the `Login` component can be customised many more than this. For a complete and detailed description, full of examples, check the [technical documentation about the component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html) that contains everything you might want to know about the customisation of the `Login` component As mentioned earlier, this is a very basic example and the `Login` component can be customized
much more extensively than this. For a complete and detailed description, full of examples, check the
[technical documentation about the component](https://alfresco.github.io/adf-component-catalog/components/LoginComponent.html).
This describes every customization available for the `Login` component.

View File

@@ -1,29 +1,51 @@
---
Level: Basic
---
# 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*. For example, individual components define and control menus, tabs, forms, buttons and every simple or complex portion ofan application's layout. In this tutorial, you will learn how to create a component using [Angular CLI](https://cli.angular.io/) within 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 in a terminal:
ng generate component my-first-component ng generate component my-first-component
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. 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.
## Using the component ## Using the 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. Once the component is created, you can use the element
```html
<app-my-first-component></app-my-first-component>
```
anywhere within the HTML file of another component to render the content of `my-first-component`.
As an example, add `<app-my-first-component></app-my-first-component>` at the top of the
`app.component.html` file in the `src` folder, and run the application again. In the browser you will
shortly see the text "my-first-component works!", as a placeholder to show where the component is
rendered in the layout.
## Anatomy of the component ## Anatomy of the component
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:
- `my-first-component.component.scss` containing the CSS used by the component. This file is created as empty. By default the new component is created in the `src/app` path and everything is stored in a folder with the
- `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. same name as the component itself. Here, you should find a folder named `my-first-component` has been added
to `src/app`, with the following contents:
- `my-first-component.component.scss` containing the CSS used by the component, initially empty.
- `my-first-component.component.html` containing the HTML used to render the component. This file is
created with a very basic placeholder message that displays the name of the component within a `p` tag.
- `my-first-component.component.spec.ts` containing the unit tests for the component. - `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. - `my-first-component.component.ts` containing the `MyFirstComponentComponent` class that implements 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. You must declare or import the component in one or more modules in order to use it. In this example the
`app.module.ts` file stored in `src/app` contains the following code:
```ts
import { MyFirstComponentComponent } from './my-first-component/my-first-component.component'; import { MyFirstComponentComponent } from './my-first-component/my-first-component.component';
@NgModule({ @NgModule({
@@ -31,5 +53,7 @@ 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 know about your brand new component. All you have read here is standard Angular, not customised or valid for ADF applications only. These is the most basic information you need to know about your component. Everything mentioned here is
standard Angular code without anything specific to ADF applications.

View File

@@ -1,22 +1,28 @@
--- ---
Level: Beginner Level: Beginner
--- ---
# Adding a new view # Adding a new view
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. 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 in your application and how to access it using a defined endpoint.
## Creating a view ## Creating a view
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.
To create a view, run the following command into a terminal, starting from the root of your project. In an Angular application, a view is implemented by a regular component. A view can use other views
(ie, other components) but a view can also be used to implement the full layout of your application.
This is the reason why creating a view is not necessarily the same task as creating a component.
To create a view, run the following command in a terminal from the root of your project:
ng generate component my-first-view ng generate component my-first-view
For further details about creating a component, you can refer to the tutorial here (link to "Adding a new component"). For further details about creating a component, refer to the tutorial [here](new-component.md).
## Routing the view ## 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.
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 with a syntax similar to the following source code.
```ts
const appRoutes: Routes = [ const appRoutes: Routes = [
{ path: 'path-in-the-app', component: ExistingComponent }, { path: 'path-in-the-app', component: ExistingComponent },
{ path: '**', component: PageNotFoundComponent } { path: '**', component: PageNotFoundComponent }
@@ -32,23 +38,30 @@ An Angular application has one singleton instance of the `Router` service that
], ],
... ...
}) })
```
To add the new view to the routing, change the `appRoutes` constant as follow. To add the new view to the routing, change the `appRoutes` constant as follows:
```ts
const appRoutes: Routes = [ const appRoutes: Routes = [
{ path: 'path-in-the-app', component: ExistingComponent }, { path: 'path-in-the-app', component: ExistingComponent },
{ path: 'my-first-view', component: MyFirstViewComponent }, // <-- Add this! { path: 'my-first-view', component: MyFirstViewComponent }, // <-- Add this!
{ path: '**', component: PageNotFoundComponent } { path: '**', component: PageNotFoundComponent }
]; ];
```
And remember to import the component in the same file with the following syntax. And remember to import the component in the same file with the following syntax.
```ts
import { MyFirstViewComponent } from './my-first-view/my-first-view.component'; 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. 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 `Router` service is declared in a location close to the file containing
the root module.
## Testing the view ## 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.
To render the new view through the application and check the user experience, restart the application and open a browser at the following URL:
http://<ip_address>:<port>/my-first-view http://<ip_address>:<port>/my-first-view
@@ -58,24 +71,28 @@ The result should be a very simple page with the following content.
## View parameters (optional) ## 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. In most use cases, you will want to add parameters to the view's endpoint. To enable this, change the `appRoutes` constant as follows:
```ts
const appRoutes: Routes = [ const appRoutes: Routes = [
{ path: 'path-in-the-app', component: ExistingComponent }, { path: 'path-in-the-app', component: ExistingComponent },
{ path: 'my-first-view/:name', component: MyFirstViewComponent }, // <-- Add this! { path: 'my-first-view/:name', component: MyFirstViewComponent }, // <-- Change this!
{ path: '**', component: PageNotFoundComponent } { 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: Then open the Typescript controller for the `MyFirstViewComponent` stored in `src/app/my-first-view` (`my-first-view.component.ts`). You need to add a few things here:
1. We need to `import` and `inject` the router into the class. 1. We need to `import` and `inject` the router into the class.
2. Subscribe to the router parameters and fetch the value. 2. Subscribe to the router parameters and fetch the value.
3. Unsubscribe to the router parameters. 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! While #3 isn't strictly required, it would eventually cause a memory leak in your application, so
please remember to unsubscribe!
Modify the typescript controller `my-first-view.component.ts` to look like this: Modify the typescript controller `my-first-view.component.ts` to look like this:
```ts
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
@@ -101,12 +118,16 @@ Modify the typescript controller `my-first-view.component.ts` to look like this:
this.params.unsubscribe(); 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. Next open the template `my-first-view.component.html` in the same folder and add the greeting as in
the following source code.
```html
<p> <p>
Hello {{ name }} Hello {{ name }}
</p> </p>
```
You can now navigate to `http://<ip_address>:<port>/my-first-view/sir` and see the nice message "Hello sir". You can now navigate to `http://<ip_address>:<port>/my-first-view/sir` and see the nice message "Hello sir".

View File

@@ -1,50 +1,63 @@
--- ---
Level: Beginner Level: Beginner
--- ---
## Preparing the development environment
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
This tutorial explains how to get set up to use ADF so you can tackle the other tutorials. It covers the basic development environment with suggested versions for each tool, library and module.
## Node.js ## Node.js
[Node.js](https://nodejs.org) is a JavaScript runtime built using an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js uses [npm](https://www.npmjs.com/) as public registry and a package system. [Node.js](https://nodejs.org) is a JavaScript runtime built using an event-driven, non-blocking I/O model
that makes it lightweight and efficient. Node.js uses [npm](https://www.npmjs.com/) as its public registry
and package system.
You need the latest `node.js` of either the `8.x` or `9.x` branch. You need the latest `node.js` from either the `8.x` or `9.x` branch.
To check the version, run the following command in a terminal. If you already have it installed then you can check the version with the following command in a terminal:
node -v node -v
## Angular CLI ## Angular CLI
The [Angular CLI](https://cli.angular.io/) is a tool to initialise, develop, scaffold and maintain [Angular](https://angular.io/) applications [Angular CLI](https://cli.angular.io/) is a tool to initialize, develop, scaffold and maintain [Angular](https://angular.io/) applications, including ADF applications.
Earlier and later versions have issues around `@angular/devkit-core`. 1.6.6 seem to be the stable choice currently. Version 1.6.6 or Angular CLI seems to be the best choice currently, since earlier and later versions have
issues with `@angular/devkit-core`.
If you already have `Angular CLI` installed check the version by running: If you already have `Angular CLI` installed then you can check the version by running:
ng --version ng --version
To globally install `Angular CLI` version globally 1.6.6 run: To install `Angular CLI` version 1.6.6 globally, run the following command:
sudo npm install -g @angular/cli@1.6.6 sudo npm install -g @angular/cli@1.6.6
## Code Editor ## Code Editor
We recommend [Visual Studio Code](http://code.visualstudio.com) - it's a free, lightweight and *very* powerful tool from Microsoft that works great with Angular development. You can use any text editor to develop ADF apps but we recommend
[Visual Studio Code](http://code.visualstudio.com) from Microsoft. It's a free, lightweight and *very*
powerful tool that works well for Angular development.
## ADF Yeoman generator (optional) ## ADF Yeoman generator (optional)
You might want to ensure that you have `Yeoman` installed by running `yo --version`. If this is not in your system make sure you run: Check that you have `Yeoman` installed by running `yo --version`. If it is not present, you can install
it by running:
sudo npm install -g yo sudo npm install -g yo
If you have installed it previously, you might want to make sure you uninstall them before. In ADF 2.0 we renamed the generator packages and the update is highly suggested. You can install the latest version of the `generator-alfresco-adf-app` (the main scaffold generator)
using the following command:
Uninstall previous versions with:
sudo npm uninstall generator-alfresco-adf-app
sudo npm uninstall generator-ng2-alfresco-app
Install the latest version of the `generator-alfresco-adf-app` using the following command.
sudo npm install -g generator-alfresco-adf-app sudo npm install -g generator-alfresco-adf-app
If you have installed an earlier version of the generator then you should uninstall it before installing
the latest one. In ADF 2.0 we renamed the generator packages, so updating is especially recommended from
pre-2.0 versions.
Uninstall versions before 2.0 with:
sudo npm uninstall generator-ng2-alfresco-app
...and versions since 2.0 with:
sudo npm uninstall generator-alfresco-adf-app

View File

@@ -1,29 +1,43 @@
--- ---
Level: Beginner Level: Beginner
--- ---
# Using components # Using components
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. There are three different ways to use, extend and configure an ADF component: configuration properties, event listeners, and content projection / HTML extensions. In this tutorial you will see a practical example of each approach using the Login component.
The ADF documentation is always a good starting point when you plan to use a component. In general,
there are three different ways to use, extend and configure an ADF component:
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. 1. Configuration properties.
2. Event listeners. 2. Event listeners.
3. Content projection / HTML extensions. 3. Content projection / HTML extensions.
## Configuration properties ## 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 and 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. Angular components can easily be configured via properties in the HTML template. In this example we will
work with the "Remember me" checkbox and "Need Help?" and "Register" links in the footer of the Login component.
To prepare for the task, make sure you have your ADF application up and running by executing `npm start`
in a terminal from the root folder of the project. Access the login page using your browser and edit the `login.component.html` file stored in the `src/app/.../login` folder. The content of the `login.component.html` file should look like the following:
```html
<adf-login <adf-login
copyrightText="&#169; 2017 - 2018 Alfresco Software, Inc. All rights reserved." copyrightText="&#169; 2017 - 2018 Alfresco Software, Inc. All rights reserved."
providers="ECM" providers="ECM"
... ...
> >
</adf-login> </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, suing 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). Looking at 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 you haven't specified any values for these properties in the source code then set them both
to `false` using the syntax shown in the example below. If you have specified values in the source code then
set them to the opposite value in the HTML template (set them to `true` if they are `false` in the source
and vice versa).
```html
<adf-login <adf-login
copyrightText="&#169; 2017 - 2018 Alfresco Software, Inc. All rights reserved." copyrightText="&#169; 2017 - 2018 Alfresco Software, Inc. All rights reserved."
providers="ECM" providers="ECM"
@@ -32,33 +46,45 @@ When reviewing the documentation you can see that the `<adf-login/>` component h
... ...
> >
</adf-login> </adf-login>
```
Once saved the HTML template you will see the login page updated with a different layout accordingly with the property values. After saving the HTML template, you will see the login page updated with a different layout matching the
new property values.
**Notice:** The two new properties are specified with `[]` around them. There are three ways to configure a component. **Note:** The two new properties are specified with `[]` around them. There are three ways to configure a
property:
1. `[property]=""` This will be an expression or property from the typescript controller. Use this for boolean expressions or variables. 1. `[property]=""` This sets the property using an expression or another property from the Typescript
2. `property=""` This will be passed in as raw text. controller. Use this syntax for boolean expressions or variables.
2. `property=""` This value will be passed as raw text.
3. `[(property)]` This is called *banana in a box* and is used for two way binding. 3. `[(property)]` This is called *banana in a box* and is used for two way binding.
## Event listeners ## Event listeners
Now that you've successfully configured properties on the `<adf-login/>` component, it's time to look at the events. Now that you've successfully configured properties on the `<adf-login/>` component, it's time to look at 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`. Looking now at the events section of 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. We can subscribe to these events and have our custom code executed when they are emitted. We will
hook into the `executeSubmit` event and show a simple `alert()` when 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). Back in the `login.component.html` file, add `(success)="mySuccessMethod($event)"` to the `<adf-login/>` component (the position is not relevant).
```html
<adf-login <adf-login
... ...
(executeSubmit)="myExecuteSubmitMethod($event)" (executeSubmit)="myExecuteSubmitMethod($event)"
> >
</adf-login> </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. Next, implement `myExecuteSubmitMethod` in the Typescript class that defines the component. Edit
the `login.component.ts` file stored in the same `src/app/.../login` folder and add the implementation
of `myExecuteSubmitMethod` as follows:
```ts
@Component({ @Component({
... ...
}) })
@@ -72,26 +98,37 @@ Next you need to implement `myExecuteSubmitMethod` in the typescript class imple
console.log(event); 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. After saving both files, the login component will be refreshed in your browser. Enter random values for
the 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. **Bonus objective:** Add a custom logo and background to the login view using the relevant properties
described in the documentation.
## Content projection / HTML extensions ## 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: The final way to configure or extend a component is through an approach called *Content projection*. This
involves adding placeholders to a component 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:
```html
<div> <div>
<p> <p>
<b>Here we have some bold text</b> <b>Here we have some bold text</b>
</p> </p>
</div> </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. We can use the same approach with ADF components to inject custom code or entire components into another
component. The documentation shows which targets are available. For example, the `<adf-login/>` component
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. 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:
```html
<adf-login <adf-login
... ...
> >
@@ -101,7 +138,11 @@ The `<adf-login/>` component supports two targets: `login-header` and `login-foo
</ng-template> </ng-template>
</login-footer> </login-footer>
</adf-login> </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. Make sure 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 add 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. When you are done, save the template and you should see a "Hello World!" message in the footer of your
login page when the browser refreshes.

View File

@@ -1,18 +1,35 @@
--- ---
Level: Intermediate Level: Intermediate
--- ---
# Working with a Data Table # 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. 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 from a generic back-end service or third party API. As an example we are going to use data from one of the available services on Alfresco Content Services. However, the procedure is much the same if want to use an Alfresco Process Services endpoint or a third party API.
## Prerequisites and data source ## 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. Before diving deep into the technical description of the
[`DataTable` component](https://alfresco.github.io/adf-component-catalog/components/DataTableComponent.html),
let's start with a description of 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. In this tutorial we will start from an existing ADF application set up to use (at least) Alfresco Content
Services as a service layer. For convenience and relevance to the Data Table, we suggest using the
[Alfresco Example Content Application](https://github.com/Alfresco/alfresco-content-app). This 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).
However, if you prefer to create a brand new ADF application from scratch then you should still be able
to follow the tutorial without difficulty.
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. For this tutorial, the endpoint used to populate the Data Table component is the
[`/people` service](https://api-explorer.alfresco.com/api-explorer/#!/people/listPeople) which lists
all users available in an Alfresco Content Services instance. The `/people` service is suitable for the
purpose of this tutorial because it is available by default in the Alfresco Content Services REST API.
As a follow-up, you could choose to use an Alfresco Process Services endpoint or a third party API.
Below is an example of the information returned by the
[`/people` service](https://api-explorer.alfresco.com/api-explorer/#!/people/listPeople):
```json
{ {
"list": { "list": {
"pagination": { "pagination": {
@@ -38,23 +55,32 @@ During the description of the current tutorial, the endpoint used to populate th
] ]
} }
} }
```
## Adding a page using the `DataTable` component ## 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. Starting from the ADF application, let's add a new component that implements a new page containing a
basic `DataTable` component. Open a terminal and `cd` to the root of the application, then run the
following command to add the component for the new page:
ng g c mydatatable -m app.module 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. In the `src/app/mydatatable` folder you should now find four files with extensions `html`, `scss`,
`spec.ts` and `ts`, that will be used to implement 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 add the new page to the routing of the application, edit the `Routes` instance in `app.routes.ts`
(if you are using the Alfresco Example Content Application) or in `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. To define the new routing, ensure the following import is included in the file:
```ts
import {MydatatableComponent} from './mydatatable/mydatatable.component'; import {MydatatableComponent} from './mydatatable/mydatatable.component';
```
Then add a new item to the `Routes` instance, as described below. Then add a new item to the `Routes` instance, as described below.
```ts
export const APP_ROUTES: Routes = [ export const APP_ROUTES: Routes = [
..., ...,
{ {
@@ -63,15 +89,22 @@ Then add a new item to the `Routes` instance, as described below.
}, },
... ...
]; ];
```
Since then, the page will be available at the URL `http://localhost:3000/#/mydatatable`, if you start from the Alfresco Example Content Application. The page will now be available at the URL `http://localhost:3000/#/mydatatable` (if you started 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. Now that the new page is in place, let's add the `DataTable` component to it. To do this, open
the `src/app/mydatatable/mydatatable.component.ts` file and add the following import:
```ts
import { ObjectDataTableAdapter } from '@alfresco/adf-core'; 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. A DataTable needs an instance of `ObjectDataTableAdapter` to be configured as the data source. Add
the source code below to the `mydatatable` component, just before the constructor:
```ts
data = new ObjectDataTableAdapter( data = new ObjectDataTableAdapter(
[ [
{ {
@@ -94,9 +127,13 @@ In a Data Table an instance of `ObjectDataTableAdapter` requires to be configure
} }
] ]
); );
```
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. Next, we need to put the `<adf-datatable>` component in the template and bind the data property, which will
configure the columns. Open the `src/app/mydatatable/mydatatable.component.html` file and replace the content
with the following:
```html
<adf-datatable <adf-datatable
[data]="data"> [data]="data">
<data-columns> <data-columns>
@@ -116,58 +153,78 @@ Next, we need to pull in the `<adf-datatable>` component in the template and bin
</data-column> </data-column>
</data-columns> </data-columns>
</adf-datatable> </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. Save the file and go back to the browser. You should now see a datatable showing three rows, each with
three columns:
![data_table_static](../docassets/images/data_table_static.png) ![data_table_static](../docassets/images/data_table_static.png)
## DataTable configuration ## DataTable 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. The DataTable can be configured in many different ways, which enables it to be used as the foundation
for all list components throughout ADF. The Document List, Task List, and Process List are extensions
of the DataTable, and even smaller components like Attachment List, Comment List, Version List and
Content Selector are also based on it.
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. Looking at the
[documentation](https://alfresco.github.io/adf-component-catalog/components/DataTableComponent.html),
we can see that it has a lot of different options, including 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: As a simple example, we'll add a `click` event to display an alert when a row is clicked. Open
`src/app/mydatatable/mydatatable.component.html` and add the following:
```html
<adf-datatable <adf-datatable
(rowClick)="onRowClick($event)" (rowClick)="onRowClick($event)"
[data]="data"> [data]="data">
....... .......
```
Next open `src/app/mydatatable/mydatatable.component.ts` and create the method `onRowClick` as described below. Next, open `src/app/mydatatable/mydatatable.component.ts` and add the method `onRowClick` as described below:
```ts
onRowClick(event: any) { onRowClick(event: any) {
alert('We just clicked row id: ' + event.value.obj.id); 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. Note that the entire row is passed in the `event` parameter. This means that our method will have
access to all the data in the row, if required. When you click a row, you should now see a nice alert:
![data_table_rowClick](../docassets/images/data_table_rowClick.png) ![data_table_rowClick](../docassets/images/data_table_rowClick.png)
## DataTable columns ## DataTable 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. Let's dig a bit deeper into the different options for rendering columns within the DataTable. 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 recommend 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`. From the documentation we can see that the Data Column component has quite a few properties but the
most important ones are `key`, `type`, `sortable`, `title` and `class`.
* `key` is the name of the property in the `ObjectDataTableAdapter` object. - `key` is the name of the corresponding 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: - `type` indicates how to render. By default it will take the `text` from the matching key in the data,
* `image` will take a URI for a Material Icon or a URL for any image and display it. but other modes are also available:
* `date` will format a date/datetime string. Use the `format` property to override and define a custom time format. - `image` will take a URI for a Material Icon or a URL for any image and display it.
* `fileSize` will convert into kb/mb/gb as needed. - `date` will format a date/datetime string. Use the `format` property to override it and define a custom time format.
* `location` assumes the value is a nodeId for ACS and will display the path. - `fileSize` will convert into kb/mb/gb as needed.
* `sortable` set to true or false to configure if the column can be sorted. - `location` assumes the value is a nodeId for ACS and will display the path.
* `title` sets the column title in the table header. - `sortable` toggles whether or not the column can be sorted.
* `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. - `title` sets the column title in the table header.
- `class` allows you to set CSS classes for 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 ## 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. Sometimes it's not enough to simply render a text string or an image. To handle such cases, the Data Column
supports Content projection to allow you to control what gets 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. 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 can 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. Open `src/app/mydatatable/mydatatable.component.ts` and change the data to the following:
```ts
data = new ObjectDataTableAdapter( data = new ObjectDataTableAdapter(
[ [
{ {
@@ -193,26 +250,38 @@ Open `src/app/mydatatable/mydatatable.component.ts` and change the data to this.
} }
] ]
); );
```
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. Next we need to define a new column in the template and use `<ng-template/>` to project our own content
into it. Open the template and add the following code:
```html
<data-column key="status" title="Status"> <data-column key="status" title="Status">
<ng-template let-entry="$implicit"> <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) == '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> <span *ngIf="entry.data.getValue(entry.row, entry.col) == 'green'" style="background-color: green; width: 20px; height: 20px"></span>
</ng-template> </ng-template>
</data-column> </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. While this might not be best practise for setting 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 what the
user experience looks like:
![data_table_contentProjection](../docassets/images/data_table_contentProjection.png) ![data_table_contentProjection](../docassets/images/data_table_contentProjection.png)
## Playing with the data source ## 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). Now that you know how to control you DataTable, let's add another element by 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 in 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. As explained above, you can do this by populating the `ObjectDataTableAdapter` object that acts as
the data source of the `DataTable` component. Open the `src/app/mydatatable/mydatatable.component.ts`
file and replace the content with the following:
```ts
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '@alfresco/adf-core';
import { ObjectDataTableAdapter, ObjectDataRow } from '@alfresco/adf-core'; import { ObjectDataTableAdapter, ObjectDataRow } from '@alfresco/adf-core';
@@ -258,28 +327,35 @@ As explained above, the solution is to populate the `ObjectDataTableAdapter` obj
} }
} }
```
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). As you can see, the major changes are in the constructor where the external API is invoked and the
`this.data` object id dynamically populates the table with the response of the services (assumed to
be in JSON but it could be in any format).
Saving the file, the following picture shows the result that the user can see in his/her browser. After saving the file, you should see something like the following in the browser:
![data_table_dataSource](../docassets/images/data_table_dataSource.png) ![data_table_dataSource](../docassets/images/data_table_dataSource.png)
## Adding an action ## 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. A common and straightforward customization for a DataTable is to add an action to each row or to rows
that meet certain conditions.
Below you can find the changes to develop into the `src/app/mydatatable/mydatatable.component.html` file. Make the changes shown below to the `src/app/mydatatable/mydatatable.component.html` file:
```html
<adf-datatable <adf-datatable
... ...
[actions]="true" [actions]="true"
(showRowActionsMenu)="onShowRowActionsMenu($event)" (showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)"> (executeRowAction)="onExecuteRowAction($event)">
</adf-datatable> </adf-datatable>
```
And the `src/app/mydatatable/mydatatable.component.ts` file. Also update `src/app/mydatatable/mydatatable.component.ts` as follows:
```ts
import { DataCellEvent, DataRowActionEvent } from '@alfresco/adf-core'; import { DataCellEvent, DataRowActionEvent } from '@alfresco/adf-core';
onShowRowActionsMenu(event: DataCellEvent) { onShowRowActionsMenu(event: DataCellEvent) {
@@ -295,17 +371,24 @@ And the `src/app/mydatatable/mydatatable.component.ts` file.
console.log(event.value.row); console.log(event.value.row);
alert('${event.value.action.title} ${event.value.row.obj.firstName}'); 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. After you have saved both files, you should see something like the following when you click the
three dots column in the table and select `Greetings` for the first row:
![data_table_dataSource](../docassets/images/data_table_action.png) ![data_table_dataSource](../docassets/images/data_table_action.png)
You can note that in the browser's console, a log describing the row object is shown for debugging purpose. Note that the browser console has a log describing how the row object is shown for debugging purposes.
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 make the example more realistic, let's add some interaction with an external service. We will use
the [`/people/{personId}` service](https://api-explorer.alfresco.com/api-explorer/#!/people/getPerson)
to get the complete profile data, retrieved as a JSON response. To make it simple, we will extract the data as a string, shown to the user through the usual `alert` command. In your final application you might want to use a more sophisticated modal window (the standard
[Material Dialog](https://material.angular.io/components/dialog/overview), perhaps).
To develop the enhancement, edit the `src/app/mydatatable/mydatatable.component.html` file, replacing the `onExecuteRowAction` method as follow. To develop the enhancement, edit the `src/app/mydatatable/mydatatable.component.html` file, replacing the
`onExecuteRowAction` method as follows:
```ts
onExecuteRowAction(event: DataRowActionEvent) { onExecuteRowAction(event: DataRowActionEvent) {
if (event.value.action.title = "Greetings") { if (event.value.action.title = "Greetings") {
@@ -325,8 +408,10 @@ To develop the enhancement, edit the `src/app/mydatatable/mydatatable.component.
} }
} }
```
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. After saving this, the application will be updated automatically and your browser should show something
like the following when the `Greetings` action is selected for a row:
![data_table_dataSource](../docassets/images/data_table_action2.png) ![data_table_dataSource](../docassets/images/data_table_action2.png)