我正在编写一个简单的Angular指令,用于显示textarea
旁边的行号。但是,由于某种原因,$ watch表达式不会触发更新。这是代码:
mod.directive('newTextArea', function() {
return {
restrict: 'E',
scope: {
query: '='
},
template:
'<div>' +
' <div ng-style="{height: height}" style="width: 20px; float: left; color: gray; font-family: Courier New; font-size: 14px; overflow: hidden; height: 85px; position: relative; top: 5px;">' +
' <div style="position: absolute">' +
' <span ng-repeat="line in lines">{{line}}<br></span>' +
' </div>' +
' </div>' +
' <textarea id="query-area" style="overflow-x: scroll; font-family: Courier New; font-size: 14px;">' +
' </textarea> {{ lines }}' +
'</div>',
controller: function($scope, $attrs, $element) {
var textarea = document.getElementById('query-area');
function updateLayout() {
var st = textarea.scrollTop;
var h = textarea.scrollHeight;
$scope.height = h;
console.log(st, h);
if (st !== undefined && h !== undefined) {
var start = Math.round(st / 14);
var stop = Math.round((st + h) / 14);
$scope.lines = _.range(start+1, stop+1);
}
}
$scope.$watch(
function() {
return [textarea.scrollHeight, textarea.scrollTop];
}, updateLayout, true
);
}
};
一旦滚动textarea或其大小发生变化,行号应立即更新。知道为什么这不起作用吗?
答案 0 :(得分:1)
观察者在摘要循环期间运行。在文本区域中写入不会导致摘要循环开始,因此观察者永远不会被执行。
如果您例如将ng-model="something"
添加到textarea
元素,那么它将起作用,因为Angular将绑定到一堆事件,并在它们触发时在内部触发摘要循环。
如果不依赖其他东西来触发摘要循环,您可以用以下内容替换$watch
:
var listener = function() {
$scope.$apply(updateLayout);
};
angular.element(textarea).on('keyup keydown keypress change', listener);
updateLayout();
$scope.$on('$destroy', function () {
angular.element(textarea).off('keyup keydown keypress change', listener);
});