2016-12-03 72 views
2

我有一个select元素在我的模板如下:角2更新选择在单位更改模型试验

<select [(ngModel)]="snapshotCriteria.salesArea" required> 
    <option *ngFor="let salesArea of salesAreas" [ngValue]="salesArea"> 
    {{salesArea.name}} 
    </option> 
</select> 

你可以看到,该模型必然会snapshotCriteria.salesArea这是一个对象,所以我们使用ngValue代替value。属性本身也是一个对象。


的成分如下:

export class Component implements OnInit { 

    salesAreas: SalesArea[]; 

    snapshotCriteria: SnapshotCriteria = { 
    salesArea: null, 
    date: null, 
    startTime: 600, 
    endTime: 3059 
    }; 


    constructor(private salesAreaService: SalesAreaService) {} 


    ngOnInit(): void { 
    this.salesAreaService.fetchSalesAreas(salesAreas) => this.salesAreas = salesAreas); 
    } 

} 

注意,其被绑定到模型selectsalesArea初始化为null


当通过操作下拉菜单通过模板进行更改时,模板正常运行。但是在我的单元测试中,我直接更新了select元素引用的模型,并且与我期望的相反,视图没有更新!由于该字段是必需的,因为验证失败,我的测试无法提交表单。这是测试:

it('...', fakeAsync(() => { 

    spyOn(salesAreaService, 'fetchSalesAreas').and.returnValue(Observable.of([ 
    {areaNumber: 1, name: 'A'} as any as SalesArea, 
    {areaNumber: 2, name: 'B'} as any as SalesArea, 
    {areaNumber: 3, name: 'C'} as any as SalesArea 
    ])); 

    fixture.detectChanges(); 
    tick(); 

    component.snapshotCriteria = { 
    salesArea: {areaNumber: 1, name: 'A'} as SalesArea, 
    date: new Date(2015, 5, 25), 
    startTime: 1000, 
    endTime: 1001 
    } as SnapshotCriteria; 

    fixture.detectChanges(); 
    tick(); 

})); 

调试显示select元素未更新。我尝试了各种各样的东西无济于事:

  1. 不在测试中重新实例化对象。
  2. 实例化salesArea对象为空对象而不是 null
  3. 调度inputchange事件在测试中。
  4. 在视图中聆听ngModelChange,但在测试中未触发 。

记下感兴趣的是,通过使用模板中valuengValue,我能够通过改变底层模型更新视图。

+0

此行为是相似,我测试了'select'元素的指令时经历。我不得不做多个'detectChanges'和'whenStable'(我没有使用'fakeAsync')调用。尝试再次调用'fixture.detectChanges();蜱();'。 (我为此提出了一个[问题](https://github.com/angular/angular/issues/11895),但回想起来,我的repro不是基于测试的,而是专注于其他一些奇怪的行为,我可能会提出另一个更关注测试的问题) – cartant

+0

@cartant在测试过程中,fixture一直保持稳定,给tick()添加更多调用没有任何作用。 – Cristian

+0

这是重要的多重'detectChanges'调用。这就是为我解决的。但是,因为我没有使用'fakeAsync',所以我和'whenStable'调用进行了配对。 – cartant

回答

2

我认为你需要做的,如下所示:

it('...', fakeAsync(() => { 
    var mockArr = [ 
    {areaNumber: 1, name: 'A'} as any as SalesArea, 
    {areaNumber: 2, name: 'B'} as any as SalesArea, 
    {areaNumber: 3, name: 'C'} as any as SalesArea 
    ]; 
    spyOn(salesAreaService, 'fetchSalesAreas').and.returnValue(Observable.of(mockArr)); 

    fixture.detectChanges(); 
    tick(); 

    component.snapshotCriteria = { 
    salesArea: mockArr.find(x => x.areaNumber === 1), 
    date: new Date(2015, 5, 25), 
    startTime: 1000, 
    endTime: 1001 
    } as SnapshotCriteria; 

    fixture.detectChanges(); 

    tick(); 
    expect(...); 
})); 

Plunker Example

+1

100%正确,谢谢!看起来'component.snapshotCriteria.salesArea'的值需要是一个引用传递给'option'元素'ngFor'的'salesAreas'的对象。 – Cristian