Skip to content Skip to sidebar Skip to footer

Angular 2 Contenteditable

In Angular 2 how can I make two way data binding with a contenteditable div?

Text Field

Solution 1:

I've adapted Isetty's answer to work with the release version of Angular 2.0, now it is available. Apart from working with the release version, I've also added a keyup event and used textContent rather than innerText, because that suites my application better. You may wish to change these things.

import {Directive, ElementRef, Input, Output, EventEmitter, OnChanges} from "@angular/core";

@Directive({
    selector: '[contenteditableModel]',
    host: {
        '(blur)': 'onEdit()',
        '(keyup)': 'onEdit()'
    }
})

export class ContentEditableDirective implements OnChanges {
    @Input('contenteditableModel') model: any;
    @Output('contenteditableModelChange') update = new EventEmitter();

    constructor(
        private elementRef: ElementRef
    ) {
        console.log('ContentEditableDirective.constructor');
    }

    ngOnChanges(changes) {
        console.log('ContentEditableDirective.ngOnChanges');
        console.log(changes);
        if (changes.model.isFirstChange())
            this.refreshView();
    }

    onEdit() {
        console.log('ContentEditableDirective.onEdit');
        var value = this.elementRef.nativeElement.innerText
        this.update.emit(value)
    }

    private refreshView() {
        console.log('ContentEditableDirective.refreshView');
        this.elementRef.nativeElement.textContent = this.model
    }
}

Solution 2:

Angular doesn't have a built-in ControlValueAccessor for contenteditable case. I've written a tiny little library that properly implements it for Angular 4 and above, and it also works with Internet Explorer 11 using MutationObserver fallback:

https://www.npmjs.com/package/@tinkoff/angular-contenteditable-accessor

Here's the code that ControlValueAccessor has to have:

registerOnChange(onChange: (value: string) => void) {
  ...
}

registerOnTouched(onTouched: () => void) {
  ...
}

setDisabledState(disabled: boolean) {
  ...
}

writeValue(value: string | null) {
  ...
}

Keep in mind that you should also watch out for dangerous pasted content so it would be wise to sanitize it in (drop)/(paste) events


Solution 3:

Please refer this code. It will work you i think.

app.ts

@Component({
    selector: 'test-component'
})
@View({
    directives: [ContenteditableModel]
    template: `
        <h1 contenteditable="true" [(contenteditableModel)]="someObj.someProperty"></h1>
        {{someObj | json}}
    `
})
export class TestCmp {
    someObj = {someProperty: "startValue"}
}

contenteditableModel.ts:

import {Directive, ElementRef, Input, Output} from "angular2/core";
import {EventEmitter} from "angular2/src/facade/async";
import {OnChanges} from "angular2/core";
import {isPropertyUpdated} from "angular2/src/common/forms/directives/shared";

@Directive({
    selector: '[contenteditableModel]',
    host: {
        '(blur)': 'onBlur()'
    }
})
export class ContenteditableModel implements OnChanges {
    @Input('contenteditableModel') model: any;
    @Output('contenteditableModelChange') update = new EventEmitter();

    private lastViewModel: any;


    constructor(private elRef: ElementRef) {
    }

    ngOnChanges(changes) {
        if (isPropertyUpdated(changes, this.lastViewModel)) {
            this.lastViewModel = this.model
            this.refreshView()
        }
    }

    onBlur() {
        var value = this.elRef.nativeElement.innerText
        this.lastViewModel = value
        this.update.emit(value)
    }

    private refreshView() {
        this.elRef.nativeElement.innerText = this.model
    }
}

For the extra inputs i found a link for you. https://www.namekdev.net/2016/01/two-way-binding-to-contenteditable-element-in-angular-2/


Solution 4:

in angular 2 [(ngModel)] used for two way data binding.

the answer of your question is already here How to use [(ngModel)] on div's contenteditable in angular2? check this out and let me know if it is working for you or not.


Solution 5:

To work properly, it is necessary to implement ControlValueAccessor for the directive contenteditable. See my solution: ng-contenteditable.


Post a Comment for "Angular 2 Contenteditable"