Angular JS:观察FOO指令中变量的变化,以反映BAR指令

时间:2016-02-08 00:36:59

标签: angularjs angular-ui-typeahead

我目前正致力于扩展Angular Typeahead的用户体验。我使结果列表无法在input .blur上清除,并在查询更改之前保留在DOM中。

但这样结果不会消失。我希望将input.blur()事件绑定到变量,稍后传递给可控制scope模块的typeahead-popup.html

以下是我目前所拥有的相关代码:

angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
    .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$position', 'typeaheadParser',
        function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) {
            return {
                link: function(originalScope, element, attrs, ctrls) {
                    var isBlurred;
                    //some irrelevant library code

                    //on this event I change isBlurred;
                    element.bind('blur', function() {
                        //irrelevant functionality
                        isBlurred = true;
                    });

                    element.bind('focus', function() {
                        isBlurred = false;
                    });
                }
            }
        }
    }])


    .directive('typeaheadPopup', function() {
        return {
            scope {
                //<irrelevant other variables>
                isBlurred: '='
            }
        },
        replace: true,
        //<irrelevant code>
        link: function(scope, element, attrs) {
            //<irrelevant other functions that have access to the scope and apply params at the DOM element>
            scope.$watch('isBlurred', function() {
                console.log(isBlurred)
            });

        });
    })

});

指令typeaheadPopup可以控制相关的DOM元素。因此,变量会从输入上的.blur.focus事件发生变化。但这不会发生。我得到wasBlurred is not defined

问题: 如何以某种方式调整代码,以便在typeahead指令中正确反映typeaheadPopup指令中发生的变量?

4 个答案:

答案 0 :(得分:1)

这是一个带有ui-bootstrap的工作Plunker

这是与ui-bootstrap和关闭按钮控件的集成。 Plunker

这是一个有效的Plunker,其中包含您提供的代码以及有关如何在指令之间进行通信的问题。

您的isBlurred变量需要分配到范围:
originalScope.isBlurred;

模糊和焦点不是将触发范围自动更改的ngModelOptions的一部分。你需要手动触发它。

element.on('blur', function() {
   originalScope.$apply(function(){
      originalScope.isBlurred = true;
   });
});

现在,您的isBlurred已与范围相关联,并且会使用您的自定义事件进行更新,您可以通过以下方式将其转发到typeaheadPopup指令:

<input type="text" ng-model="name" typeahead typeahead-popup="isBlurred">

在typeaheadPopup中定义一个独立的范围:

scope :  {
    isBlurred: '=typeaheadPopup'
}

它是:您的isBlurred变量是可访问的,并将在您的指令中自动更新。无需$watch。但如果您想在事件发生变化时触发事件,则需要一个:

scope.$watch('isBlurred', function() {
     alert("inside typeaheadPopup directive" + scope.isBlurred)
});

答案 1 :(得分:1)

一般答案是针对所有非Angular事件处理程序(在您的情况下为element.bind),您应该调用范围。$ apply (或< strong>范围。$ digest )运行摘要周期并同步值。

因此,对于您的情况,您可以手动调用:

element.on('blur', function() {
    originalScope.isBlurred = true;    
    originalScope.$apply();
});

或运行将为您执行此操作的Angular方法,例如$ timeout:

element.on('blur', function() {
    $timeout(function(){
       originalScope.isBlurred = true;
    });
});

$ timeout有时需要像黑客一样集成第三方非Angular库。

答案 2 :(得分:0)

我猜你需要像demo这样的东西吗?所以你需要在每个指令中分配一个双向有界范围,比如

scope: {
  model: "="
},

然后用相同的模型

设置它们
<body ng-controller='MainController as vm'>
   <foo model='vm.foobar'></foo>
   <bar model='vm.foobar'></bar>
</body>

所以MainController的foobar设置为双向限制于foo和bar的范围,因此从技术上讲,它们共享相同的模型并且具有模型所具有的每个更改。

请参阅完整代码的演示

答案 3 :(得分:0)

如果您可以嵌套指令,或者将一个指令用作另一个指令,那么它们就能够更清晰地进行通信。如果它们存在于同一级别,那么我相信一些注入股票状态是你最好的选择。

如果可能,嵌套指令并按照&#34;创建通信指令&#34;中所述进行通信。 ({3}}。(/ p>)的(在底部)

示例:

angular.module('foo', [])
.directive('parent', function() {
  return {
    restrict: 'E',
    transclude: true,
    controller: function() {
      this.someFunction = function(pane) {
      };
    }
  };
})
.directive('child', function() {
  return {
    require: '^^parent',
    restrict: 'E',
    transclude: true,
    link: function(scope, element, attrs, parentCtrl) {
      parentCtrl.someFunction();
    }
  };
});