我目前正致力于扩展Angular Typeahead的用户体验。我使结果列表无法在input
.blur
上清除,并在查询更改之前保留在DOM中。
但这样结果不会消失。我希望将input.blur()
事件绑定到变量,稍后传递给可控制scope
模块的typeahead-popup.html
。
以下是我目前所拥有的相关代码:
angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
.directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$position', 'typeaheadParser',
function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) {
return {
link: function(originalScope, element, attrs, ctrls) {
var isBlurred;
//some irrelevant library code
//on this event I change isBlurred;
element.bind('blur', function() {
//irrelevant functionality
isBlurred = true;
});
element.bind('focus', function() {
isBlurred = false;
});
}
}
}
}])
.directive('typeaheadPopup', function() {
return {
scope {
//<irrelevant other variables>
isBlurred: '='
}
},
replace: true,
//<irrelevant code>
link: function(scope, element, attrs) {
//<irrelevant other functions that have access to the scope and apply params at the DOM element>
scope.$watch('isBlurred', function() {
console.log(isBlurred)
});
});
})
});
指令typeaheadPopup
可以控制相关的DOM元素。因此,变量会从输入上的.blur
和.focus
事件发生变化。但这不会发生。我得到wasBlurred is not defined
。
问题:
如何以某种方式调整代码,以便在typeahead
指令中正确反映typeaheadPopup
指令中发生的变量?
答案 0 :(得分:1)
这是一个带有ui-bootstrap的工作Plunker。
这是与ui-bootstrap和关闭按钮控件的集成。 Plunker
这是一个有效的Plunker,其中包含您提供的代码以及有关如何在指令之间进行通信的问题。
您的isBlurred
变量需要分配到范围:
originalScope.isBlurred;
模糊和焦点不是将触发范围自动更改的ngModelOptions的一部分。你需要手动触发它。
element.on('blur', function() {
originalScope.$apply(function(){
originalScope.isBlurred = true;
});
});
现在,您的isBlurred已与范围相关联,并且会使用您的自定义事件进行更新,您可以通过以下方式将其转发到typeaheadPopup
指令:
<input type="text" ng-model="name" typeahead typeahead-popup="isBlurred">
在typeaheadPopup中定义一个独立的范围:
scope : {
isBlurred: '=typeaheadPopup'
}
它是:您的isBlurred变量是可访问的,并将在您的指令中自动更新。无需$watch
。但如果您想在事件发生变化时触发事件,则需要一个:
scope.$watch('isBlurred', function() {
alert("inside typeaheadPopup directive" + scope.isBlurred)
});
答案 1 :(得分:1)
一般答案是针对所有非Angular事件处理程序(在您的情况下为element.bind
),您应该调用范围。$ apply (或< strong>范围。$ digest )运行摘要周期并同步值。
因此,对于您的情况,您可以手动调用:
element.on('blur', function() {
originalScope.isBlurred = true;
originalScope.$apply();
});
或运行将为您执行此操作的Angular方法,例如$ timeout:
element.on('blur', function() {
$timeout(function(){
originalScope.isBlurred = true;
});
});
$ timeout有时需要像黑客一样集成第三方非Angular库。
答案 2 :(得分:0)
我猜你需要像demo这样的东西吗?所以你需要在每个指令中分配一个双向有界范围,比如
scope: {
model: "="
},
然后用相同的模型
设置它们<body ng-controller='MainController as vm'>
<foo model='vm.foobar'></foo>
<bar model='vm.foobar'></bar>
</body>
所以MainController
的foobar设置为双向限制于foo和bar的范围,因此从技术上讲,它们共享相同的模型并且具有模型所具有的每个更改。
请参阅完整代码的演示
答案 3 :(得分:0)
如果您可以嵌套指令,或者将一个指令用作另一个指令,那么它们就能够更清晰地进行通信。如果它们存在于同一级别,那么我相信一些注入股票状态是你最好的选择。
如果可能,嵌套指令并按照&#34;创建通信指令&#34;中所述进行通信。 ({3}}。(/ p>)的(在底部)
示例:
angular.module('foo', [])
.directive('parent', function() {
return {
restrict: 'E',
transclude: true,
controller: function() {
this.someFunction = function(pane) {
};
}
};
})
.directive('child', function() {
return {
require: '^^parent',
restrict: 'E',
transclude: true,
link: function(scope, element, attrs, parentCtrl) {
parentCtrl.someFunction();
}
};
});