web-dev-qa-db-ja.com

AngularJS-contenteditable <span>でng-modelが失敗する

私はAngularJSを学んでいます。説明できないことや、説明(または解決策)を見つけることができません。

単純なAngularJSアプリがあり、<span contenteditable="true">を値にバインドしようとしていますが、機能しません。例えば:

<!-- Works as expected -->
<input data-ng-model="chunk.value"></input>

<!-- Shows value, but doesn't bind - changes not reflected in model -->
<span contenteditable="true">{{chunk.value}}</span>

<!-- This is empty -->
<span contenteditable="true" data-ng-model="chunk.value"></span>

最後のスパンで双方向バインディングを使用して、その値を編集するとchunk.valueが更新されるようにするにはどうすればよいですか?

16
Alex McMillan

ng-bind! 'span'での一方向のバインドにはng-bindを使用します。

例については、ここを参照してください: https://docs.angularjs.org/api/ng/directive/ngBind

したがって、あなたの行は次のようになります:<span contenteditable="true" ng-bind="chunk.value"></span>

この助けを願っています

21
Siti Farah

作る ng-model contenteditableを使用する<span>要素、カスタムディレクティブを使用:

app.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);
        }
      }
    };
}]);

使用法:

<span contenteditable ng-model="userContent">Change me!</span>
<p>{{userContent}}</p>

詳細については、


デモ

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);
        }
      }
    };
  }]);
[contenteditable] {
  border: 1px solid black;
  background-color: white;
  min-height: 20px;
}
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angular-sanitize/angular-sanitize.js"></script>
<body ng-app="customControl">
 <span contenteditable ng-model="userContent">Change me!</span>
 <hr>
 Content={{userContent}}
</body>
1
georgeawg

_ng-model_はspanで使用するためのものではありません。どうしても必要な場合は、このためのカスタムディレクティブを作成できます。このディレクティブは、contentEditablespanに_keydown,keyup_リスナーを設定し、スコープモデル($apply()内)を更新します。これにより、スパンコンテンツがモデルにバインドされます。

すぐに plunker を作成しました。見てみな。 _<span>_コンテンツをスコープモデルに同期します。ブラウザコンソールを開いて、何かを入力するたびにスコープモデルが更新されることを確認します。

0
Sandeep Panda

ng-model-options="{ getterSetter: true }"動作がng-modelが関連付けられている要素に追加する。 ng-model-options="{ getterSetter: true }"<form>に追加することもできます。これにより、その内部のすべての<input>sに対してこの動作が有効になります。

例は、ngModelgetter/setterとともに使用する方法を示しています。 デモページ

0
Prabhakaran S

@VtoCorleoneが指摘したように、ngModelは機能しません。 ngModel docs

The ngModel directive binds an input,select, textarea (or custom form control) to a property on the scope using NgModelController, which is created and exposed by this directive.

contenteditableディレクティブ をご覧ください。

それ以外の場合、潜在的な回避策:呼び出される関数を用意します。次に、その関数はコントローラー内の$scope.chunk.valueを更新します。バインディングが更新されると、他の要素のコンテンツも処理されます。

正確な外観や機能がわからないので、<textarea>の中に入れて、<span>のようにスタイルを設定します(枠線や背景はありません)。次に、それがfocusにあるときに、スタイルを追加して、編集できることを確認します。この方法では、ng-modelを使用することを目的としているため、これを使用できます。このアプローチの基本的な実装は次のとおりです。 Plunker

0
EnigmaRM