Two-way binding to contenteditable element in Angular 2

contenteditable is a new HTML5 feature where you can edit any text inside DOM elements which are not editable by default (as input or textearea). Angular 2 is gaining it’s momentum right now but couldn’t find a recipe to bind contenteditable element to certain model object. I decided to write a simple Directive that binds element in two-way through element’s  innerText  field.

Simple approach

Normally, you can add  contenteditable  property to your element and listen for blur event which will call some update.

But it’s not two-way binding. {{text}}  binds from model to element, and statement set for blur event updates the other way.

There’s also a little drawback hidden in there. Let’s take a look again:

Having to make multiple references (like  #el1 , #el2 ) is not cool – more code and easier to make a mistake.

Let’s find a way to make it a little less reference-polluting and really two-way binded.

new Directive: contenteditableModel

TL; DR but let’s look what’s in there.

Here’s the usage – we turn the  contenteditable  property on and bind it to text  model:

element -> model

There are two key things to update (our binded) model when contenteditable element changes:

1. blur  event – triggers when you focus away from your element

Of course, you could add  keyup event to update more often. Depends on your needs.

2. name of event that triggers update of model

Here’s our update event:

Actually, update  (triggered in onBlur) could be updateModel , doYourStuff  or whatever else. What you need is a proper value for the @Output  directive – it’s a directive name (same as in directive selector) plus “Change” suffix. So here’s contenteditableModelChange . The suffix is what makes a difference.

model -> element

Directive has to implement OnChanges  interface.

innerText vs innerHTML vs textContent

Personally I needed innerText  but if you need single line text and better performance you may want to use textContent . To read more about differences read on “innerText vs textContent”.

Whole code

Whole code can be found here or here:


[1] plunker for contenteditableModel
[2] Directive in Angular2
[3] “innerText vs textContent”