Estoy tratando de usar ngModel para vincular de dos maneras el contenido de entrada editable de div de la siguiente manera:
<div id="replyiput" class="btn-input" [(ngModel)]="replyContent" contenteditable="true" data-text="type..." style="outline: none;" ></div>pero no funciona y se produce un error:
EXCEPTION: No value accessor for '' in [ddd in PostContent@64:141] app.bundle.js:33898 ORIGINAL EXCEPTION: No value accessor for ''NgModel espera que el elemento enlazado tenga una propiedad de value , que los div no tienen. Es por eso que obtiene el error de No value accessor .
Puede configurar su propia propiedad equivalente y enlace de datos de eventos utilizando la propiedad textContent (en lugar de value ) y el evento de input :
import {Component} from 'angular2/core'; @Component({ selector: 'my-app', template: `{{title}} <div contenteditable="true" [textContent]="model" (input)="model=$event.target.textContent"></div> <p>{{model}}` }) export class AppComponent { title = 'Angular 2 RC.4'; model = 'some text'; constructor() { console.clear(); } } No sé si el evento de input es compatible con todos los navegadores para contenteditable . En su lugar, siempre puede enlazar con algún evento de teclado.
Respuesta actualizada (2017-10-09) :
Ahora tengo el módulo ng-contenteditable . Su compatibilidad con las formas Angular.
Respuesta anterior (2017-05-11) : en mi caso, puedo hacerlo fácilmente:
<div contenteditable="true" (input)="post.postTitle = $event.target.innerText" >{{ postTitle }}</div> Donde post - es un objeto con propiedad postTitle .
La primera vez, después de ngOnInit() y obtener una post desde el backend, configuré this.postTitle = post.postTitle en mi componente.
Trabajando Plunkr aquí http://plnkr.co/edit/j9fDFc , pero el código relevante a continuación.
La vinculación y actualización manual de textContent no funcionaba para mí, no maneja los saltos de línea (en Chrome, escribir después de un salto de línea hace que el cursor vuelva al principio) pero pude hacerlo funcionar usando una directiva de modelo editable de https://www.namekdev.net/2016/01/two-way-binding-to-contenteditable-element-in-angular-2/ .
Lo ajusté para manejar texto sin formato de varias líneas (con \n s, no <br> s) usando white-space: pre-wrap , y lo actualicé para usar keyup en lugar de blur . Tenga en cuenta que algunas soluciones a este problema usan el evento de input que aún no es compatible con IE o Edge en elementos contenteditable .
Aquí está el código:
Directiva:
import {Directive, ElementRef, Input, Output, EventEmitter, SimpleChanges} from 'angular2/core'; @Directive({ selector: '[contenteditableModel]', host: { '(keyup)': 'onKeyup()' } }) export class ContenteditableModel { @Input('contenteditableModel') model: string; @Output('contenteditableModelChange') update = new EventEmitter(); /** * By updating this property on keyup, and checking against it during * ngOnChanges, we can rule out change events fired by our own onKeyup. * Ideally we would not have to check against the whole string on every * change, could possibly store a flag during onKeyup and test against that * flag in ngOnChanges, but implementation details of Angular change detection * cycle might make this not work in some edge cases? */ private lastViewModel: string; constructor(private elRef: ElementRef) { } ngOnChanges(changes: SimpleChanges) { if (changes['model'] && changes['model'].currentValue !== this.lastViewModel) { this.lastViewModel = this.model; this.refreshView(); } } /** This should probably be debounced. */ onKeyup() { var value = this.elRef.nativeElement.innerText; this.lastViewModel = value; this.update.emit(value); } private refreshView() { this.elRef.nativeElement.innerText = this.model } }Uso:
import {Component} from 'angular2/core' import {ContenteditableModel} from './contenteditable-model' @Component({ selector: 'my-app', providers: [], directives: [ContenteditableModel], styles: [ `div { white-space: pre-wrap; /* just for looks: */ border: 1px solid coral; width: 200px; min-height: 100px; margin-bottom: 20px; }` ], template: ` <b>contenteditable:</b> <div contenteditable="true" [(contenteditableModel)]="text"></div> <b>Output:</b> <div>{{text}}</div> <b>Input:</b><br> <button (click)="text='Success!'">Set model to "Success!"</button> ` }) export class App { text: string; constructor() { this.text = "This works\nwith multiple\n\nlines" } }Solo probado en Chrome y FF en Linux hasta ahora.