Angular 2 - large scale application forms' handling

前端 未结 4 1557
青春惊慌失措
青春惊慌失措 2020-11-28 10:07

At the company I’m working for, we’re developing a large scale application with multiple forms, that the user needs to fill in in order to register for our program. When all

4条回答
  •  没有蜡笔的小新
    2020-11-28 10:34

    I commented elsewhere about @ngrx/store, and while I still recommend it, I believe I was misunderstanding your problem slightly.

    Anyway, your FormsControlService is basically a global const. Seriously, replace the export class FormControlService ... with

    export const formControlsDefinitions = {
       // ...
    };
    

    and what difference does it make? Instead of getting a service, you just import the object. And since we're now thinking of it as a typed const global, we can define the interfaces we use...

    export interface ModelControl {
        name: string;
        validators: ValidatorFn[];
    }
    
    export interface ModelGroup {
       name: string;
       // Any subgroups of the group
       groups?: ModelGroup[];
       // Any form controls of the group
       controls?: ModelControl[];
    }
    

    and since we've done that, we can move the definitions of the individual form groups out of the single monolithic module and define the form group where we define the model. Much cleaner.

    // personal_details.ts
    
    export interface PersonalDetails {
      ...
    }
    
    export const personalDetailsFormGroup: ModelGroup = {
       name: 'personalDetails$';
       groups: [...]
    }
    

    But now we have all these individual form group definitions scattered throughout our modules and no way to collect them all :( We need some way to know all the form groups in our application.

    But we don't know how many modules we'll have in future, and we might want to lazy load them, so their model groups might not be registered at application start.

    Inversion of control to the rescue! Let's make a service, with a single injected dependency -- a multi-provider which can be injected with all our scattered form groups when we distribute them throughout our modules.

    export const MODEL_GROUP = new OpaqueToken('my_model_group');
    
    /**
     * All the form controls for the application
     */
    export class FormControlService {
        constructor(
            @Inject(MMODEL_GROUP) rootControls: ModelGroup[]
        ) {}
    
        getControl(name: string): AbstractControl { /etc. }
    }
    

    then create a manifest module somewhere (which is injected into the "core" app module), building your FormService

    @NgModule({
       providers : [
         {provide: MODEL_GROUP, useValue: personalDetailsFormGroup, multi: true}
         // and all your other form groups
         // finally inject our service, which knows about all the form controls
         // our app will ever use.
         FormControlService
       ]
    })
    export class CoreFormControlsModule {}
    

    We've now got a solution which is:

    • more local, the form controls are declared alongside the models
    • more scalable, just need to add a form control and then add it to the manifest module; and
    • less monolithic, no "god" config classes.

提交回复
热议问题