1

I'm looking for tutorial or example on how to implement a simple input text for searching in the grid. My attempt (but ng-keyup require angularjs > 1.1.3 and I've got 1.0.7)

<input type="text" ng-keyup="mySearch()" ng-model="searchText">
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
                    setTimeout(function () {
                        var data;
                        if (searchText) {
                            var ft = searchText.toLowerCase();
                            $http.get('largeLoad.json?q='+encodeURIComponent(ft)).success(function (largeLoad) {        
                                $scope.setPagingData(largeLoad,page,pageSize);
                            });            
                        } else {
                            $http.get('largeLoad.json').success(function (largeLoad) {
                                $scope.setPagingData(largeLoad,page,pageSize);
                            });
                        }
                    }, 100);
                };
$scope.mySearch = function(){
                    console.log($scope.searchText);
                    $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage,$scope.searchText);
                }

Bye

NB its a fake request against a json file just to make the example.

Update: I'm using ng-grid-1.3.2

Whisher
  • 31,320
  • 32
  • 120
  • 201
  • Are you using the ng-grid it might be good to specify which version of the grid your using as well, some things like the row aggregation have changed pretty significantly over time. I'll show my current implementation with the ng-grid. – shaunhusain Sep 10 '13 at 14:41
  • I've updated my question with the version. – Whisher Sep 10 '13 at 14:43
  • Does the solution provided not work for some reason? – shaunhusain Sep 10 '13 at 15:06

1 Answers1

2

Basically to solve this problem I think you can use a solution similar to what I've done below where I'm just watching the property of the model for changes and firing a function to do the filtering on the data set at that point.

The HTML for the text input

<input type="text" placeholder="Type to filter" ng-model="gardenModel.externalFilterText"/>

The JavaScript that filters the data set (also included the part I had a watch on a service to update the data in the first place too or if the data is refreshed to reapply the filter).

//This function is called every time the data is updated from the service or the filter text changes
$scope.filterGardens = function(filterText) {
  //Basically everything in this function is custom filtering specific
  //to the data set I was looking at if you want something closer to the
  //real implementation you'll probably have to dig through the source (I believe they separated the search filter code into it's own file in the original project)

  //Creating a temporary array so changes don't cause a bunch of firing of watchers
  var tempToShow = [];

  //doing case insensitive search so lower case the filter text
  filterText = filterText.toLowerCase();

  //If the filter text is blank just use the whole data set
  if(!filterText || filterText == "")
  {
    $scope.gardenModel.shownGardens = $scope.gardenModel.gardens;
    return;
  }

  //step through each entry in the main list and add any gardens that match
  for (var i = 0; i < $scope.gardenModel.gardens.length; i++) {
    var curEntry = $scope.gardenModel.gardens[i];
    var curGarden = curEntry.curGarden;


    if(curGarden["Garden Name"] && curGarden["Garden Name"].answer.toString().toLowerCase().indexOf(filterText)!=-1)
      tempToShow.push(curEntry);
    else if(curGarden["Address"] && curGarden["Address"].answer.toString().toLowerCase().indexOf(filterText)!=-1)
      tempToShow.push(curEntry);
    else if(curGarden["Ownership"] && curGarden["Ownership"].answer.toString().toLowerCase().indexOf(filterText)!=-1)
      tempToShow.push(curEntry);
    else if(curGarden.gardenId && curGarden.gardenId == filterText)
      tempToShow.push(curEntry);
  };
  $scope.gardenModel.shownGardens = tempToShow;
}

//Watch for any changes to the filter text (this is bound to the input in the HTML)
$scope.$watch('gardenModel.externalFilterText', function(value) {
  $scope.filterGardens(value);
});

//Watch for any changes on the service (this way if addition/edit are made and
//refresh happens in the service things stay up to date in this view, and the filter stays)
$scope.$watch( function () { return gardenService.gardens; }, function ( gardens ) {
  $scope.gardenModel.gardens = gardens;
  $scope.filterGardens($scope.gardenModel.externalFilterText);
});

Edit Cleaned up the code formatting a bit and added some comments.

shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • Thanks, just a question the myData are $scope.gardenModel.gardens ? – Whisher Sep 10 '13 at 15:24
  • sorry to bother you again you can spend two words :) about $scope.$watch( function () { return gardenService.gardens; }, function ( gardens ) { // handle it here. e.g.: $scope.gardenModel.gardens = gardens; $scope.filterGardens($scope.gardenModel.externalFilterText); }); thx again for your time. – Whisher Sep 10 '13 at 15:26
  • Yup I created a gardenModel object that I stored all the stuff for that controller in, the gardens is just an array of all the gardens, then the shownGardens is what I'm using for the data of my grid. The watch expression is so if the data stored in the service changes then the data in the view is updated. This way I don't need to know what triggered the change just that something caused the data to need a refresh (something was added or edited). – shaunhusain Sep 10 '13 at 15:26
  • I've made a more simple example http://plnkr.co/edit/Uz9yl8rHf7oXCAttsS7P take a look I've got $scope.$watch( function () { return $scope.myData; }, function ( value ) { if(!$scope.searchText || $scope.searchText == ""){ $scope.myData = value; return; } /* THis give me an error 10 $digest() iterations reached. Aborting! */ //$scope.filterData($scope.searchText); console.log($scope.searchText); }); – Whisher Sep 10 '13 at 16:27
  • Yeah so I just made two arrays to keep this easy on myself. I have one array shownGardens that I use for display then there's the services.gardens which is the original array I watch (this way I don't change the one that I'm watching from the service getting into this infinite loop business, I'll see if I can tweak your plunkr) – shaunhusain Sep 10 '13 at 16:31
  • sure you absolutely can :) – Whisher Sep 10 '13 at 16:36
  • @Whisher hey sorry to tell ya I have to throw in the towel on this one... feel free to redact the accepted answer I got past the issue you were running into but for some reason it's telling me searchText is an array but I can't find anywhere that would happen: http://plnkr.co/edit/rU4Ouq8cd0BM1jTmLLV5?p=preview – shaunhusain Sep 10 '13 at 16:52
  • In this way $scope.$watch( function () { return $scope.myData; }, function ( value ) {if(!$scope.searchText || $scope.searchText == ""){$scope.myData = value; return; } $scope.filterData($scope.searchText); console.log(value); //console.log(valueb); //$scope.myData = value; },true); I didn't get errors anymore http://stackoverflow.com/questions/18814449/angularjs-10-digest-iterations-reached. I've updated the pliunkr.The problem is that I use the backspade the grid didn't get updated :( – Whisher Sep 15 '13 at 18:47
  • 1
    I've updated the plunker again I've added $scope.origData and it seems to works :) – Whisher Sep 15 '13 at 20:14