I have the following code:
Template:
<button *ngFor="name of students"
(click)="modifyText($event.currentTarget)">{{name}}</button>
TypeScript
this.students = ["Carl", "Rob", "Joy];
public modifyText(htmlElement: HTMLElement) {
this.dataset.edit = !this.dataset.edit;
htmlElement.contentEditable = this.dataset.edit;
htmlElement.focus();
}
The problem is, as soon as I modify the content with content-editable, I seem to lose the binding to {{name}}, as if I have a separate button on the page:
<button (click)="students[0] = 'Amy'">Manual Set Name</button>
The students array changes, but when I look at the text of the button, it is what I had "edited" in contenteditable, and does not show Amy at all.
I suggest you to use ngModel and pure Angular two ways data binding in an embedded component :
import {Component, Input, Output, EventEmitter} from '@angular/core';
@Component({
selector: 'editable-button',
template: `
<button *ngIf="!editable" (click)="editable = true">{{title}}</button>
<input *ngIf="editable" (blur)="editTitle()" [(ngModel)]="title">
`,
})
export class EditableButtonComponent {
@Input() title: string;
@Output() titleChange = new EventEmitter<string>();
editable= false;
editTitle() {
this.editable = false;
this.titleChange.emit(this.title);
}
}
And then your template will look like the following :
<editable-button *ngFor="let name of students; let index=index" [(title)]="students[index]"></editable-button>
Note I'm using the index of the element in place of it's reference. Here you could see an explaination : https://github.com/angular/angular/issues/10423
Working stylized Plunker example here : https://plnkr.co/edit/eia5PYp3Z5F6WRcWpMeA?p=preview
I am not sure where is your error is. Here is my simple way to write this component.
https://plnkr.co/edit/DpOzFIEeRZ05n64mWnvL
@Component({
selector: 'my-app',
template: `
<div>
here is value = {{value}}
<button [attr.contenteditable]="contenteditable" #el
(click)="open(el)"
(blur)="close(el)"
(keyup.enter)="close(el)">{{value}}</button>
</div>
`,
})
export class App {
value ="aaa";
contenteditable = false;
constructor() {
}
open(el) {
this.contenteditable = true;
setTimeout(()=>el.focus());
}
close(el) {
this.contenteditable = false;
this.value = el.innerText;
}
}