diff --git a/ng2-components/ng2-activiti-form/README.md b/ng2-components/ng2-activiti-form/README.md index f8c02b3ac8..0f1b938059 100644 --- a/ng2-components/ng2-activiti-form/README.md +++ b/ng2-components/ng2-activiti-form/README.md @@ -110,7 +110,6 @@ Usage example of this component : **main.ts** ```ts - import { NgModule, Component } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; @@ -150,8 +149,6 @@ export class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule); - - ``` ### Display form instance by task id @@ -173,7 +170,7 @@ For an existing Task both form and values will be fetched and displayed. ``` -Only form definition will be fetched +Only form definition will be fetched. ### Display form definition by form name @@ -184,8 +181,11 @@ Only form definition will be fetched ``` -### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form. If there are no form -definied in activiti for the type of the node, a new form will be automaticaly created in activiti. +### Display form definition by ECM nodeId + +In this case the metadata of the node are showed in an activiti Form. +If there is no form definied in activiti for the type of the node, +a new form will be automaticaly created in Activiti. ```html ``` -### Display form definition by form name, and store the form field as metadata. The param nameNode is optional. +### Display form definition by form name, and store the form field as metadata. + +The param nameNode is optional. ```html ``` -### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form, and store the form field - as metadata. The param nameNode is optional. +### Display form definition by ECM nodeId + +In this case the metadata of the node are showed in an activiti Form, +and store the form field as metadata. The param nameNode is optional. ```html +``` + +This component depends on `FormRenderingService` service to map `FormFieldModel` to UI component +based on field type or metadata information. + +### Component type resolvers + +`FormRenderingService` maps field types to corresponding instances exposing `ComponentTypeResolver` interface: + +```ts +export interface ComponentTypeResolver { + (field: FormFieldModel): Type<{}>; +} +``` + +Typically a `ComponentTypeResolver` is a function that takes `FormFieldModel` and returns corresponding component type. +It can be either a predefined component type or a dynamically evaluated based on field properties and metadata. + +#### Static component mapping + +You can (re)map fields like following: + +```ts +let customResolver: ComponentTypeResolver = () => CustomWidgetComponent; +formRenderingService.setComponentTypeResolver('text', customResolver, true); +``` + +or simply: + +```ts +formRenderingService.setComponentTypeResolver('text', () => CustomWidgetComponent, true); +``` + +#### Dynamic component mapping + +Alternatively your resolver may return different component types based on `FormFieldModel` state and condition: + +```ts +let customResolver: ComponentTypeResolver = (field: FormFieldModel): Type<{}> => { + if (field) { + let params = field.params; + } + return UnknownWidget; +}; +formRenderingService.setComponentTypeResolver('text', customResolver, true); +``` + +### Default component mappings + +Stencil Name | Field Type | Component Type | +| --- | --- | --- | +| Text | text | TextWidget | +| Number | integer | NumberWidget | +| Multi-line text | multi-line-text | MultilineTextWidget | +| Checkbox | boolean | CheckboxWidget | +| Dropdown | dropdown | DropdownWidget | +| Date | date | DateWidget | +| Amount | amount | AmountWidget | +| Radio buttons | radio-buttons | RadioButtonsWidget | +| Hyperlink | hyperlink | HyperlinkWidget | +| Display value | readonly | DisplayValueWidget | +| Display text | readonly-text | DisplayTextWidget | +| Typeahead | typeahead | TypeaheadWidget | +| People | people | PeopleWidget | +| Group of people | functional-group | FunctionalGroupWidget | +| Dynamic table | dynamic-table | DynamicTableWidget | +| N/A | container | ContainerWidget (layout component) | +| Header | group | ContainerWidget | +| Attach | upload | AttachWidget or UploadWidget (based on metadata) | +| N/A | N/A | UnknownWidget | + + + +## Replacing default form widgets with custom components + +This is a short walkthrough on replacing a standard `Text` widget with a custom component for all Alfresco Activiti forms +rendered within `` component. + +First let's create a simple Alfresco Activiti form with `Text` widgets: + +![default text widget](assets/text-default-widget.png) + +Every custom widget must inherit `WidgetComponent` class in order to function properly: + +```ts +import { Component } from '@angular/core'; +import { WidgetComponent } from 'ng2-activiti-form'; + +@Component({ + selector: 'custom-editor', + template: ` +
Look, I'm a custom editor!
+ ` +}) +export class CustomEditorComponent extends WidgetComponent {} +``` + +Now you will need adding it to the application module or any custom module that is imported into the application one: + +```ts +import { NgModule } from '@angular/core'; +import { CustomEditorComponent } from './custom-editor.component'; + +@NgModule({ + declarations: [ CustomEditorComponent ], + exports: [ CustomEditorComponent ], + entryComponents: [ CustomEditorComponent ] +}) +export class CustomEditorsModule {} +``` + +Every custom widget should be added into all three module collections: `declarations`, `exports` and `entryComponents`. + +If you decided storing custom widgets in a separate dedicated module (and optionally as separate redistributable library) +don't forget importing it into your main application one: + +```ts +@NgModule({ + imports: [ + // ... + CustomEditorsModule + // ... + ], + providers: [], + bootstrap: [ AppComponent ] +}) +export class AppModule {} +``` + +Now you can import `FormRenderingService` in any of your Views and override default mapping similar to the following: + +```ts +import { Component } from '@angular/core'; +import { CustomEditorComponent } from './custom-editor.component'; + +@Component({...}) +export class MyView { + + constructor(formRenderingService: FormRenderingService) { + formRenderingService.setComponentTypeResolver('text', () => CustomEditorComponent, true); + } + +} +``` + +At runtime it should look similar to the following: + +![custom text widget](assets/text-custom-widget.png) + + + +## Replacing custom stencils with custom components + +This is a short walkthrough on rendering custom Alfresco Activiti stencils by means of custom Angular 2 components. + +### Creating custom stencil + +First let's create a basic stencil and call it `Custom Stencil 01`: + +![custom stencil](assets/activiti-stencil-01.png) + +_Note the `internal identifier` value as it will become a `field type` value when corresponding form is rendered._ + +Next put some simple html layout for `Form runtime template` and `Form editor template` fields: + +```html +
Custom activiti stencil
+``` + +Now you are ready to design a test form based on your custom stencil: + +![custom stencil form](assets/activiti-stencil-02.png) + +Once wired with a new task it should look like the following within Alfresco Activiti web application: + +![custom stencil task](assets/activiti-stencil-03.png) + +### Creating custom widget + +If you load previously created task into ADF `` component you will see something like the following: + +![adf stencil](assets/adf-stencil-01.png) + +Let's create an Angular 2 component to render missing content: + +```ts +import { Component } from '@angular/core'; +import { WidgetComponent } from 'ng2-activiti-form'; + +@Component({ + selector: 'custom-stencil-01', + template: `
ADF version of custom Activiti stencil
` +}) +export class CustomStencil01 extends WidgetComponent {} +``` + +Put it inside custom module: + +```ts +import { NgModule } from '@angular/core'; +import { CustomStencil01 } from './custom-stencil-01.component'; + +@NgModule({ + declarations: [ CustomStencil01 ], + exports: [ CustomStencil01 ], + entryComponents: [ CustomStencil01 ] +}) +export class CustomEditorsModule {} +``` + +And import into your Application Module + +```ts +@NgModule({ + imports: [ + // ... + CustomEditorsModule + // ... + ], + providers: [], + bootstrap: [ AppComponent ] +}) +export class AppModule {} +``` + +Now you can import `FormRenderingService` in any of your Views and provide new mapping: + +```ts +import { Component } from '@angular/core'; +import { CustomStencil01 } from './custom-stencil-01.component'; + +@Component({...}) +export class MyView { + + constructor(formRenderingService: FormRenderingService) { + formRenderingService.setComponentTypeResolver('custom_stencil_01', () => CustomStencil01, true); + } + +} +``` + +At the runtime you should now see your custom Angular 2 component rendered in place of the stencils: + +![adf stencil runtime](assets/adf-stencil-02.png) \ No newline at end of file