2016-11-12 57 views
3

在我的Angular 2应用程序,我想有一个输入列表。按下其中一个里面的Enter将添加一个新的输入,并立即关注它。这是本网站上已询问的问题,Eric Martinez provided a neat answer to it that accomplishes that with a custom directiveAngular 2:焦点输入原因'表达已改变后,它被改变'错误

他的解决方案基于一个虚拟的整数列表。我在尝试将其适应更现实的场景方面遇到困难。我已付出Eric的普拉克,这样你就可以run the code here,但最重要的文件是这一个:

//our root app component 
import {Component, Directive, Renderer, ElementRef} from 'angular2/core' 

class Person { name: string } 

@Directive({ 
    selector : 'input' 
}) 
class MyInput { 
    constructor(public renderer: Renderer, public elementRef: ElementRef) {} 

    // It won't work at construction time 
    ngOnInit() { 
    this.renderer.invokeElementMethod(
     this.elementRef.nativeElement, 'focus', []); 
    } 
} 

@Component({ 
    selector: 'my-app', 
    providers: [], 
    template: ` 
    <div *ngFor="#input of inputs"> 
     <input 
     (keydown.enter)="add()" 
     [(ngModel)]="input.name" 
     type="text"/> 
    </div> 
    `, 
    directives: [MyInput] 
}) 
export class App { 
    inputs: Person[] = [{name: 'Alice'}]; 

    add() { 
    var newPerson = new Person(); 
    newPerson.name = 'Bob'; 

    this.inputs.push(newPerson); 
    } 
} 

我的inputs阵列现在是Person对象的列表。输入双向绑定到Personname属性。 <input>现在被包装在一个<div>内,因为我预计稍后我会写更多标记来显示每个Person

做出这些更改后,该示例仅在第一次尝试按Enter时起作用 - 带文本的新输入Bob按预期显示。但是,当我再尝试按Enter键第二次,我得到一个错误:

angular2.dev.js:23730 Error: Expression 'ngClassUntouched in [email protected]:6' has changed after it was checked. Previous value: 'true'. Current value: 'false' 
    at ExpressionChangedAfterItHasBeenCheckedException.BaseException [as constructor] (angular2.dev.js:7587) 
    at new ExpressionChangedAfterItHasBeenCheckedException (angular2.dev.js:4992) 
    at ChangeDetector_App_1.AbstractChangeDetector.throwOnChangeError (angular2.dev.js:9989) 
    at ChangeDetector_App_1.detectChangesInRecordsInternal (viewFactory_App:143) 
    at ChangeDetector_App_1.AbstractChangeDetector.detectChangesInRecords (angular2.dev.js:9874) 
    at ChangeDetector_App_1.AbstractChangeDetector.runDetectChanges (angular2.dev.js:9857) 
    at ChangeDetector_App_0.AbstractChangeDetector._detectChangesContentChildren (angular2.dev.js:9930) 
    at ChangeDetector_App_0.AbstractChangeDetector.runDetectChanges (angular2.dev.js:9858) 
    at ChangeDetector_HostApp_0.AbstractChangeDetector._detectChangesInViewChildren (angular2.dev.js:9936) 
    at ChangeDetector_HostApp_0.AbstractChangeDetector.runDetectChanges (angular2.dev.js:9861) 

我该如何解决呢?

我在Chrome中运行示例。我发现使用基于Angular2的Beta 12版本的Eric Martinez的解压缩来解决问题是最容易的,但是现实世界的应用程序中,我现在使用的是Angular 2.0.0。

回答

3

Angular2不喜欢在更改检测回调期间更改模型(如ngOnInit()是)。调用ChangeDetectorRef.detectChanges()应该修复它:

class MyInput { 
    constructor(public renderer: Renderer, public elementRef: ElementRef 
     ,private cdRef:ChangeDetectorRef) {} 

    // It won't work at construction time 
    ngOnInit() { 
    this.renderer.invokeElementMethod(
     this.elementRef.nativeElement, 'focus', []); 
    this.cdRef.detectChanges(); 
    } 
} 
+0

在Plunker这样做会导致铬因内存不足错误的崩溃,因为某种原因。在我的真实应用程序中,即使底层数组仍然附加到后面,也会阻止出现任何新的“”。我也不太清楚我改变模型的方式。 – kamilk

+1

不管怎么样,你都不应该试着把注意力集中在'ngOnInit()上,因为这里的元素还不存在。使用'ngAfterViewInit()'或'ngAfterViewChecked()'。 –

+0

我尝试了两个事件,我尝试将它们与'.detectChanges()'结合使用,仍然是同样的问题... https://plnkr.co/edit/Hh3H36fceFSm0Q20PVV3?p=preview – kamilk