2015-02-18 4 views
11

Ich versuche, den Wert einer contenteditable zu meinem JS-Code zu speichern. Aber ich kann nicht herausfinden, warum ng-model in diesem Fall nicht funktioniert.zufrieden stellbar mit ng-Modell funktioniert nicht

<div ng-app="Demo" ng-controller="main"> 
    <input ng-model="inputValue"></input> 
    <div>{{inputValue}}</div> // Works fine with an input 
    <hr/> 
    <div contenteditable="true" ng-model="contentValue"></div> 
    <div>{{contentValue}}</div> // Doesn't work with a contenteditable 
</div> 

Gibt es einen Workaround dafür?

See: JSFiddle

Hinweis: ich einen Text-Editor erstellen, so dass der Benutzer sollte das Ergebnis sehen, während ich die HTML dahinter bin zu speichern. (. Dh Benutzer sehen: „Dies ist ein Beispiel!“, Während ich speichere: This is an <b>example</b> !)

Antwort

26

contenteditable Tag wird nicht direkt arbeitet mit Winkeln des ng-Modell, weil die Art und Weise contenteditable rerender das DOM-Element bei jeder Änderung.

Sie haben es mit einer benutzerdefinierten Richtlinie wickeln dafür:

JS:

angular.module('customControl', ['ngSanitize']). 
directive('contenteditable', ['$sce', function($sce) { 
    return { 
    restrict: 'A', // only activate on element attribute 
    require: '?ngModel', // get a hold of NgModelController 
    link: function(scope, element, attrs, ngModel) { 
     if (!ngModel) return; // do nothing if no ng-model 

     // Specify how UI should be updated 
     ngModel.$render = function() { 
     element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); 
     }; 

     // Listen for change events to enable binding 
     element.on('blur keyup change', function() { 
     scope.$evalAsync(read); 
     }); 
     read(); // initialize 

     // Write data to the model 
     function read() { 
     var html = element.html(); 
     // When we clear the content editable the browser leaves a <br> behind 
     // If strip-br attribute is provided then we strip this out 
     if (attrs.stripBr && html == '<br>') { 
      html = ''; 
     } 
     ngModel.$setViewValue(html); 
     } 
    } 
    }; 
}]); 

HTML

<form name="myForm"> 
<div contenteditable 
     name="myWidget" ng-model="userContent" 
     strip-br="true" 
     required>Change me!</div> 
    <span ng-show="myForm.myWidget.$error.required">Required!</span> 
<hr> 
<textarea ng-model="userContent"></textarea> 
</form> 

Quelle aus dem original docs

+0

Ich habe diesen Code bereits im doc gesehen, aber seine Verwendung nicht richtig verstanden, Ihre paar Zeilen haben mich verstanden. =) – Elfayer

+6

Es wird 'ng-model'-Wert nicht angezeigt. Sagen wir anstelle von statischem Text "Ändere mich!" Ich habe eine Variable, die variabel dargestellt wird. – dVaffection

+2

@Ben Diamant: Sobald ich mit der Bearbeitung des contenteditable div beginne, geht der Cursor bei jedem Tastendruck an den Anfang des div. Klicken Sie auf den gewünschten Ort, um ihn erneut zu bearbeiten. –

5

einfach die Lese bewegen Funktionsaufruf in $ render

angular.module('customControl', ['ngSanitize']). 
directive('contenteditable', ['$sce', function($sce) { 
    return { 
    restrict: 'A', // only activate on element attribute 
    require: '?ngModel', // get a hold of NgModelController 
    link: function(scope, element, attrs, ngModel) { 
     if (!ngModel) return; // do nothing if no ng-model 

    // Specify how UI should be updated 
     ngModel.$render = function() { 
     element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); 
     read(); // initialize 
     }; 

     // Listen for change events to enable binding 
     element.on('blur keyup change', function() { 
     scope.$evalAsync(read); 
     }); 

     // Write data to the model 
     function read() { 
     var html = element.html(); 
     // When we clear the content editable the browser leaves a <br> behind 
     // If strip-br attribute is provided then we strip this out 
     if (attrs.stripBr && html == '<br>') { 
      html = ''; 
     } 
     ngModel.$setViewValue(html); 
     } 
    } 
    }; 
}]); 
+0

Warum ist das im ursprünglichen AngularJS-Beispiel falsch? – fishbone

+0

Es funktioniert, weil Sie den viewValue nach dem Rendern einstellen müssen oder die Ansicht nicht Änderungen am Modell widerspiegelt, und das Verschieben des Lesefunktionsaufrufs in $ render erreicht genau das. – goonerify

+0

Ich frage mich nur, warum sie es nicht so gemacht haben ihr Beispiel, weil das viel mehr Sinn macht – fishbone