I am trying to call a callback on a controller from my custom directive. My aim to generate a search directive that can be re-used in multiple place. I want to pass it the function it needs to call on the attached controller via the function specified in the directive's attribute.
Plunkr URL is here
The code is as follows
<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>
I am a ng-noob and have read the documentation multiple times. Needless to say ng-directive still remains a mystery.
Thank you for the help
The problem with your code was not about the controller doSearch method. I could see the controller method is successfully invoked when the search button is clicked.
The issue was with the controller scope property searchText
. Ideally, when you change the search text, this property should be set.
I modified your code a bit to pass the searchText
to the directive and set to the search box input as ng-model.
see the plunk
There were a few things wrong with your code. I fixed them in a fork of your Plunkr .
You were relying on $scope.searchText
to be the text the user entered in the filter's textbox, but didn't bind to that anywhere. Instead, in my version, I chose to make a searchText
parameter available to the do-search="doSearch(searchText)"
attribute expression. This means the doSearch
function on the controller becomes:
$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;
}
}
You will notice I also used .toLocaleLowerCase()
(effectively the same as .toLowerCase()
but theoretically deals with unicode/funky characters better) to make sure I did a case insensitive search.
I added ng-submit="search()"
to the form in the template for your directive so the user can press Enter to apply the filtering.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.