Jacob
Jacob

Reputation: 25

AngularJS data binding in controller

This works great:

<input type="text" class="search" data-ng-model="name"/>
<div class="rf-contact" data-ng-repeat="contact in contacts | filter: name">
   <p class="rf-first">{{contact.first_name}} {{contact.last_name}}</p>
</div>

However I need to implement filter in the controller:

var contactsController = function ($scope, $filter){
    $scope.contacts = contacts;
    $scope.filteredContacts = $filter('filter')($scope.contacts, $scope.name);
}

<input type="text" class="search" data-ng-model="name"/>   
<div class="rf-contact" data-ng-repeat="contact in filteredContacts">
    <p class="rf-first">{{contact.first_name}} {{contact.last_name}}</p>
</div>

The problem with the code above is that the data binding is lost. When the data is changing in the text field, the filtering is not happening. Do I need to explicitly set event listeners for the input field in my controller? thanks.

Upvotes: 0

Views: 169

Answers (2)

Christophe L
Christophe L

Reputation: 14035

You could try $watch-ing the name:

var contactsController = function ($scope, $filter){
    $scope.contacts = contacts;
    $scope.filteredContacts = $filter('filter')($scope.contacts, $scope.name);
    $scope.$watch('name', function(newValue, oldValue) {
        $scope.filteredContacts = $filter('filter')($scope.contacts, newValue);
    });
}

For more info on $watch: http://docs.angularjs.org/api/ng/type/$rootScope.Scope. Anytime "something" happens through Angular (like the value of "name" changes because you type something in the text field), Angular will fire the watch you created and execute the function. This is necessary here because the initial code you wrote builds the filteredContacts scope variable when the controller is instantiated and there's nothing re-evaluating this expression.

While this solution with an explicit $watch will work, it's a little hacky. This kind of logic is better encapsulated in a custom filter. You can easily build one with arbitraty logic as described in http://docs.angularjs.org/tutorial/step_09.

Upvotes: 1

bigblind
bigblind

Reputation: 12867

Try the following

var contactsController = function ($scope, $filter){
  $scope.filterContacts = function(){
    $scope.contacts = contacts;
    $scope.filteredContacts = $filter('filter')($scope.contacts, $scope.name);
  }
}

<input type="text" class="search" data-ng-model="name" ng-change="filterContacts()"/>   
<div class="rf-contact" data-ng-repeat="contact in filteredContacts">
    <p class="rf-first">{{contact.first_name}} {{contact.last_name}}</p>
</div>

Here's a jsfiddle of this in action: http://jsfiddle.net/CAuq9/

Upvotes: 0

Related Questions