我想连接一个带有多个输入元素的弹出式菜单,并在一个新的输入元素被聚焦时显示菜单。点击菜单外按钮,菜单关闭。
简化的PLKNR示例链接/代码如下。
我想知道在这种情况下更新弹出式菜单位置的最直接方法是什么。换句话说:如何将有关新聚焦的输入元素的信息返回到指令中以在那里进行更改(输入元素的位置和值)。
在我的代码中,我存储了关于服务位置的信息(以及对当前聚焦的输入元素的引用),但这不起作用(该指令在没有scope.$apply的情况下不会更新)。
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $document, eventService) {
$("input").on("focus", function(event) {
$scope.$apply(function() {
eventService.register(event.target, $scope);
eventService.positon = $(event.target).position();
$scope.position = eventService.position;
console.log("in", $scope.position);
eventService.addMenu();
});
console.log('from event', $(event.target).position());
});
$("input").on("blur", function() {
console.log('blured');
// eventService.closeList()
});
});
app.directive("myMenu", function($document, eventService, $compile) {
return {
restrict: "A",
link: function(scope, elem, attrs) {
var menu = angular.element('<div id="menu" class="menu">menu {{menuText}}<div>');
$compile(menu)(scope);
eventService.input = $("input").first(); //set the first input
scope.menuText = eventService.input.val();
scope.$watch(function() {
return eventService.input.val();
}, function(newValue, ov) {
scope.menuText = newValue;
});
// $document.off("dialogmutex", closeMenu);
$document.on("dialogmutex", closeMenu);
// close menu on outside click:
$document.on("click", function(event) {
// if the menu or input is clicked dont close it.
if (!((event.target === elem[0]) || event.target === eventService.input[0] || (elem.find(event.target).length > 0))) {
$document.trigger("dialogmutex");
}
});
function addMenu() {
// positioning the menu does not work
var pos = eventService.position;
if (pos) {
elem.css({
top: pos.yPos,
left: pos.xPos,
position: 'absolute'
});
}
console.log("directive position:", pos);
elem.append(menu);
scope.menuText += " x "
}
function closeMenu() {
elem.find("#menu").remove();
}
addMenu(); // open menu on app start
eventService.addMenu = addMenu; // open the menu later from the controller via service
}
};
});
// service used to register a new input element with the directive.
app.service('eventService', function() {
service = {
register: function(el) {
service.input = $(el);
console.log('reg');
service.position = service.input.position();
console.log("on service", service.position)
}
};
return service;
});
更新:
我得到了它的工作使用ngStyle
指令容器元素和指令范围上的positionCSS对象,这样我只需要调用$scope.$apply
一次(在事件处理程序)
使用id
为每个输入和使用.closest
在jQuery应该做的技巧。您可以参考此链接了解详细版本。