formsangularroutermulti-stepdata-exchange

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


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 @input, @output (e.g. you cannot change from step5 to 2)

2) Use the new property data in the new router (see here) (e.g. you cannot change from step5 to 2))

3) A shared Service (Dependency Injection) to store data (Component Interaction) (e.g. you can change from step5 to 2)

4) New rudiments with @ngrx/store (not really experienced yet)

Can you give some "gained experience values", what do you use and why?


Solution

  • 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.