1

Here is my issue: I am using ng-repeat to make a list of spans. Each span has the contenteditable attribute and ng-model directive. Everything works as expected (including two-way data binding), until I try to add a new item to the list.

<div ng-repeat="item in list">
    <span ng-model="item.text" contenteditable></span>
</div>
<button ng-click="addItemToList"></button>

The methods look like this:

$scope.addItemToList = function () {
    $scope.list.push({text: 'dummy text'});
}

or

$scope.addItemToList = function () {
    $scope.list.splice(1, 0, {text: 'dummy text'});
}

When adding the new item to the list (push or splice), the DOM updates, but the last item is initialised empty, with no text whatsoever. The last item in the model list also empties out, even if I specifically push an element with text in it.

After a few tests, I've noticed that this only happens if the list's length is bigger after modifying it: if I try to replace/modify/remove (not add) an element in the list, it works well. I believe this has to do with the way contenteditable elements initialise in the DOM (I think they initialise empty, and somehow, the model empties out as well).

Has anyone encountered this problem before? If yes, how did you solve it / what workaround have you found?

Marius
  • 69
  • 2
  • 10
  • I was unable to reproduce the problem with angular 1.5. check this out http://plnkr.co/edit/awim00mOk7M28uAGCnMo?p=preview you will find some fixes to your functions. It is hard to tell what the problem is with out the relevant parts from the controller. Please let me know if this helps. – It-Z Mar 30 '16 at 17:34
  • He was asking about when using ng-model with a contenteditable span, not putting a binding inside of a contenteditable span. I believe I have reproduced it here: https://plnkr.co/edit/v3elswolP9AgWHDIPwCk – CShark Mar 30 '16 at 17:44
  • @CShark Yes, this is my issue, and your plunker is similar to my code, the only difference being that when the list initialises on page refresh (list not empty), the `span`s actually have the list's text in them. Only when adding a new item, the new `span` appears empty (always the last one). I can't reproduce it in Plunker or JSFiddle – Marius Mar 31 '16 at 07:45

2 Answers2

1

Based on the angular docs related to ngModelController, it seems that there is not built-in support for two-way data binding with contenteditable elements, seeing as in the plunkr example they wrote their own contenteditable directive. You might be able to use a modified version of that as a workaround.

It looks to be a similar problem as this question and the contenteditable directive there looks similar to the contenteditable directive in the angular docs example.

I also found this directive on github that might accomplish what you are trying to do.


Edit: I did a new version of the plunk I posted in the comment above: https://plnkr.co/edit/v3elswolP9AgWHDIPwCk

In this version I added a contenteditable directive that appears to be working correctly. It is basically a spin off of how the input[type=text] directive is written in angular, but I took out the places where it handles different types of input (since in this case it will just be text) and the places where it handles events that contenteditable elements don't even fire. I also changed it so that the $viewValue gets updated based on element.html() instead of element.val(). You might be able to use something like this as a workaround

Community
  • 1
  • 1
CShark
  • 1,562
  • 1
  • 16
  • 27
  • I have also looked on this question, and tried all the custom contenteditable directives I could find (even tried modifying them according to other responses), but nothing seems to work. The last span always initialises empty. I have come up with a kind of hackish-noobish workaround, but it doesn't solve my problem completely (I'm sure more issues will appear in the future because of this) – Marius Mar 31 '16 at 08:03
  • I updated my answer to provide a workaround based on how angular currently handles ng-model on its input elements. – CShark Mar 31 '16 at 21:30
  • @MariusVlas Forgot to tag you, but I updated my answer. – CShark Apr 02 '16 at 14:55
0

The issue is old but that was the same problem for me today. (angular 1.5). My workaround was to add on blur update option: <td contenteditable data-ng-model="position.value" ng-model-options="{updateOn: 'blur'}"></td> somehow then model stopped getting be empty on initialize. I like using update on blur in many places (solves some performaces issues) so this is good for me, however it's some kind of trick.

Pawel
  • 13
  • 3