【问题标题】:Dynamically add ng-click in dropdown directive在下拉指令中动态添加 ng-click
【发布时间】: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


    【解决方案1】:

    玩了一会儿后,我了解了如何编译 html。我只需要传入我正在使用的叠加层的内容。所以有效的代码行是:

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 为什么我必须编译 html? ng-click 是添加到 li 元素中,而不是添加到它的内容中?
      • 糟糕,很多代码...您必须重新编译添加点击的 HTML。
      • 好的。我该怎么做。我仍在学习指令,不熟悉如何去做。谢谢。
      • 谁能帮助我重新编译html?
      猜你喜欢
      • 2014-04-02
      • 1970-01-01
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      • 2014-01-23
      • 2016-03-05
      • 2014-08-14
      • 1970-01-01
      相关资源
      最近更新 更多