使用angularjs,我显示了像这样的2级列表
- first main item
- first subitem of the first main item
- second subitem of the first main item
- AN EMPTY ITEM AS PLACEHOLDER TO ENTER THE NEXT SUBITEM
- second main item
- first subitem of the second main item
- second subitem of the second main item
- AN EMPTY ITEM AS PLACEHOLDER TO ENTER THE NEXT SUBITEM
为了节省空间,我希望只有在相应的div
中的任何内容具有焦点时才显示PLACEHOLDER,以便只有一个这样的占位符。我知道那里有ngFocus
,但我更喜欢比创建大量事件处理程序更简单的东西。也许是这样的:
<div ng-focus-model="mainItem.hasFocus" ng-repeat="mainItem in list">
... main item line
... all subitems
</div>
单向绑定就足够了,因为我不需要设置焦点。
答案 0 :(得分:9)
这里的问题如下:我们希望避免向每个子节点添加事件侦听器,但只将其添加到父节点。家长将负责采取适当的行动。对此的一般解决方案是使用均匀传播(委托)。我们只向父节点附加一个侦听器,当子节点上发生事件时(在此示例中关注输入元素),它将冒泡到父节点,父节点将执行侦听器。
这是指令:
app.directive('ngFocusModel', function () {
return function (scope, element) {
var focusListener = function () {
scope.hasFocus = true;
scope.$digest();
};
var blurListener = function () {
scope.hasFocus = false;
scope.$digest();
};
element[0].addEventListener('focus', focusListener, true);
element[0].addEventListener('blur', blurListener, true);
};
});
该指令侦听事件并相应地设置范围的值,因此我们可以进行条件更改。
这里有几点需要注意。
focus
和blur
事件不会“冒泡”,我们需要使用“事件捕获”来捕获它们。这就是为什么不使用element.on('focus/blur')
(它不允许捕获,afaik)而是addEventListener
方法的原因。此方法允许我们通过相应地将第三个参数设置为false
或true
来指定是否将在“事件冒泡”或“事件捕获”上执行侦听器。
我们本可以使用“冒泡”的focusin
和focusout
事件,但不幸的是,这些事件在Firefox(focusin和focusout)中不受支持。
这是实施的plunker。
<强>更新强>
在我看来,这可以使用:focus
伪类使用纯CSS来完成,唯一的缺点是占位符需要相对于输入元素处于适当的位置(兄弟)。请参阅codepen。
答案 1 :(得分:2)
不幸的是,做出你想要的唯一坚实的方法是回应输入上的焦点\模糊事件......这是获得通知的唯一方式。
您可以将隐藏输入作为每个div中的第一个元素并将NgFocus属性放在其上,但只有在用户选中它时才有效。
答案 2 :(得分:2)
我创建了一个可以用于所需内容的小指令:
app.directive('childFocus', function($window){
var registered = [];
// observing focus events in single place
$window.addEventListener('focus', function(event){
registered.forEach(function(element){
if(element.contains(event.target)){
// if element with focus is a descendant of the
// element with our directive then action is triggered
element._scope.$apply(element._scope.action);
}
});
}, true)
return {
scope : {
action : '&childFocus' // you can pass whatever expression here
},
link : function(scope, element){
// keep track ref to scope object
element[0]._scope = scope;
// (probably better would be to register
// scope with attached element)
registered.push(element[0]);
scope.$on('destroy', function(){
registered.splice(registered.indexOf(element[0]),1);
});
}
}
});