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);
}
}
});