在下拉指令中动态添加ng-click

时间:2014-08-01 16:03:04

标签: javascript jquery angularjs angularjs-directive

我正在尝试动态添加ng-click到一堆在指令内动态创建的li。我们的想法是隐藏select元素并使用带有ul的自定义div覆盖它,并将其用作下拉列表。这样它无论如何都可以设计风格。当你从ul列表中选择时,我使用该指令来控制select。我在指令中动态创建了ul和li,并在元素之前添加它们。我动态添加ng-click属性。这一切都很好,然而,ng-click永远不会触发。所以我被迫通过jQuery使用click事件(由于Foundation而在页面上)。这是我的代码。 `dataviz.directive(“customDropdown”,[“$ timeout”,“$ rootScope”,“$ document”,“$ compile”,函数($ 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移动设备。

2 个答案:

答案 0 :(得分:1)

在玩了一下后,我重新学习了如何编译html。我只需要传递我正在使用的叠加层的内容。所以有效的代码行是:

$compile(ul.contents())(scope);

现在我知道如何正确使用$ compile服务。 :)

答案 1 :(得分:0)

您必须在需要Angular指令的新HTML上使用$compile

li.html(
    $compile(curOpt.html())(scope);
);