From 8037d4c76c31062574c6e80a67b4604df87095e1 Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Wed, 2 May 2018 16:43:47 +0100 Subject: [PATCH] [ADF-2679] Reviewed tutorials (#3254) * [ADF_2679] Reviewed tutorial text * [ADF-2679] Reviewed tutorials * [ADF-2679] Fixed glitches in index page --- docs/tutorials/README.md | 15 +- .../creating-the-app-using-yeoman.md | 81 ++- docs/tutorials/customising-login.md | 35 +- docs/tutorials/new-component.md | 58 +- docs/tutorials/new-view.md | 147 +++-- docs/tutorials/preparing-environment.md | 51 +- docs/tutorials/using-components.md | 175 ++++-- docs/tutorials/working-with-data-table.md | 589 ++++++++++-------- 8 files changed, 681 insertions(+), 470 deletions(-) diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index ad5f384341..9ed1b4999a 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -14,11 +14,10 @@ The tutorials are graded as follows: | 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. | -| [**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/). | -| [**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 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. | -| [**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). | -| [**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. | - +| [**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) | 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) | 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 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, and content projection / HTML extensions. In this tutorial you will see a practical example of each approach using the Login component. | +| [**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 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. | diff --git a/docs/tutorials/creating-the-app-using-yeoman.md b/docs/tutorials/creating-the-app-using-yeoman.md index 3f52412b42..7489e826f0 100644 --- a/docs/tutorials/creating-the-app-using-yeoman.md +++ b/docs/tutorials/creating-the-app-using-yeoman.md @@ -1,37 +1,42 @@ --- Level: Basic --- + # 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 -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 -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 -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) -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. - -**Process and Content Services** - -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: +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 +see a few warnings at the end like this: 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. @@ -43,34 +48,44 @@ 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 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 -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": { - "target": "http://localhost:8080", // <-- Change this! - "secure": false, - "changeOrigin": true - }, - "/activiti-app": { - "target": "http://localhost:9999", // <-- Change this! - "secure": false, - "changeOrigin": true - } -} + { + "/alfresco": { + "target": "http://localhost:8080", // <-- Change this! + "secure": false, + "changeOrigin": true + }, + "/activiti-app": { + "target": "http://localhost:9999", // <-- Change this! + "secure": false, + "changeOrigin": true + } ## 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) diff --git a/docs/tutorials/customising-login.md b/docs/tutorials/customising-login.md index 079a86d869..45931f1a98 100644 --- a/docs/tutorials/customising-login.md +++ b/docs/tutorials/customising-login.md @@ -1,31 +1,44 @@ --- 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 -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 -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: - - My custom HTML for the header - +```html + + My custom HTML for the header + +``` -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) ## 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. diff --git a/docs/tutorials/new-component.md b/docs/tutorials/new-component.md index ff3bbf8da8..7a1f5bb375 100644 --- a/docs/tutorials/new-component.md +++ b/docs/tutorials/new-component.md @@ -1,35 +1,59 @@ +--- +Level: Basic +--- + # 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. -v +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. + ## 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 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 -Once done, wherever you will use `` 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 `` 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 + +``` + +anywhere within the HTML file of another component to render the content of `my-first-component`. + +As an example, add `` 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 -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. - - `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. +By default the new component is created in the `src/app` path and everything is stored in a folder with the +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.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: - import { MyFirstComponentComponent } from './my-first-component/my-first-component.component'; +```ts +import { MyFirstComponentComponent } from './my-first-component/my-first-component.component'; - @NgModule({ - declarations: [ - ... - MyFirstComponentComponent - ], +@NgModule({ + declarations: [ + ... + 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. diff --git a/docs/tutorials/new-view.md b/docs/tutorials/new-view.md index 4b0ca3ac85..e752f40a8a 100644 --- a/docs/tutorials/new-view.md +++ b/docs/tutorials/new-view.md @@ -1,54 +1,67 @@ --- Level: Beginner --- + # 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 -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 -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 -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. - const appRoutes: Routes = [ - { path: 'path-in-the-app', component: ExistingComponent }, - { path: '**', component: PageNotFoundComponent } - ]; - - @NgModule({ - imports: [ - RouterModule.forRoot( - appRoutes, - { enableTracing: true } // <-- debugging purposes only. - ) - // other imports here - ], - ... - }) +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. -To add the new view to the routing, change the `appRoutes` constant as follow. +```ts +const appRoutes: Routes = [ + { path: 'path-in-the-app', component: ExistingComponent }, + { path: '**', component: PageNotFoundComponent } +]; - const appRoutes: Routes = [ - { path: 'path-in-the-app', component: ExistingComponent }, - { path: 'my-first-view', component: MyFirstViewComponent }, // <-- Add this! - { path: '**', component: PageNotFoundComponent } - ]; +@NgModule({ + imports: [ + RouterModule.forRoot( + appRoutes, + { enableTracing: true } // <-- debugging purposes only. + ) + // other imports here + ], + ... +}) +``` + +To add the new view to the routing, change the `appRoutes` constant as follows: + +```ts +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'; +```ts +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 -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://:/my-first-view @@ -58,55 +71,63 @@ The result should be a very simple page with the following content. ## 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: - const appRoutes: Routes = [ - { path: 'path-in-the-app', component: ExistingComponent }, - { path: 'my-first-view/:name', component: MyFirstViewComponent }, // <-- Add this! - { path: '**', component: PageNotFoundComponent } - ]; +```ts +const appRoutes: Routes = [ + { path: 'path-in-the-app', component: ExistingComponent }, + { path: 'my-first-view/:name', component: MyFirstViewComponent }, // <-- Change 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: +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. 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! +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: - 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(); - } - } +```ts +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; -Next open the template `my-first-view.component.html` in the same folder and print out the greeting like the following source code. +@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 add the greeting as in +the following source code. + +```html

Hello {{ name }}

+``` You can now navigate to `http://:/my-first-view/sir` and see the nice message "Hello sir". diff --git a/docs/tutorials/preparing-environment.md b/docs/tutorials/preparing-environment.md index 16f9fb4028..24940cf418 100644 --- a/docs/tutorials/preparing-environment.md +++ b/docs/tutorials/preparing-environment.md @@ -1,50 +1,63 @@ --- 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](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. -To check the version, run the following command in a terminal. +You need the latest `node.js` from either the `8.x` or `9.x` branch. +If you already have it installed then you can check the version with the following command in a terminal: node -v ## 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 -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 ## 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) -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 -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. - -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. +You can install the latest version of the `generator-alfresco-adf-app` (the main scaffold generator) +using the following command: 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 diff --git a/docs/tutorials/using-components.md b/docs/tutorials/using-components.md index 98008a133a..5792f78010 100644 --- a/docs/tutorials/using-components.md +++ b/docs/tutorials/using-components.md @@ -1,107 +1,148 @@ --- Level: Beginner --- + # 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. 2. Event listeners. 3. Content projection / HTML extensions. ## 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. - - - -When reviewing the documentation you can see that the `` 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). +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 + + +``` -Once saved the HTML template you will see the login page updated with a different layout accordingly with the property values. +Looking at the documentation, you can see that the `` 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). -**Notice:** The two new properties are specified with `[]` around them. There are three ways to configure a component. +```html + + +``` -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. +After saving the HTML template, you will see the login page updated with a different layout matching the +new property values. + +**Note:** The two new properties are specified with `[]` around them. There are three ways to configure a +property: + +1. `[property]=""` This sets the property using an expression or another property from the Typescript +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. ## Event listeners -Now that you've successfully configured properties on the `` component, it's time to look at the events. +Now that you've successfully configured properties on the `` 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 `` component (the position is not relevant). +Back in the `login.component.html` file, add `(success)="mySuccessMethod($event)"` to the `` component (the position is not relevant). - - +```html + + +``` -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: - @Component({ - ... - }) - export class LoginComponent { - - ... +```ts +@Component({ + ... +}) +export class LoginComponent { - // Add this! - myExecuteSubmitMethod(event: any) { - alert('Form was submitted!'); - console.log(event); - } + ... + + // 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. +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 -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. -
-

- Here we have some bold text -

-
+In regular HTML, elements can be nested. For example: -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. +```html +
+

+ Here we have some bold text +

+
+``` -The `` 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 `` tag. +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 `` 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 `` tag: - - - - Hello World! - - - +```html + + + + Hello World! + + + +``` -Watch carefully that you place the `` tag *inside* the `` tag. Inside the `` or `` tags you can put anything you want, as long as you wrap it inside an `` tag. You can also source in custom or 3rd party components. +Make sure that you place the `` tag *inside* the `` tag. Inside the +`` or `` tags you can put anything you want, as long as you wrap it inside +an `` 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. diff --git a/docs/tutorials/working-with-data-table.md b/docs/tutorials/working-with-data-table.md index c423039a67..d0bd502cd4 100644 --- a/docs/tutorials/working-with-data-table.md +++ b/docs/tutorials/working-with-data-table.md @@ -1,332 +1,417 @@ --- 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. +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 -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): - { - "list": { - "pagination": { - "count": 46, - "hasMoreItems": false, - "totalItems": 46, - "skipCount": 0, - "maxItems": 100 +```json +{ + "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" }, - "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. +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 -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: - import {MydatatableComponent} from './mydatatable/mydatatable.component'; +```ts +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 - }, - ... - ]; +```ts +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. +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: - import { ObjectDataTableAdapter } from '@alfresco/adf-core'; +```ts +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: - 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' - } - ] - ); +```ts +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 `` 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 `` 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 + + + + + + + + + + +``` -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 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 + + ....... +``` -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: - onRowClick(event: any) { - alert('We just clicked row id: ' + event.value.obj.id); - } +```ts +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. +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 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. -* `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. +- `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 in the data, +but other modes are also available: + - `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 it 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` toggles whether or not the column can be sorted. +- `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 -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: - 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' - } - ] - ); +```ts +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 `` 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 `` to project our own content +into it. Open the template and add the following code: - - - - - - +```html + + + + + + +``` -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) ## 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 { 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 populates the table with the response of the services (assumed to +be in JSON but it could be in any format). + +After saving the file, you should see something like the following in the browser: + +![data_table_dataSource](../docassets/images/data_table_dataSource.png) + +## Adding an action + +A common and straightforward customization for a DataTable is to add an action to each row or to rows +that meet certain conditions. + +Make the changes shown below to the `src/app/mydatatable/mydatatable.component.html` file: + +```html + + +``` + +Also update `src/app/mydatatable/mydatatable.component.ts` as follows: + +```ts +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}'); +} +``` + +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) + +Note that the browser console has a log describing how the row object is shown for debugging purposes. + +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 follows: + +```ts +onExecuteRowAction(event: DataRowActionEvent) { + + if (event.value.action.title = "Greetings") { - 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', + 'people/' + event['value']['row']['obj']['id'], [], 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); })); + alert(JSON.stringify(response.entry)); } ); - - } - 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. - -![data_table_dataSource](../docassets/images/data_table_dataSource.png) - -## 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. - - - - -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. - -![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. - -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. +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)