From df9563aaffcb43506ba13d11dc5a4d841ab56404 Mon Sep 17 00:00:00 2001 From: Steve Rhoades Date: Fri, 17 Jan 2020 23:30:09 -0800 Subject: [PATCH] Add documentation section for the dynamic option and list data --- README.md | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/README.md b/README.md index 282107a39..f64797bc3 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Explore the [**live sample**](http://ng2-dynamic-forms.udos86.de/sample/index.ht - [Form Control Configuration](#form-control-configuration) - [Form Control Events](#form-control-events) - [Updating Form Controls](#updating-form-controls) +- [Dynamic Option and List Population](#dynamic-form-control-option-and-list-population) - [Custom Templates](#custom-templates) - [Custom Validators](#custom-validators) - [Custom Form Controls](#custom-form-controls) @@ -689,6 +690,123 @@ To optimize this you can optionally pass a `DynamicFormComponent` to `detectChan this.formService.detectChanges(this.formComponent); ``` +## Dynamic Option And List Population +A common use case of forms is having select, datalist, checkboxes and radio buttons automatically populate based on another form controls value. NG Dynamic Forms accomplishes this by allowing you to provide a `service` per form control to dynamically pull these values based on a related form controls input. + +### Configuration +To connect your form controls you will need to provide a `dataProvider` attribute along with a relation with a path to the `id` or `rootPath` of the related form control. Additionally you will need to provide a `service` which is a token from which your service can be pulled from DI. + +| Name | Description | +| :--- | :--- | +| relation | Similar to how relations work, you provide a rootPath or id to the related control | +| *relation*.id | ID of the input control | +| *relation*.rootPath | The path to the input control from the form group. | +| service | A token representing the service in the DI. | + +```typescript +export function WikiPageForm(): DynamicFormControlModel[] { + return [ + new DynamicInputModel({ + id: 'wiki-title', + label: 'Search Title', + value: '', + validators: { + required: null, + }, + errorMessages: { + required: '{{ label }} is required', + }, + }), + new DynamicSelectModel({ + id: 'wiki-page', + label: 'Wiki Page', + value: '-1', + options: [{value: '-1', label: '-- select a wikipedia page'}], + dataProvider: { + relation: {id: 'wiki-title'}, + service: WikipediaService, + }, + relations: [ + { + match: MATCH_DISABLED, + when: [ + { + rootPath: 'wiki-title', value: '', + }, + ], + }, + ], + validators: { + required: null, + }, + errorMessages: { + required: '{{ label }} is required', + }, + }) + ]; +} +``` +### Data Provider +NG Dynamic forms will look attempt to inject a given service via the token provided by the `dataProvider.service` definition. Your service must implement one of two methods depending on your form control. + +| Control Name | Interface | +| :--- | :--- | +| DynamicInputModel | DynamicFormControlListDataProvider\ | +| DynamicSelectModel | DynamicFormControlOptionDataProvider\ | +| DynamicSelectModel | DynamicFormControlOptionDataProvider\ | +| DynamicRadioModel | DynamicFormControlOptionDataProvider\ | +| DynamicCheckboxModel | DynamicFormControlOptionDataProvider\ | + +```typescript +const WIKI_URL = 'https://en.wikipedia.org/w/api.php'; +const PARAMS = new HttpParams({ + fromObject: { + action: 'opensearch', + format: 'json', + origin: '*', + }, +}); + +@Injectable({ + providedIn: 'root', +}) +export class WikipediaService + implements DynamicFormControlListDataProvider, DynamicFormControlOptionDataProvider { + constructor(private http: HttpClient) {} + + fetchList(value: string): Observable { + return this.fetch(value); + } + + fetchOptions(value: string): Observable[]> { + return this.fetch(value).pipe(map( + response => { + if (!Array.isArray(response)) { + return []; + } + + return response.map((val) => { + return { + label: val, + value: val as string, + } as DynamicFormOptionConfig; + }); + }), + ); + } + + fetch(term: string): Observable { + if (typeof(term) !== 'string' || term === '') { + return of([]); + } + + return this.http + .get(WIKI_URL, {params: PARAMS.set('search', term)}).pipe( + map(response => response[1]), + ); + } +} +``` ## Custom Templates