web-dev-qa-db-ja.com

Angular2のマルチステップフォーム間でのデータ交換:実証済みの方法は何ですか?

マルチステップフォーム間でデータを交換するための次のアプローチを想像できます。

1)フォームステップごとにコンポーネントを作成し、@ input、@ outputを介してコンポーネント間でデータを交換します(たとえば、ステップ5から2に変更することはできません)

2)新しいルーターで新しいプロパティdataを使用します( ここを参照 )(たとえば、ステップ5から2に変更することはできません))

3)データを格納する共有サービス( 依存性注入 )( コンポーネントの相互作用 )(例:ステップ5から2に変更できます)

4)@ ngrx/storeの新しい基本(まだ実際には経験していません)

「得られた経験値」をいくつか挙げていただけますか。何を使用し、その理由を教えてください。

13
user2227400

セッションストレージを使用してみませんか?たとえば、次の静的ヘルパークラス(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);
  }

}

上記のクラスを使用すると、オブジェクトにマルチステップフォームデータを配置して共有できます(アイデアは、php laravelなどの多くのバックエンドフレームワークの「セッションヘルパー」と同様です)。


もう1つのアプローチは、 シングルトンサービス を作成することです。それはそのように見えるかもしれません(明確にするために非常に単純に)(私は以下のコードをテストせず、頭からテストします):

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;
     }
}

そして、メインファイルでbootstrap application:

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

そして最後のステップ-重要:コンポーネントでシングルトンサービスを使用したい場合-プロバイダーセクションにintを入れないでください(これはangular2 DIの動作によるものです-シングルトンサービスに関する上記のリンクを読んでください)。以下の例は、フォームのステップ2からステップ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)
  }

}

そのように見えるはずです。

8

以下の私の編集を参照してください。


私の意見では、SessionStorageを使用することは、厳密にはこれにアプローチするための「角度のある」方法ではありません。共有サービスがその方法です。ステップ間のルーティングを実装することはさらに良いでしょう(各コンポーネントはあなたが適切と思うように独自のフォームと異なるロジックを持つことができるので:

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

サービス_multistep.service_は、モデルを保持し、コンポーネントのロジックを実装できます。

_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)]]);

  };

}; 
_

幸運を。


2016年12月6日編集


実際、しばらくの間フォームAPIを使用してきたので、以前の回答がこれを達成するための最良の方法であるとは思いません。

望ましいアプローチは、FormGroupプロパティの下に独自のFormControlFormGroup または FormArray )として、マルチステップフォームの各ステップを持つトップレベルのcontrolsを作成することです。このような場合の最上位のフォームは、フォームの状態の信頼できる唯一の情報源であり、作成の各ステップ(ngOnInit /コンストラクター)は、最上位のFormGroupからそれぞれのステップのデータを読み取ることができます。擬似コードを参照してください。

_   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];
       }
    }
_

したがって、フォームと各ステップの状態は、フォーム自体の本来あるべき場所に正確に保持されます。

15
nikk wong