Exchange Data between multi step forms in Angular2: What is the proven way?

前端 未结 2 1203
情书的邮戳
情书的邮戳 2020-12-23 15:46

I can imagine following approaches to exchange Data between multi step forms:

1) Create a component for each form step and exchange data between components over @inp

相关标签:
2条回答
  • 2020-12-23 15:56

    Why not use session storage? For instance you can use this static helper class (TypeScript):

    export class Session {
    
      static set(key:string, value:any) {
          window.sessionStorage.setItem(key, JSON.stringify(value));
      }
    
      static get(key:string) {
          if(Session.has(key)) return JSON.parse(window.sessionStorage[key])
          return null;
      }
    
      static has(key:string) {
          if(window.sessionStorage[key]) return true;
          return false;
      }
    
      static remove(key:string) {
          Session.set(key,JSON.stringify(null)); // this line is only for IE11 (problems with sessionStorage.removeItem)
          window.sessionStorage.removeItem(key);
      }
    
    }
    

    And using above class, you can put your object with multi-steps-forms data and share it (idea is similar like for 'session helper' in many backend frameworks like e.g. php laravel).


    The other approach is to create Singleton service. It can look like that (in very simple from for sake of clarity) (I not test below code, I do it from head):

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class SessionService {
    
        _session = {};
    
        set(key:string, value:any) {
             this._session[key]= value; // You can also json-ize 'value' here
        }
    
        get(key:string) {
             return this._session[key]; // optionally de-json-ize here
         }
    
         has(key:string) {
             if(this.get(key)) return true;
             return false;
         }
    
         remove(key:string) {         
             this._session[key]=null;
         }
    }
    

    And then in your main file where you bootstrap application:

    ...
    return bootstrap(App, [
      ...
      SessionService
    ])
    ...
    

    And the last step - critical: When you want to use you singleton service in your component - don't put int in providers section (this is due to angular2 DI behavior - read above link about singleton services). Example below for go from form step 2 to step 3:

    import {Component} from '@angular/core';
    import {SessionService} from './sessionService.service';
    ...
    
    @Component({
      selector: 'my-form-step-2',
      // NO 'providers: [ SessionService ]' due to Angular DI behavior for singletons
      template: require('./my-form-step-2.html'),
    })
    
    export class MyFormStep2  {
    
      _formData = null;
    
      constructor(private _SessionService: SessionService) {
         this._formData = this._SessionService.get('my-form-data')
      }
    
      ...
      submit() {
         this._SessionService.set('my-form-data', this._formData)
      }
    
    }
    

    It should looks like that.

    0 讨论(0)
  • 2020-12-23 16:02

    See my edit below.


    Using SessionStorage is not strictly the 'angular' way to approach this in my opinion—a shared service is the way to go. Implementing routing between steps would be even better (as each component can have its own form and different logic as you see fit:

    const multistepRoutes: Routes = [
      {
        path: 'multistep',
        component: MultistepComponent,
        children: [
          {
            path: '',
            component: MultistepBaseComponent,
          },
          {
            path: 'step1',
            component: MultistepStep1Component
          },
          {
            path: 'step2',
            component: MultistepStep2Component
          }
        ]
      }
    ];
    

    The service multistep.service can hold the model and implement logic for components:

    import { Injectable, Inject } from '@angular/core';
    import { Router } from '@angular/router';
    
    @Injectable()
    export class MultistepService { 
    
      public model = {};
      public baseRoute = '/multistep';
      public steps = [
    
        'step1', 
        'step2'
    
      ];
    
      constructor (
        @Inject(Router) public router: Router) { };
    
      public getInitialStep() {
    
        this.router.navigate([this.baseRoute + '/' + this.steps[0]]);
    
      };
    
      public goToNextStep (direction /* pass 'forward' or 'backward' to service from view */): any {
    
        let stepIndex = this.steps.indexOf(this.router.url.split('/')[2]);
    
        if (stepIndex === -1 || stepIndex === this.steps.length) return;
    
        this.router.navigate([this.baseRoute + '/' + this.steps[stepIndex + (direction === 'forward' ? 1 : -1)]]);
    
      };
    
    }; 
    

    Good luck.


    EDIT 12/6/2016


    Actually, now having worked with the form API for a while I don't believe my previous answer is the best way to achieve this.

    A preferrable approach is to create a top level FormGroup which has each step in your multistep form as it's own FormControl (either a FormGroup or a FormArray) under it's controls property. The top level form in such a case would be the single-source of truth for the form's state, and each step on creation (ngOnInit / constructor) would be able to read data for its respective step from the top level FormGroup. See the pseudocode:

       const topLevelFormGroup = new FormGroup({
           step1: new FormGroup({fieldForStepOne: new FormControl('')}),
           step2: new FormGroup({fieldForStepTwo}),
           // ...
       });
    
       ... 
    
       // Step1Component
    
       class Step1Component { 
           private stepName: string = 'step1';
           private formGroup: FormGroup;
           constructor(private topLevelFormGroup: any /* DI */) {
               this.formGroup = topLevelFormGroup.controls[this.stepName];
           }
        }
    

    Therefore, the state of the form and each step is kept exactly where it should be—in the form itself!

    0 讨论(0)
提交回复
热议问题