如何将回调传递给扩展现有指令的Angular指令?

时间:2016-09-26 09:50:54

标签: angularjs ui-select angular-ui-select

我正在使用Angular ui-select创建一个"搜索和选择组件"。当用户键入搜索字段时,它会立即将项目列表过滤为自由文本过滤器。此外,用户可以从下拉列表中选择选项,这些选项在过滤器中用作精确搜索词(例如按类别过滤)。

我创建了一个扩展<ui-select>的附加指令,以便从该作用域中访问$select.search值。此变量包含用户键入的自由文本。我的问题是如何将其传递给父控制器?

理想情况下,我喜欢以下内容:

<ui-select
  my-ui-select
  on-search-changed="searchChanged(newValue, oldValue)"
  multiple
  ng-model="ctrl.myModel">
    <!-- ... -->
</ui-select>

我的自定义指令会使用自由文本值调用on-search-changed回调。问题是我无法为my-ui-select指令定义范围,因为它会与ui-select范围冲突。

如何将回调方法传递给我的自定义指令,同时仍能访问ui-select范围?或者有更好的方法来实现我之后的目标吗?

我创建了a Plunker based on the ui-select examples。我已经定义了使用myUiSelect输出搜索词的console.log指令。我想要的是从那里调用DemoCtrl.searchChanged方法。

2 个答案:

答案 0 :(得分:0)

在您call on-search-changed回调的自定义指令中,您可以使用$ emit发出事件。 有关$ emit的文档:

  

通过范围层次结构通知向上调度事件名称   注册的$ rootScope.Scope监听器。

所以你可以这样做:

$scope.$emit("mySelectEventThing", "Hey this is the value I want to emit");

在您的父作用域/控制器中,您可以收听事件:

$scope.$on("mySelectEventThing", function(event, theValue) {
    alert(theValue); // alert with 'Hey this is the value I want to emit'
});

$ emit向上广播到父作用域。 $ broadcast向下发送到所有子范围。如果你有很多范围,$ broadcast的性能要高一些。你可能不需要这个。

发送事件是Angular中正确传递数据到另一个范围的唯一方法。

您也可以使用$ scope。$ parent访问父作用域,但这是非常糟糕的做法,因为您无法确保达到预期范围。

答案 1 :(得分:0)

我认为你应该改变你的方法,而不是在你的指令中扩展ui select,你应该将它包装在yoru指令中,并从控制器传递函数以在指令中调用。

指令代码

app.directive('myUiSelect', function() {
    return {
    templateUrl:'myUiSelect.html',
    scope:{
      onSearchChanged:'=',
      selectedItem:'=',
      items:'='
    },
    link: function(scope, element, attrs, $select) {
    scope.selectedItemModel = {
        selectedItem:[]

    }
    scope.onSelectCallback = function(item, selectedItems){

    scope.onSearchChanged(scope.selectedItemModel.selectedItem, item)

   }
  }
 };
})

html partial(myUiSelect.html)

<ui-select multiple 
       ng-model="selectedItemModel.selectedItem" 
       theme="bootstrap" 
       ng-disabled="ctrl.disabled" 
       sortable="true"
       on-select="onSelectCallback($item, $model)"
       close-on-select="false" 
       style="width: 800px;">
<ui-select-match placeholder="Select person...">{{$item.name}} &lt;{{$item.email}}&gt;</ui-select-match>
<ui-select-choices repeat="person in items | propsFilter: {name: $select.search, age: $select.search}">
  <div ng-bind-html="person.name | highlight: $select.search"></div>
  <small>
    email: {{person.email}}
    age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
  </small>
 </ui-select-choices>
 </ui-select>

这是工作Plunker

如果我对这个问题的理解不对,请告诉我