Contenteditable with ng-model doesn't work

后端 未结 3 1780
轻奢々
轻奢々 2020-12-03 05:22

I\'m trying to store the value of a contenteditable to my JS code. But I can\'t find out why ng-model doesn\'t work in this case.

&         


        
相关标签:
3条回答
  • 2020-12-03 06:06

    contenteditable tag will not work directly with angular's ng-model because the way contenteditable rerender the dom element on every change.

    You have to wrap it with a custom directive for that:

    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>
    

    Source it from the original docs

    0 讨论(0)
  • 2020-12-03 06:20

    Just move the read function call into $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 讨论(0)
  • 2020-12-03 06:27

    Neither of the other answers worked for me. I needed the model's initial value to be rendered when the control was initialized. Instead of calling read(), I used this code inside the link function:

    ngModel.$modelValue = scope.$eval(attrs.ngModel);
    ngModel.$setViewValue(ngModel.$modelValue);
    ngModel.$render()
    
    0 讨论(0)
提交回复
热议问题