Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular custom control contenteditable, how do I hook up ngModel?

Tags:

angular

<button (click)="onSaveChanges()">Save Changes</button>
<section>
  <news-column *ngFor="let column of news.columns">
    <news-header>
      <h2 contenteditable="true" spellcheck="true">
        {{ column.header }}
      </h2>
    </news-header>
    <news-content contenteditable="true" spellcheck="true">
      {{ column.content }}
    </news-content>
    <news-read-more contenteditable="true">
      {{ column.readmore.text }}
    </news-read-more>
    <news-photo contenteditable="true">{{ column.photo.url }} </news-photo>
  </news-column>
</section>

I'm allowing users to edit content using contenteditable. Problem is that the data is bound to news.columns as shown above. When user makes changes I can see them via this construct:

     ele.addEventListener("input", event => {
          let change = event.target as HTMLElement;
          console.log(change.innerText);
        });

But when looking at the news.column binding, the changes are not there. The traditional approach is to add [ngModel] etc. But ngModels only apply to input elements. Not any contenteditable element. I'd prefer the changes to happen in the binding, but as mentioned I can see the changes at the DOM layer.

Any suggestions on getting the bindind content to relfect the change e.g. each news.column should have the edited content.

like image 455
JWP Avatar asked Dec 06 '25 20:12

JWP


1 Answers

I suspect you need to do more implementation. contenteditable isn't an angular thing, it's an HTML attribute that specifies that the element is editable. I could be wrong but I don't think that has anything to do with angular's binding. I searched Angular.io and "contenteditable" comes up with zero hits in docs.

Fortunately there seem to be some examples of how to create a directive for this, and it seems many modules (angular-mentions) wrap that up for you.

Here's two examples I semi-randomly picked from searching for "contenteditable angular" on GitHub:

https://github.com/KostyaTretyak/ng-stack/tree/master/projects/contenteditable

https://github.com/TinkoffCreditSystems/angular-contenteditable-accessor

If you look up some code, you find the same thing: create a directive that manages the content updates, e.g:

/*
 * This is a barebones contenteditable {@link ControlValueAccessor} allowing you to use
 * Angular forms with native contenteditable HTML. For security reasons you might want
 * to consider sanitizing pasted/dropped content before using it. Also make sure that
 * you do not set any dangerous content as control value yourself, because directive
 * just outputs control value as-is.
 */
@Directive({
    selector:
        '[contenteditable][formControlName], [contenteditable][formControl], [contenteditable][ngModel]',
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => ContenteditableValueAccessor),
            multi: true,
        },
    ],
})
etc. etc.
like image 117
Tim Consolazio Avatar answered Dec 08 '25 12:12

Tim Consolazio