【发布时间】:2014-08-01 16:03:04
【问题描述】:
我正在尝试将 ng-click 动态添加到在指令内动态创建的一堆 li 中。这个想法是隐藏选择元素并用带有 ul 的自定义 div 覆盖它,并将其用作下拉菜单。这样它就可以随心所欲地设计。当您从 ul 列表中选择时,我使用该指令来控制选择。我在指令中动态创建了 ul 和 li,并将它们添加到元素之前。我动态添加了 ng-click 属性。这一切都很好,但是,ng-click 永远不会触发。所以我不得不通过 jQuery 使用 click 事件(由于 Foundation,它在页面上)。这是我的代码。 `dataviz.directive("customDropdown", ["$timeout", "$rootScope", "$document", "$compile", function($timeout, $rootScope, $document, $compile){
return {
controller: function($scope) {
$scope.clicked = function() {
alert("ng click worked");
}
},
link: function(scope, element, attributes) {
// hide the default select element
// TODO: use css instead
element.hide();
var id,
overlay = angular.element(document.createElement("div")),
ul = angular.element(document.createElement("ul")),
span = angular.element(document.createElement("span"));
id = Math.random().toString().slice(2);
/*
* Process the option clicked on. this will dynamically set the
* correct option as selected and trigger the change event
*
* @method processOptionClick
* @param {Element} the li element clicked on
* @return undefined
* */
function processOptionClick(li) {
if ( li.data("value") !== "0" ) overlay.addClass("active");
span.html(li.html());
element
.children()
.attr("selected", false);
element
.children()
.eq(li.attr("data-value"))
.attr("selected", true);
// firefox and safari need you to explicitly set the selected attribute
element[0].selectedIndex = li.attr("data-value");
element.trigger("change");
}
/*
* Populate the li based on the options in the select element
*
*
* @method populateFakeDropdown
* @return undefined
* */
function populateFakeDropdown() {
// use $timeout to make sure options are populated before copying
// them to the ul
// TODO: this can be better. maybe a promise or custom event of something like that
$timeout(function(){
var options = element.children();
// set the span html to the selected li
span.html((element.find(":selected").html()));
// if the value is blank then the dropdown reset so remove the active overlay
if ( element.find(":selected").val() === "" ) overlay.removeClass("active");
// remove all previous li's
ul.empty();
// loop through the options and rebuild the li's
angular.forEach(options, function(value, key) {
var curOpt = angular.element(value),
li = angular.element(document.createElement("li"));
if ( curOpt.html() === "Janssen" ) overlay.addClass("active");
li.addClass("options");
// set the data-value to the index. should be the same as the option it mirrors
li.attr("data-value", key);
li.attr("data-ng-click", "clicked()");
li.on("click", function(){
processOptionClick(li);
});
// set the text of the li from the text of the option
li.html(curOpt.html());
ul.append(li);
});
}, 10);
}
span.addClass("selected");
/*
* set the data-id of the span. this used for when clicking on dropdown.
* without this if you click on the text of the dropdown it wouldn't trigger
* */
span.attr("data-id", id);
// hide ul
// TODO: this should be done in the css
ul.hide();
overlay
.addClass("dropdown")
.addClass("view-height")
.addClass(function(){
return element.attr("class");
});
overlay.attr("data-id", id);
overlay
.append(span)
.append(ul);
// prepend the new overlay before the select element
element.before(overlay);
// bind a click event to the body. this allows us to close the "dropdown" when clicking outside of it
angular.element($document[0].body).on("click", function(e){
var element = angular.element(e.target);
// hide any open ul's
ul.hide();
// if the element clicked on matches then show the ul
if ( element.attr("data-id") === id ) {
ul.addClass("active").show();
}
});
// this should run only once when the directive is instatiated. it will
// populate the fake dropdown
populateFakeDropdown();
// anytime there is an update to the request object update the dropdows as
// there is a potential that they may have changed
$rootScope.$on("updateDropdowns", function(){
populateFakeDropdown();
});
}
}
}]);`
我想使用 ng-click,这样我就可以将其保持在角度范围内,并在移动设备上利用 ngTouch。
【问题讨论】:
标签: javascript jquery angularjs angularjs-directive