我可以想象以下在多步骤表单之间交换数据的方法:
1)为每个表单步骤创建一个组件,并通过@input,@output在组件之间交换数据(例如,您不能从step5更改为2)
data
2)在新路由器中使用新属性(见这里)(例如,你不能从第5步更改为第2步))
3)一个共享服务(依赖注入)来存储数据(组件交互)(例如,你可以从第5步更改为第2步)
4) @ngrx/store 的新基础(还没有真正体验过)
您能否给出一些“获得的经验值”,您使用什么以及为什么?
请参阅下面的我的编辑。
在我看来,严格来说,使用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
将多步表单中的每个步骤作为它自己的FormControl
(一个FormGroup或一个 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];
}
}
因此,表单的状态和每一步都准确地保存在它应该在的位置——在表单本身中!
为什么不使用会话存储?例如,您可以使用这个静态辅助类(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)。
另一种方法是创建单例服务。它看起来像这样(为了清楚起见,非常简单)(我没有测试下面的代码,我是从头开始做的):
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;
}
}
然后在引导应用程序的主文件中:
...
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)
}
}
它应该看起来像这样。