我有一个具有p
元素的组件。其onClick
事件会将其更改为textarea
,以便用户可以编辑数据。我的问题是:
我曾尝试使用“ElementRef”和“@ViewChild()”,但似乎我错过了一些东西:
// ------ THE CLASS
@ViewChild('tasknoteId') taskNoteRef:ElementRef;
noteEditMode: boolean = false;
get isShowNote (){
return !this.noteEditMode && this.todo.note ? true : false;
}
taskNote: string;
toggleNoteEditMode () {
this.noteEditMode = !this.noteEditMode;
this.renderer.invokeElementMethod(this.taskNoteRef.nativeElement,'focus');
}
// ------ THE COMPONENT
<span class="the-insert">
<form [hidden]="!noteEditMode && todo.note">
<textarea #tasknoteId id="tasknote"
name="tasknote"
[(ngModel)]="todo.note"
placeholder="{{ notePlaceholder }}"
style="background-color:pink"
(blur)="updateNote()" (click)="toggleNoteEditMode()"
[autofocus]="noteEditMode"
[innerHTML]="todo.note">
</textarea>
</form>
</span>
答案 0 :(得分:66)
更新(使用渲染器):
请注意,现在已弃用原始渲染器服务 Renderer2的青睐
此外,正如@GünterZöchbauer所指出的那样:
实际上使用ElementRef就好了。也用 使用Renderer2的ElementRef.nativeElement很好。什么是气馁 正在直接访问ElementRef.nativeElement.xxx的属性。
您可以使用elementRef
以及ViewChild
来实现此目的。但由于以下原因,不建议使用elementRef
正如official ng2 documentation所指出的那样。
elementRef
(直接访问):export class MyComponent {
constructor (private _elementRef : elementRef) {
this._elementRef.nativeElement.querySelector('textarea').focus();
}
}
ViewChild
(更好的方法):<textarea #tasknote name="tasknote" [(ngModel)]="taskNote" placeholder="{{ notePlaceholder }}"
style="background-color: pink" (blur)="updateNote() ; noteEditMode = false " (click)="noteEditMode = false"> {{ todo.note }} </textarea> // <-- changes id to local var
export class MyComponent implements AfterViewInit {
@ViewChild('tasknote') input: ElementRef;
ngAfterViewInit() {
this.input.nativeElement.focus();
}
}
renderer
:export class MyComponent implements AfterViewInit {
@ViewChild('tasknote') input: ElementRef;
constructor(private renderer: Renderer2){
}
ngAfterViewInit() {
//using selectRootElement instead of depreaced invokeElementMethod
this.renderer.selectRootElement(this.input["nativeElement"]).focus();
}
}
答案 1 :(得分:10)
Angular 2.0.0 Final:
我发现使用ViewChild
setter是设置初始表单控件焦点的最可靠方法:
@ViewChild("myInput")
set myInput(_input: ElementRef | undefined) {
if (_input !== undefined) {
setTimeout(() => {
this._renderer.invokeElementMethod(_input.nativeElement, "focus");
}, 0);
}
}
首先使用undefined
值调用setter,然后调用初始化ElementRef
。
工作示例和完整来源:http://plnkr.co/edit/u0sLLi?p=preview
使用TypeScript 2.0.3 Final / RTM,Angular 2.0.0 Final / RTM和Chrome 53.0.2785.116 m(64位)。
Angular 4 +的更新
Renderer
已弃用,仅支持Renderer2
,Renderer2
does not have invokeElementMethod
。您需要直接访问DOM以将焦点设置为input.nativeElement.focus()
。
我仍然发现 ViewChild setter 方法效果最佳。使用AfterViewInit
时,我有时会遇到read property 'nativeElement' of undefined
错误。
@ViewChild("myInput")
set myInput(_input: ElementRef | undefined) {
if (_input !== undefined) {
setTimeout(() => { //This setTimeout call may not be necessary anymore.
_input.nativeElement.focus();
}, 0);
}
}