在指令中调用控制器函数

时间:2015-02-09 05:52:53

标签: javascript angularjs

我试图从我的自定义指令调用控制器上的回调。 我的目标是生成一个可以在多个地方重复使用的搜索指令。我想通过指令属性中指定的函数传递它需要在附加控制器上调用的函数。

Plunkr网址为here

代码如下

<html ng-app="demo">

<head>
   <title>My Angular App</title>
   <link data-require="bootstrap@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
   <script data-require="bootstrap@*" data-semver="3.3.1" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
   <script data-require="jquery@*" data-semver="2.1.3" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller='carsController'>
  <search-box placeholder="Search Cars" do-search="doSearch()"></search-box>
  <!--
  <form class="form-inline">
    <div class="form-group">
      <input type="text" class="form-control" ng-model="searchText" placeholder="Search Cars" />
    </div>
    <button type="button" class="btn btn-default" ng-click="doSearch()">search</button>    
  </form>
  -->
  <table class="table table-striped">
    <thead>
      <tr>
        <th>Make</th>
        <th>Model</th>
      </tr>
    </thead>
    <tbody ng-repeat="car in cars">
      <tr>
        <td>{{car.make}}</td>
        <td>{{car.model}}</td>
      </tr>
    </tbody>
  </table>
</div>
</body>


app = angular.module('demo',[]);
//controllers
app.controller("carsController", ['$scope', function($scope) {
$scope.searchText = "";
$scope._cars = [
{
  'model': 'A4',
  'make':'Audi'
},
{
  'model':'328i',
  'make':'BMW'
}
];

$scope.cars = $scope._cars; 
$scope.doSearch = function() {
if($scope.searchText.length > 0) {
  $scope.cars = [];
  $scope._cars.forEach(function(car, index) {
  if(car.make.indexOf($scope.searchText) > -1) {
    $scope.cars.push(car);   
  }
}); 
} else {
  $scope.cars = $scope._cars;
}
}

$scope.resetSearch = function() {
  $scope.searchText = "";
  $scope.cars = $scope._cars;
}
}]);

// directives
app.directive("searchBox", searchBox);
function searchBox(){
  return {
    restrict: 'E',
    transclude: true,
    scope: {
       placeholder: '@',
       doSearch: '&'
    },
    link: searchBoxLink,
    templateUrl:'search.html'
  }
}

function searchBoxLink(scope, element, attrs, controller) {
    scope.search = function() {
    scope.doSearch();
  }
}

<form class="form-inline">
  <div class="form-group">
    <input type="text" class="form-control" placeholder="{{placeholder}}" />
    <button type="button" class="btn btn-default" ng-click="search()">
      Search
    </button>
 </div>
</form>

我是ng-noob并且多次阅读过该文档。毋庸置疑,ng-directive仍然是一个谜。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

您的代码问题与控制器doSearch方法无关。我可以看到单击搜索按钮时成功调用了控制器方法。

问题在于控制器范围属性searchText。理想情况下,当您更改搜索文本时,应设置此属性。

我稍微修改了你的代码,将searchText传递给指令,并将搜索框设置为ng-model。

请参阅plunk

答案 1 :(得分:0)

您的代码存在一些问题。我将它们修改为fork of your Plunkr

不绑定搜索文本

您依赖$scope.searchText作为用户在过滤器文本框中输入的文字,但未在任何地方绑定。相反,在我的版本中,我选择为searchText属性表达式提供do-search="doSearch(searchText)"参数。这意味着控制器上的doSearch功能变为:

$scope.doSearch = function(searchText) {
  // make sure its a string and lowercased
  searchText = (searchText || '').toString().toLocaleLowerCase();
  if (searchText.length > 0) {
    $scope.cars = [];
    $scope._cars.forEach(function(car, index) {
      if (car.make.toLocaleLowerCase().indexOf(searchText) > -1) {
        $scope.cars.push(car);
      }
    });
  } else {
    $scope.cars = $scope._cars;
  }
}

您会注意到我也使用了.toLocaleLowerCase()(实际上与.toLowerCase()相同但理论上更好地处理了unicode / funky字符)以确保我进行了不区分大小写的搜索。

其他小改进

我将ng-submit="search()"添加到指令模板中的表单中,以便用户可以按Enter键应用过滤。

相关问题