2015-02-18 18 views
11

Próbuję zapisać wartość contenteditable do mojego kodu JS. Ale nie mogę się dowiedzieć, dlaczego ng-model nie działa w tym przypadku.Contenteditable z ng-model nie działa

<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> 

Czy istnieje obejście tego problemu?

Patrz: JSFiddle

Uwaga: Tworzę edytor tekstu, więc użytkownik powinien zobaczyć wynik, a ja przechowywania HTML za nim. (Tj. Użytkownik patrz: „To przykład!”, A ja przechowywania: This is an <b>example</b> !)

Odpowiedz

26

tag contenteditable nie działa bezpośrednio z NG-modelu kątowym, ponieważ droga contenteditable rerender elementu DOM na każdej zmianie.

Trzeba owinąć go z dyrektywy niestandardowym za to:

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> 

Źródło go z original docs

+0

Już widziałem ten kod w dokumencie, ale nie rozumiałem, jak poprawnie go używa, kilka linii pozwoliło mi to zrozumieć. =) – Elfayer

+6

Nie wyświetla wartości 'ng-model'. Powiedzmy zamiast statycznego tekstu "Zmień mnie!" Mam zmienną, która pokazuje zmienną taką jaka jest. – dVaffection

+2

@Ben Diamant: Jak tylko rozpocznę edycję contenteditable div, przy każdym naciśnięciu klawisza mój kursor przejdzie na początek div. Musisz kliknąć w wybranym miejscu, aby edytować ponownie. –

5

Wystarczy przesunąć odczytu wywołanie funkcji w $ 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

Dlaczego błąd jest nieprawdziwy w oryginalnym przykładzie AngularJS? – fishbone

+0

Działa, ponieważ musisz ustawić wartość viewValue po renderowaniu lub widok nie będzie odzwierciedlał zmian w modelu, a przeniesienie wywołania funkcji odczytu do $ render osiąga tylko to, – goonerify

+0

Po prostu zastanawiam się, dlaczego nie zrobili tego w ten sposób w ich przykład, ponieważ ma to więcej sensu – fishbone

Powiązane problemy