Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically populate a controls list or options based on a related controls value #1055

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

steverhoades
Copy link

@steverhoades steverhoades commented Jan 13, 2020

The purpose of this PR is to allow for the dynamic population of related input values.

Goals:

  • Allow the value of one input to automatically and asynchronously populate the list or options for another input

Configuration

This PR introduces another configuration attribute on the DynamicFormControlModel.
The dataProvider attribute contains the following properties.

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 The service that will be used to fetch the data on related input control value change

Usage

Example Configuration

car-details.form.ts
import { CarDataProviderService } from './car-data-provider.service.ts';

export function CarDetailsForm(): DynamicFormControlModel[] {
  return [
    new DynamicSelectModel({
      id: 'make',
      label: 'Make',
      value: '',
      options: [
        {value: '', label: '-- Select a Make'},
        {value: 'chevy', label: 'Chevrolet'},
        {value: 'ford', label: 'Ford'},
        {value: 'toyota', label: 'Toyota'},
      ],
      validators: {
        required: null,
      },
      errorMessages: {
        required: '{{ label }} is required',
      },
    }),
    new DynamicSelectModel({
      id: 'model',
      label: 'Model',
      value: '',
      options: [
        {value: '', label: '-- Select a Model'},
      ],
      dataProvider: {
        relation: {id: 'make'},
        service: CarDataProviderService,
      },
      relations: [
        {
          match: MATCH_DISABLED,
          when: [
            {
              id: 'make', value: '',
            },
          ],
        },
      ],
      validators: {
        required: null,
      },
      errorMessages: {
        required: '{{ label }} is required',
      },
    }),
  ];
}

Create a data provider. The data provider must implement one of two service interfaces DynamicFormControlListDataProvider or DynamicFormControlOptionsDataProvider.
Note: The service must return an Observable.

car-data-provider.service.ts
import {Observable, of} from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class CarDataProviderService implements DynamicFormControlOptionDataProvider<string> {

  fetchOptions(value: string): Observer<DynamicFormOptionConfig<string>[]> {
    switch (value) {
      case 'chevy':
        return of([
          {
            value: 'silverado',
            label: 'Silverado',
          },
          {
            value: 'traverse',
            label: 'Traverse',
          },
        ]);
        break;
      case 'ford':
        return of([
          {
            value: 'f150',
            label: 'F150',
          },
          {
            value: 'f250',
            label: 'f250',
          },
        ]);        
        break;
      case 'toyota':
        return of([
          {
            value: 'tacoma',
            label: 'Tacoma',
          },
          {
            value: 'tundra',
            label: 'Tundra',
          },
        ]);
        break;        
    }
  }
}

Note

This PR is based off my previous PR #1054

…sage support, add custom error message function support
…ows for building proxying form components. Add support for the input event on input controls to support use cases such as characters left
@steverhoades steverhoades changed the title WIP: Dynamically populate a controls list and options based on related control values WIP: Dynamically populate a controls list or options based on related control values Jan 13, 2020
@steverhoades steverhoades changed the title WIP: Dynamically populate a controls list or options based on related control values WIP: Dynamically populate a controls list or options based on related controls value Jan 13, 2020
@steverhoades steverhoades changed the title WIP: Dynamically populate a controls list or options based on related controls value WIP: Dynamically populate a controls list or options based on a related controls value Jan 13, 2020
@codecov-io
Copy link

codecov-io commented Jan 13, 2020

Codecov Report

Merging #1055 into master will increase coverage by 0.16%.
The diff coverage is 95.65%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1055      +/-   ##
==========================================
+ Coverage   90.49%   90.65%   +0.16%     
==========================================
  Files         170      171       +1     
  Lines        2673     2719      +46     
  Branches      247      257      +10     
==========================================
+ Hits         2419     2465      +46     
+ Misses        196      193       -3     
- Partials       58       61       +3
Impacted Files Coverage Δ
...-ngx-bootstrap-form-control-container.component.ts 100% <100%> (ø) ⬆️
.../dynamic-basic-form-control-container.component.ts 100% <100%> (ø) ⬆️
...c-ng-bootstrap-form-control-container.component.ts 97.5% <100%> (+0.06%) ⬆️
.../dynamic-ionic-form-control-container.component.ts 65.78% <100%> (+0.92%) ⬆️
...s/core/src/lib/model/dynamic-form-control.model.ts 97.22% <100%> (+0.16%) ⬆️
...ynamic-primeng-form-control-container.component.ts 82.35% <100%> (+0.35%) ⬆️
...namic-material-form-control-container.component.ts 95% <100%> (+0.12%) ⬆️
.../dynamic-kendo-form-control-container.component.ts 77.35% <100%> (+0.43%) ⬆️
...ms/core/src/lib/service/dynamic-form-validators.ts 100% <100%> (ø) ⬆️
...amic-bootstrap-form-control-container.component.ts 100% <100%> (ø) ⬆️
... and 6 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4ea5ace...dff4256. Read the comment docs.

@steverhoades steverhoades force-pushed the feature/dynamic-data-connectors branch from 2e934b1 to d9b641e Compare January 18, 2020 04:44
@steverhoades steverhoades force-pushed the feature/dynamic-data-connectors branch from df9563a to dff4256 Compare January 18, 2020 18:15
@steverhoades steverhoades changed the title WIP: Dynamically populate a controls list or options based on a related controls value Dynamically populate a controls list or options based on a related controls value Jan 18, 2020
@matheo
Copy link

matheo commented Apr 16, 2021

Hi @steverhoades
Do you mind to share your experience with dynamic forms
in the discussions of a new library to implement advanced features?
https://dev.to/myndpm/a-new-approach-to-have-dynamic-forms-in-angular-5d11
Thanks in advance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants