3

contenteditable div で (ngModel $formatters と $parsers を使用して) 一致したテキストを強調表示しようとしています。レンダリング後に強調表示は行われず、ngModel の変更をリッスンして HTML を更新すると、変更ごとにキャレットが移動します。

つまり、'search' と入力すると、$viewValue に入力された後に (SEARCH) に変換され、$modelValue では 'search' (またはこの例では SEARCH) のままになり、'search から 'h' を削除すると括弧が削除されます。 '

編集plunkr を編集して、同じモデルに関連付けられた 2 つのフィールドが存在するようにしました (1 つの入力、1 つの contenteditable pre ですが、実際には問題ではありません)。一方を変更すると、もう一方が $modelValue の変更を取得します$formatters を介してプッシュしますが、変更が行われた div は変更を反映しません。$viewValue が変更されたときに、すべての div (1 つまたは複数の場合) が $parse および $format されるようにしたいと思います。

http://plnkr.co/edit/H4Cw5t?p=preview

HTML

<pre ng-model="someString" highlight-search contenteditable="true"></pre>

JS

app.directive('contenteditable', function() {
  return {
    require: '?ngModel',
    link: function(scope, element, attrs, ctrl) {
      if(!ctrl) return;

      // view -> model
      element.bind('keyup', function() {
        var key = event.keyCode;
        if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;

        var value = element.html();

        if (ctrl.$modelValue !== value) {
            scope.$apply(function() {
                ctrl.$setViewValue(value);
            });
            //element.html(ctrl.$viewValue);   //messes up cursor position
        }

        console.log(ctrl.$modelValue, '\n', ctrl.$viewValue);
      });

      // model -> view
      ctrl.$render = function() {
        element.html(ctrl.$viewValue);
      };
    }
  };
});

app.directive('highlightSearch', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link : function(scope, element, attrs, ngModel) {
            var highlightSites = function (input) {
                return input.replace(/search/gi, '(SEARCH)');
            };

            var unhighlightSites = function (input) {
                return input.replace(/[^A-Z ]/ig, '');
            };

            ngModel.$parsers.push(unhighlightSites);
            ngModel.$formatters.push(highlightSites);
        }
    }
});
4

0 に答える 0