Angular Material:md-autocomplete - 如何在Enter事件中隐藏md-autocomplete-suggestions?

sna*_*ggs 14 angularjs angular-material

我有md-autocomplete:

<md-autocomplete 
                         md-min-length="1"
                         ng-enter="presEnter();"
                         md-no-cache="true"                        
                         md-selected-item="selectedItem" 
                         md-search-text="searchText" 
                         md-items="item in querySearch(searchText)"
                         md-item-text="item.name" 
                         placeholder="Search for a vegetable">
          <span md-highlight-text="searchText">{{item.name}} :: {{item.type}}</span>
        </md-autocomplete>
Run Code Online (Sandbox Code Playgroud)

与指令:ng-enter.

我的目标:当用户按下时Enter我想隐藏md-autocomplete-suggestions下拉列表

我从HTML中知道我需要以某种方式调用:$mdAutocompleteCtrl.hidden = true;但不知道如何$mdAutocompleteCtrl在Controller中使用.

我用Google搜索并发现:

$timeout( function() { $scope.$$childHead.$mdAutocompleteCtrl.hidden = true; },100);
Run Code Online (Sandbox Code Playgroud)

但没有$mdAutocompleteCtrl(至少在我的JS中,只在HTML中,我不知道它的范围)

我玩这个例子:输入'a'并在下拉列表后按Enter键.

有任何想法吗?

Jam*_*mes 20

$mdAutocompleteCtrl作为属性放置在自动填充的范围内.

首先,您需要访问自动完成元素.一种方法是在自动完成上放置一个ID:

<md-autocomplete id='Auto'
                 md-min-length="1"
                 ng-enter="presEnter();"
                 md-no-cache="true"
                 md-selected-item="selectedItem"
                 md-search-text="searchText"
                 md-items="item in querySearch(searchText)"
                 md-item-text="item.name"
                 placeholder="Search for a vegetable">
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用该元素来获取自动完成的内部范围.由于autocomplete元素本身位于您提供的范围内,因此您需要获取其中一个autocomplete的子元素的范围.

$scope.presEnter = function(e){
    var autoChild = document.getElementById('Auto').firstElementChild;
    var el = angular.element(autoChild);
    el.scope().$mdAutocompleteCtrl.hidden = true;
};
Run Code Online (Sandbox Code Playgroud)

这是一个工作示例:http://codepen.io/anon/pen/rVPZNN#editors=101


DRo*_*son 10

TLDR:触发的示例代码隐藏http://codepen.io/anon/pen/mJvGzp?editors=101

问题:

首先,"Angular Way"建议应避免在Controller中操纵指令.Controller应该基本上只检索(通过服务等)并提供构建视图所需的数据; 它通常应该避免关心这些视图的实现方式(即它应该知道不会使用哪些指令).这有很多很好的理由,一个可能是当你想要修改视图时,它会让生活变得更加容易,例如交换指令.

如果指令确实需要手动修改,最好从另一个指令执行此操作.这允许更大的灵活性,并在以后简化重构(相同的示例:如果交换不同的自动完成指令).

此外,虽然在这种情况下它似乎是解决问题的唯一方法,但$scope.$$childHead.$mdAutocompleteCtrl.hidden代码看起来相当hacky - 除非没有其他选择,否则应该避免访问属性$$,并避免修改兄弟指令而不通过共享范围属性.

不幸的是,在深入挖掘源代码(在主分支上)之后,我找不到任何更好的方法来触发隐藏功能,而不是(如你所建议的)抓住它的范围并修改hidden属性.

通过Controller访问它的另一个问题是它有点困难,因为它通过其他一些范围嵌套.你可以传递事件,获取DOM节点,然后调高它的范围,但这在Controller中是很多不相关的东西.

解决方案:

因此,我们可以添加一个兄弟指令,类似于ngEnter您在Codepen示例中包含的示例指令.也许是一些更明确的东西,以便它更明显地在做什么:

.directive('mdHideAutocompleteOnEnter', function () {
    return function (scope, element, attrs) {
        element.bind("keydown keypress", function (event) {
            if(event.which === 13) {
                scope.$apply(function (){
                    scope.$$childHead.$mdAutocompleteCtrl.hidden = true; // $scope  modified to scope
                });

                event.preventDefault();
            }
        });
    };
});
Run Code Online (Sandbox Code Playgroud)

HTML相关时只包含此指令:

<md-autocomplete 
               md-hide-autocomplete-on-enter
               md-items="item in querySearch(searchText)"
               md-item-text="item.name">
     <span md-highlight-text="searchText">{{item.name}} :: {{item.type}}</span>
</md-autocomplete>
Run Code Online (Sandbox Code Playgroud)

以下是使用它进行修改的示例:http://codepen.io/anon/pen/mJvGzp?edit = 101