diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index a881122c5e..3e4434206f 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -82,7 +82,10 @@ import { ProcessServicesCloudModule } from '@alfresco/adf-process-services-cloud import { FilteredSearchComponent } from './components/files/filtered-search.component'; import { RouterModule } from '@angular/router'; import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-layout.component'; -import { SampleWidgetComponent } from './components/cloud/custom-form-components/sample-widget.component'; +import { + CustomEditorComponent, + CustomWidgetComponent +} from './components/cloud/custom-form-components/custom-editor.component'; import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; @@ -188,7 +191,8 @@ registerLocaleData(localeSv); ConfirmDialogExampleComponent, FormCloudDemoComponent, ConfirmDialogExampleComponent, - SampleWidgetComponent, + CustomEditorComponent, + CustomWidgetComponent, ProcessCloudLayoutComponent ], providers: [ diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts index c4966f25ba..0f890812cf 100644 --- a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts @@ -28,7 +28,10 @@ import { FormCloudService } from '@alfresco/adf-process-services-cloud'; import { Subscription } from 'rxjs'; -import { SampleWidgetComponent } from '../../../cloud/custom-form-components/sample-widget.component'; +import { + CustomEditorComponent, + CustomWidgetComponent +} from '../../../cloud/custom-form-components/custom-editor.component'; @Component({ templateUrl: 'cloud-form-demo.component.html', @@ -60,7 +63,16 @@ export class FormCloudDemoComponent implements OnInit, OnDestroy { private automationService: CoreAutomationService, private formRenderingService: FormRenderingService) { this.formRenderingService.register({ - 'custom': () => SampleWidgetComponent + 'demo-widget': () => CustomEditorComponent, + 'custom-editor': () => CustomEditorComponent, + 'custom-string': () => CustomWidgetComponent, + 'custom-datetime': () => CustomWidgetComponent, + 'custom-file': () => CustomWidgetComponent, + 'custom-number': () => CustomWidgetComponent, + 'custom-something': () => CustomWidgetComponent, + 'custom-boolean': () => CustomWidgetComponent, + 'custom-date': () => CustomWidgetComponent, + 'custom': () => CustomWidgetComponent }); } diff --git a/demo-shell/src/app/components/cloud/custom-form-components/sample-widget.component.ts b/demo-shell/src/app/components/cloud/custom-form-components/custom-editor.component.ts similarity index 71% rename from demo-shell/src/app/components/cloud/custom-form-components/sample-widget.component.ts rename to demo-shell/src/app/components/cloud/custom-form-components/custom-editor.component.ts index c730460bf3..83ad39a908 100644 --- a/demo-shell/src/app/components/cloud/custom-form-components/sample-widget.component.ts +++ b/demo-shell/src/app/components/cloud/custom-form-components/custom-editor.component.ts @@ -17,14 +17,29 @@ import { Component, OnInit } from '@angular/core'; import { FormService, WidgetComponent } from '@alfresco/adf-core'; +// tslint:disable:component-selector + +@Component({ + selector: 'custom-editor-widget', + template: ` +
+ ADF version of custom form widget +
+ ` +}) +export class CustomEditorComponent extends WidgetComponent { + constructor() { + super(); + } +} @Component({ selector: 'app-sample-widget', template: `
- Look, I'm custom cloud form widget!

- Value :: {{displayValue}} + + {{field.value}}

@@ -37,21 +52,20 @@ import { FormService, WidgetComponent } from '@alfresco/adf-core'; [value]="field.value" [(ngModel)]="field.value" (ngModelChange)="onFieldChanged(field)"> + {{field.placeholder}}
` }) -export class SampleWidgetComponent extends WidgetComponent implements OnInit { - - displayValue: string; +export class CustomWidgetComponent extends WidgetComponent implements OnInit { constructor(public formService: FormService) { super(formService); } ngOnInit() { - this.displayValue = this.field.value; + this.field.value = typeof this.field.value === 'object' ? JSON.stringify(this.field.value) : this.field.value; } } diff --git a/demo-shell/src/app/components/cloud/process-cloud-layout.component.ts b/demo-shell/src/app/components/cloud/process-cloud-layout.component.ts index c7478f7a5c..7df8d0e247 100644 --- a/demo-shell/src/app/components/cloud/process-cloud-layout.component.ts +++ b/demo-shell/src/app/components/cloud/process-cloud-layout.component.ts @@ -18,7 +18,7 @@ import { Component } from '@angular/core'; import { FormRenderingService } from '@alfresco/adf-core'; import { CloudFormRenderingService } from '@alfresco/adf-process-services-cloud'; -import { SampleWidgetComponent } from './custom-form-components/sample-widget.component'; +import { CustomEditorComponent, CustomWidgetComponent } from './custom-form-components/custom-editor.component'; @Component({ template: ``, @@ -30,7 +30,16 @@ export class ProcessCloudLayoutComponent { constructor(private formRenderingService: FormRenderingService) { this.formRenderingService.register({ - 'custom': () => SampleWidgetComponent + 'custom-editor': () => CustomEditorComponent, + 'demo-widget': () => CustomEditorComponent, + 'custom-string': () => CustomWidgetComponent, + 'custom-datetime': () => CustomWidgetComponent, + 'custom-file': () => CustomWidgetComponent, + 'custom-number': () => CustomWidgetComponent, + 'custom-something': () => CustomWidgetComponent, + 'custom-boolean': () => CustomWidgetComponent, + 'custom-date': () => CustomWidgetComponent, + 'custom': () => CustomWidgetComponent }); } } diff --git a/docs/docassets/images/aae-form-widget.png b/docs/docassets/images/aae-form-widget.png new file mode 100644 index 0000000000..d7b9a2dbe8 Binary files /dev/null and b/docs/docassets/images/aae-form-widget.png differ diff --git a/docs/docassets/images/aae-form-with-widget.png b/docs/docassets/images/aae-form-with-widget.png new file mode 100644 index 0000000000..1aee104efb Binary files /dev/null and b/docs/docassets/images/aae-form-with-widget.png differ diff --git a/docs/docassets/images/aae-resolved-widget.png b/docs/docassets/images/aae-resolved-widget.png new file mode 100644 index 0000000000..c9e039150f Binary files /dev/null and b/docs/docassets/images/aae-resolved-widget.png differ diff --git a/docs/docassets/images/aae-simple-form.png b/docs/docassets/images/aae-simple-form.png new file mode 100644 index 0000000000..7027e16280 Binary files /dev/null and b/docs/docassets/images/aae-simple-form.png differ diff --git a/docs/docassets/images/aae-simple-override-form.png b/docs/docassets/images/aae-simple-override-form.png new file mode 100644 index 0000000000..10465d5e0e Binary files /dev/null and b/docs/docassets/images/aae-simple-override-form.png differ diff --git a/docs/docassets/images/aae-unresolved-widget.png b/docs/docassets/images/aae-unresolved-widget.png new file mode 100644 index 0000000000..ffb2ea4946 Binary files /dev/null and b/docs/docassets/images/aae-unresolved-widget.png differ diff --git a/docs/user-guide/aae-extensions.md b/docs/user-guide/aae-extensions.md new file mode 100644 index 0000000000..743dd6153a --- /dev/null +++ b/docs/user-guide/aae-extensions.md @@ -0,0 +1,172 @@ +--- +Title: Form Extensibility for AAE Form Widget +Added: v4.1.0 +--- + +## Form Extensibility for AAE Form Widget +This page describes how you can customize ADF forms to your own specification. + +## Contents +There are two ways to customize the form +- [Replace default form widgets with custom components](#replace-default-form-widgets-with-aae-form-widgets) +- [Replace custom form widget with custom components](#replace-custom-form-widgets-with-custom-components) + +## Replace default form widgets with AAE form widgets + +This is an example of replacing the standard `Text` [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) with a custom component for all AAE forms rendered within the `` component. + +1. Create a simple form with some `Text` widgets: + + ![default text widget](../docassets/images/aae-simple-form.png) + + Every custom widget component must inherit the [`WidgetComponent`](../insights/components/widget.component.md) class in order to function properly: + + ```ts + import { Component } from '@angular/core'; + import { WidgetComponent } from '@alfresco/adf-core'; + @Component({ + selector: 'custom-editor', + template: ` +
Look, I'm a AAE custom editor!
+ ` + }) + export class CustomEditorComponent extends WidgetComponent {} + ``` + +2. Add 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 ] + }) + export class CustomEditorsModule {} + ``` + +3. Every custom widget component should be added into the the collections `declarations` and `exports`. If you decided to store custom widgets in a separate dedicated module (and optionally as a separate re-distributable library) don't forget to import it into the main application: + + ```ts + @NgModule({ + imports: [ + // ... + CustomEditorsModule + // ... + ], + providers: [], + bootstrap: [ AppComponent ] + }) + export class AppModule {} + ``` + +4. Import the [`FormRenderingService`](../core/services/form-rendering.service.md) into any of your Views and override the default mapping, for example: + + ```ts + import { Component } from '@angular/core'; + import { CustomEditorComponent } from './custom-editor.component'; + @Component({...}) + export class MyView { + constructor(formRenderingService: FormRenderingService) { + this.formRenderingService.register({ + 'text': () => CustomEditorComponent + }, true); + } + } + ``` + +5. At runtime the form should look similar to the following: + + ![custom text widget](../docassets/images/aae-simple-override-form.png) + + +## Replace custom form widgets with custom components + +This is an example of rendering custom form widgets using custom Angular components. + +### Create a custom form widget + +To begin, create a basic form widget and call it `demo-widget`: + +![custom form widget](../docassets/images/aae-form-widget.png) + +**Note**: The `type` is important as it will become the `field type` when the form is rendered. + +You can now design a form that uses your custom form widget: + +![custom form widget form](../docassets/images/aae-form-with-widget.png) + +### Create a custom widget + +When displayed in a task, the field will look similar to the following: + +![adf form widget](../docassets/images/aae-unresolved-widget.png) + + +To render the missing content: + +1. Create an Angular component: + + ```ts + import { Component } from '@angular/core'; + import { WidgetComponent } from '@alfresco/adf-core'; + @Component({ + selector: 'app-demo-widget', + template: `
ADF version of custom form widget
` + }) + export class DemoWidgetComponent extends WidgetComponent {} + ``` + +2. Place it inside the custom module: + + ```ts + import { NgModule } from '@angular/core'; + import { DemoWidgetComponent } from './demo-widget.component'; + @NgModule({ + declarations: [ DemoWidgetComponent ], + exports: [ DemoWidgetComponent ] + }) + export class CustomWidgetsModule {} + ``` + +3. Import it into your Application Module: + + ```ts + @NgModule({ + imports: [ + // ... + CustomWidgetsModule + // ... + ], + providers: [], + bootstrap: [ AppComponent ] + }) + export class AppModule {} + ``` + +4. Import the [`FormRenderingService`](../core/services/form-rendering.service.md) in any of your Views and provide the new mapping: + + ```ts + import { Component } from '@angular/core'; + import { DemoWidgetComponent } from './demo-widget.component'; + @Component({...}) + export class MyView { + constructor(formRenderingService: FormRenderingService) { + this.formRenderingService.register({ + 'custom-editor': () => DemoWidgetComponent + }); + } + } + ``` + +At runtime you should now see your custom Angular component rendered in place of the original form widgets: + +![adf form widget runtime](../docassets/images/aae-resolved-widget.png) + +## See Also + +- [Extensibility](./extensibility.md) +- [Form field model](../core/models/form-field.model.md) +- [Form rendering service](../core/services/form-rendering.service.md) +- [Form component](../core/components/form.component.md) +- [Widget component](../insights/components/widget.component.md) diff --git a/docs/user-guide/aps-extensions.md b/docs/user-guide/aps-extensions.md new file mode 100644 index 0000000000..9e523a779d --- /dev/null +++ b/docs/user-guide/aps-extensions.md @@ -0,0 +1,184 @@ +--- +Title: Form Extensibility for APS Stencil +Added: v1.9.0 +--- + +## Form Extensibility for APS Stencil +This page describes how you can customize ADF forms to your own specification. + +## Contents +There are two ways to customize the form +- [Replace default form widgets with custom components](#replacing-default-form-widgets-with-custom-components) +- [Replace custom stencils with custom components](#replacing-custom-stencils-with-custom-components) + +## Replace default form widgets with custom components + +This is an example of replacing the standard `Text` [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) with a custom component for all APS forms rendered within the `` component. + +1. Create a simple form with some `Text` widgets: + + ![default text widget](../docassets/images/text-default-widget.png) + + Every custom [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) must inherit the [`WidgetComponent`](../insights/components/widget.component.md) class in order to function properly: + + ```ts + import { Component } from '@angular/core'; + import { WidgetComponent } from '@alfresco/adf-core'; + + @Component({ + selector: 'custom-editor', + template: ` +
Look, I'm a custom editor!
+ ` + }) + export class CustomEditorComponent extends WidgetComponent {} + ``` + +2. Add 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 ] + }) + export class CustomEditorsModule {} + ``` + +3. Every custom [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) should be added into the collections: `declarations` and `exports`. If you decided to store custom widgets in a separate dedicated module (and optionally as a separate re-distributable library), don't forget to import it into the main application: + + ```ts + @NgModule({ + imports: [ + // ... + CustomEditorsModule + // ... + ], + providers: [], + bootstrap: [ AppComponent ] + }) + export class AppModule {} + ``` + +4. Import the [`FormRenderingService`](../core/services/form-rendering.service.md) in any of your Views and override the default mapping, for example: + + ```ts + import { Component } from '@angular/core'; + import { CustomEditorComponent } from './custom-editor.component'; + + @Component({...}) + export class MyView { + + constructor(formRenderingService: FormRenderingService) { + formRenderingService.setComponentTypeResolver('text', () => CustomEditorComponent, true); + } + + } + ``` + +5. At runtime it should look similar to the following: + + ![custom text widget](../docassets/images/text-custom-widget.png) + +## Replace custom stencils with custom components + +This is an example of rendering custom APS stencils using custom Angular components. + +### Create a custom stencil + +1. Create a basic stencil and call it `Custom Stencil 01`: + + ![custom stencil](../docassets/images/activiti-stencil-01.png) + + **Note**: the `internal identifier` is important as it will become the `field type` when the form is rendered. + +2. Create a simple html layout for the [`Form`](../../lib/process-services/src/lib/task-list/models/form.model.ts)`runtime template` and [`Form`](../../lib/process-services/src/lib/task-list/models/form.model.ts)`editor template` fields: + + ```html +
Custom activiti stencil
+ ``` + +3. Create a test form based on your custom stencil: + + ![custom stencil form](../docassets/images/activiti-stencil-02.png) + +4. Create a task using the test form. It will look similar to the following: + + ![custom stencil task](../docassets/images/activiti-stencil-03.png) + +### Create a custom widget + +1. Load the form created in the previous steps into the ADF `` component: + + ![adf stencil](../docassets/images/adf-stencil-01.png) + +2. Create an Angular component to render the missing content: + + ```ts + import { Component } from '@angular/core'; + import { WidgetComponent } from '@alfresco/adf-core'; + + @Component({ + selector: 'custom-stencil-01', + template: `
ADF version of custom Activiti stencil
` + }) + export class CustomStencil01 extends WidgetComponent {} + ``` + +3. Place it inside a custom module: + + ```ts + import { NgModule } from '@angular/core'; + import { CustomStencil01 } from './custom-stencil-01.component'; + + @NgModule({ + declarations: [ CustomStencil01 ], + exports: [ CustomStencil01 ] + }) + export class CustomEditorsModule {} + ``` + +4. Import it into your Application Module: + + ```ts + @NgModule({ + imports: [ + // ... + CustomEditorsModule + // ... + ], + providers: [], + bootstrap: [ AppComponent ] + }) + export class AppModule {} + ``` + +5. Import the [`FormRenderingService`](../core/services/form-rendering.service.md) in any of your Views and provide the 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); + } + + } + ``` + +6. At runtime you should now see your custom Angular component rendered in place of the stencils: + + ![adf stencil runtime](../docassets/images/adf-stencil-02.png) + +## See Also + +- [Extensibility](./extensibility.md) +- [Form field model](../core/models/form-field.model.md) +- [Form rendering service](../core/services/form-rendering.service.md) +- [Form component](../core/components/form.component.md) +- [Widget component](../insights/components/widget.component.md) diff --git a/docs/user-guide/extensibility.md b/docs/user-guide/extensibility.md index 7d84cc308f..a00271578f 100644 --- a/docs/user-guide/extensibility.md +++ b/docs/user-guide/extensibility.md @@ -18,10 +18,7 @@ _Note: it is assumed you are familiar with Alfresco Process Services (powered by - [How components and widgets are rendered on a Form](#how-components-and-widgets-are-rendered-on-a-form) - [Component type resolvers](#component-type-resolvers) - [Default component mappings](#default-component-mappings) -- [Replacing default form widgets with custom components](#replacing-default-form-widgets-with-custom-components) -- [Replacing custom stencils with custom components](#replacing-custom-stencils-with-custom-components) - - [Creating custom stencil](#creating-custom-stencil) - - [Creating custom widget](#creating-custom-widget) +- [Form Extensibility for APS/AAE](#form-extensibility-for-apsaae) - [See Also](#see-also) ## How components and widgets are rendered on a Form @@ -102,173 +99,9 @@ formRenderingService.setComponentTypeResolver('text', customResolver, true); | Attach | upload | AttachWidgetComponent or [`UploadWidgetComponent`](../../lib/core/form/components/widgets/upload/upload.widget.ts) (based on metadata) | | N/A | N/A | [`UnknownWidgetComponent`](../../lib/core/form/components/widgets/unknown/unknown.widget.ts) | -## Replacing default form widgets with custom components - -This is a short walkthrough on replacing a standard `Text` [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) with a custom component for all APS forms -rendered within `` component. - -First let's create a simple APS form with `Text` widgets: - -![default text widget](../docassets/images/text-default-widget.png) - -Every custom [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) must inherit [`WidgetComponent`](../insights/components/widget.component.md) class in order to function properly: - -```ts -import { Component } from '@angular/core'; -import { WidgetComponent } from '@alfresco/adf-core'; - -@Component({ - selector: 'custom-editor', - template: ` -
Look, I'm a custom editor!
- ` -}) -export class CustomEditorComponent extends WidgetComponent {} -``` - -Now you will need to add 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 ] -}) -export class CustomEditorsModule {} -``` - -Every custom [widget](../../lib/testing/src/lib/core/pages/form/widgets/widget.ts) should be added into the following collections: `declarations`, `exports`. - -If you decided to store custom widgets in a separate dedicated module (and optionally as separate redistributable library) -don't forget to import it into your main application one: - -```ts -@NgModule({ - imports: [ - // ... - CustomEditorsModule - // ... - ], - providers: [], - bootstrap: [ AppComponent ] -}) -export class AppModule {} -``` - -Now you can import [`FormRenderingService`](../core/services/form-rendering.service.md) 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](../docassets/images/text-custom-widget.png) - -## Replacing custom stencils with custom components - -This is a short walkthrough on rendering custom APS stencils by means of custom Angular components. - -### Creating custom stencil - -First let's create a basic stencil and call it `Custom Stencil 01`: - -![custom stencil](../docassets/images/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`](../../lib/process-services/src/lib/task-list/models/form.model.ts)`runtime template` and [`Form`](../../lib/process-services/src/lib/task-list/models/form.model.ts)`editor template` fields: - -```html -
Custom activiti stencil
-``` - -Now you are ready to design a test form based on your custom stencil: - -![custom stencil form](../docassets/images/activiti-stencil-02.png) - -Once wired with a new task it should look like the following within APS web application: - -![custom stencil task](../docassets/images/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](../docassets/images/adf-stencil-01.png) - -Let's create an Angular component to render missing content: - -```ts -import { Component } from '@angular/core'; -import { WidgetComponent } from '@alfresco/adf-core'; - -@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 ] -}) -export class CustomEditorsModule {} -``` - -And import into your Application Module - -```ts -@NgModule({ - imports: [ - // ... - CustomEditorsModule - // ... - ], - providers: [], - bootstrap: [ AppComponent ] -}) -export class AppModule {} -``` - -Now you can import [`FormRenderingService`](../core/services/form-rendering.service.md) 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 runtime you should now see your custom Angular component rendered in place of the stencils: - -![adf stencil runtime](../docassets/images/adf-stencil-02.png) +## Form Extensibility for APS/AAE +- [Form Extensibility for APS Stencil](./aps-extensions.md) +- [Form Extensibility for AAE Form Widget](./aae-extensions.md) ## See Also