Custom指令不会对属性更改做出反应

时间:2014-07-16 16:42:50

标签: javascript jquery angularjs twitter-bootstrap angularjs-directive

我正在构建一个模态指令,我可以使用它来填充一些数据表。我有一个名为modal-visible的指令属性,它将是一个布尔值,默认为false。如果默认值为true,则在加载时,模态可见。但是,当我最初将其设置为false并更改事件中的值时,属性会更改,但该指令不会选择更改。我在指令的链接部分有一个监视器,但它只能获取初始更改。

以下是我的代码示例。我只有一个带按钮和模态的简单测试页面。模态属性modal-visible设置为'false'。单击该按钮时,模态的模态可见属性将更新为“true”,但模式不会显示在页面上。有人可以指导我这个解决方案,并给我一个很好的探索,为什么会发生这种情况?感谢。

testing.html

<button id="btn1" class="btn btn-default">Click Me</button>
<modal id="chartModal" modal-title="Testing a Modal" modal-visible="false">
  <p>Body</p>
</modal>

<script type="text/javascript">
    var modal = $("#chartModal");
    var btn = $("#btn1");

    btn.on("click", function() {
        modal.attr("modal-visible", "true");
    })
</script>

modal.js

(function() {

    var app = angular.module("contactAuthApp");


//////////////////////////
//  BEGIN - DIRECTIVES
//////////////////////////

    var modalDirective = function() {
        return {
            restrict: "E",
            scope: {
                modalVisible: "=",
                modalTitle: "@"
            },
            transclude: true,
            controller: function($scope) {

            },
            templateUrl: "utils/modal.html",
            link: function (scope, element, attrs) {
                //Attach base classes
                element.addClass("modal fade");

                //Hide or show the modal
                scope.showModal = function (visible) {
                    if (visible) {
                        element.modal("show");
                    } else {
                        element.modal("hide");
                    }
                }

                //Check to see if the modal-visible attribute exists
                if (!attrs.modalVisible) {

                    //The attribute isn't defined, show the modal by default
                    scope.showModal(true);

                } else {

                    //Watch for changes to the modal-visible attribute
                    scope.$watch("modalVisible", function (newValue, oldValue) {
                        scope.showModal(newValue);
                    });

                    //Update the visible value when the dialog is closed through UI actions (Ok, cancel, etc.)
                    element.bind("hide.bs.modal", function () {
                        scope.modalVisible = false;
                        if (!scope.$$phase && !scope.$root.$$phase)
                            scope.$apply();
                    });

                }
            }
        };
    }

//////////////////////////
//  END - DIRECTIVES
//////////////////////////  


    app.directive("modal", modalDirective);

})();

modal.html(指令模板)

<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
            <h4 class="modal-title">{{modalTitle}}</h4>
        </div>
        <div class="modal-body">
            <div data-ng-transclude></div>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-default pull-right" data-dismiss="modal">Close</button>
        </div>
    </div>
</div>

EDITED

嘿runTarm:这是我的更新代码,将modalVisible的隔离范围更改为'@'并观察链接中的属性。仍然无法让它发挥作用:

var modalDirective = function() {
    return {
        restrict: "E",
        scope: {
            modalVisible: "@",
            modalTitle: "@"
        },
        transclude: true,
        controller: function($scope) {

        },
        templateUrl: "utils/modal.html",
        link: function (scope, element, attrs) {

            //Attach base classes
            element.addClass("modal fade");

            //Hide or show the modal
            scope.showModal = function (visible) {
                if (visible === true) {
                    element.modal("show");
                } else {
                    element.modal("hide");
                }
            }

            //Watch for changes to the modal-visible attribute
            attrs.$observe("modalVisible", function (val) {
                console.log(val);
                scope.showModal(val);
            });

            //Update the visible value when the dialog is closed through UI actions (Ok, cancel, etc.)
            element.bind("hide.bs.modal", function () {
                scope.modalVisible = false;
                if (!scope.$$phase && !scope.$root.$$phase)
                    scope.$apply();
            });

        }
    };
}

2 个答案:

答案 0 :(得分:2)

对于此条件!attrs.modalVisible,您在else块中有监视,因此在该条件失败时会触发它。将指令(删除if-else块)修改为如下所示:

//Watch for changes to the modal-visible attribute
scope.$watch("modalVisible", function (newValue, oldValue) {
    if( newValue ) {
        scope.showModal(newValue);
    } else {
        //Update the visible value when the dialog is closed 
        //through UI actions (Ok, cancel, etc.)
        element.bind("hide.bs.modal", function () {
            scope.modalVisible = false;
            if (!scope.$$phase && !scope.$root.$$phase)
                scope.$apply();
        });
    }
});

答案 1 :(得分:0)

指令的隔离范围与父范围之间的双向绑定不能与这样的常量一起使用。

<modal modal-visible="false"> // false is a constant boolean value not a variable in the parent scope

您必须选择继续使用双向绑定还是使用自定义监视功能来检测属性更改。

请参阅http://plnkr.co/edit/ZwrL6qlKTQCWZJ3EsXdM?p=preview以获取示例。

在上面的plunker中,modal-two正在使用双向绑定:

<button id="btn2" class="btn btn-default" ng-click="isModalVisible = true">Click Me v2</button>
<modal-two id="chartModal2" modal-title="Testing a Modal" modal-visible="isModalVisible">
  <p>Body</p>
</modal-two>

modal正在使用自定义监视功能:

scope.$watch(function() {
  return element.attr('modal-visible');
}, function (newValue, oldValue) {
  scope.showModal(newValue === 'true');
});

但是,我会拒绝使用自定义监视功能,这不是一种有角度的方式,可能会导致性能问题。