1

I was able to purely implement a grid from a JSON object - AngularJS ng-repeat to populate grid from array. However, due to the nature of the added indices, being able to create a search bar with ng-model and filter:search does not work - it only can search for the first in each table row.

var test= angular.module("app", []);

test.controller("appControl", function($scope, $http) {
 $http.get("http://www.w3schools.com/angular/customers.php")
  .success(function (response) {
   $scope.data = response.records;
  }
 );
    $scope.getFiltered= function(obj, idx){
       //Set a property on the item being repeated with its actual index
       //return true only for every 1st item in 5 items
       return !((obj._index = idx) % 5);
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<body ng-app='app' ng-controller='appControl'>
    <input type='text' ng-model='search.Country' />
    <table>
        <tr ng-repeat="work in data | filter:getFiltered | filter:search">
            <td>{{work.Country}}</td>
            <td>{{data[work._index+1].Country}}</td>
            <td>{{data[work._index+2].Country}}</td>
            <td>{{data[work._index+3].Country}}</td>
            <td>{{data[work._index+4].Country}}</td>
        </tr>
    </table>
</body>

The length of data may or not cause the table to look like a perfect rectangle.

I'm working on making a function to split up the array and create the grid in JavaScript itself, but I'm still not sure how to filter it via search input.

Second try (with the mentioned function, but no filters at all yet...):

var test= angular.module("app", []);

function createGrid(arr, width) {
    newArr = [];
    reps = Math.ceil(arr.length/width) * width;
    k = 0;
    for (var i = 0; i < reps/width; i++) {
        newArr[i] = [];
    }
    
    for (var i = 0; i < reps/width; i++) {
        for (var j = 0; j < width; j++) {
            (arr[k]) ? newArr[i][j] = arr[k] : newArr[i][j] = "";
            //console.log(i, j, arr[k]);
            k++;
        }
    }
    
    return newArr;
}

test.controller("appControl", function($scope, $http) {
    $scope.gridWidth = 4;
 $http.get("http://www.w3schools.com/angular/customers.php")
  .success(function (response) {
   $scope.data = createGrid(Object.keys(response.records).map(function(k) { return response.records[k] }), $scope.gridWidth);
  }
 );
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<body ng-app='app' ng-controller='appControl'>
    <input type='text' ng-model='search.Country' />
    <table>
        <tr ng-repeat="row in data">
            <td ng-repeat='work in row'>
                {{ work.Country }}
            </td>
        </tr>
    </table>
</body>
Community
  • 1
  • 1
Firedrake969
  • 763
  • 8
  • 22

2 Answers2

3

You could try something like this:

var test= angular.module("app", []);
  
test.controller("appControl", function($scope, $http) {

 $http.get("http://www.w3schools.com/angular/customers.php")
  .success(function (response) {
          $scope.data = response.records;
                 $scope.filteredData= response.records;
  }
 );

     $scope.$watch('search', function () {

      var array=[];
      for(var i in $scope.data)
      {
          if($scope.search==undefined || $scope.search.length == 0 ||  ($scope.data[i].Country!=undefined&&$scope.data[i].Country.toUpperCase().startsWith($scope.search.toUpperCase()))){
             array.push($scope.data[i]);
          }
      }
      $scope.filteredData=array;
    });

    $scope.getFiltered= function(obj, idx){
       //Set a property on the item being repeated with its actual index
       //return true only for every 1st item in 3 items
       return !((obj._index = idx) % 5);
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<body ng-app='app' ng-controller='appControl'>
    <input type='text' ng-model='search' />
    <table>
        <tr ng-repeat="work in filteredData | filter:getFiltered | filter:search">
            <td>{{work.Country}}</td>
            <td ng-show="filteredData[work._index+1]">{{filteredData[work._index+1].Country}}</td>
            <td ng-show="filteredData[work._index+2]">{{filteredData[work._index+2].Country}}</td>
            <td ng-show="filteredData[work._index+3]">{{filteredData[work._index+3].Country}}</td>
            <td ng-show="filteredData[work._index+4]">{{filteredData[work._index+4].Country}}</td>
        </tr>
    </table>
</body>
Rendy Del Rosario
  • 1,277
  • 10
  • 20
  • The thing is that I'd only want the results saying the search, and not the whole row (http://prntscr.com/6yyra2) – Firedrake969 Apr 27 '15 at 23:27
  • Thank you! I've accepted it with a minor change - I replaced startsWith() with includes(). – Firedrake969 Apr 28 '15 at 01:07
  • There are still some flaws in this answer, as the filter:search is not needed for example. also checking for a variable to be undefined shouldn't be done against `undefined`but against the `typeof 'undefined'`and so on. It looks like you just copied parts of my answer without understanding them :( – Rias Apr 28 '15 at 09:36
  • His answer was actually first, sorry. Also, yours has a few issues that this one doesn't - however, I did upvote yours, as I can only accept one answer. – Firedrake969 Apr 28 '15 at 15:51
2

You could prefilter the items after a successful Ajax call and every time your model search changes.

  1. Save the previously filtered items into $scope.workers.
  2. Use $scope.$watch to watch for changes in the model search
  3. Use the function searched(data) to filter for the entries that have characters given in the search field using the indexOf method. If the filter is empty, also show every item (typeof $scope.search == 'undefined').
  4. If you want the search be case insensitive, transform searchand the Country .toLowerCase(), when using .indexOf()

Then you will only need one Angular filter $scope.getFiltered(), which makes sure, that the entries are in rows of five.

var test= angular.module("app", []);

test.controller("appControl", function($scope, $http) {
 $http.get("http://www.w3schools.com/angular/customers.php")
  .success(function (response) {
   $scope.data = response.records;
            $scope.workers = $scope.searched($scope.data);
  }
 );

    $scope.getFiltered= function(obj, idx){
       //Set a property on the item being repeated with its actual index
       //return true only for every 1st item in 5 items
       return !((obj._index = idx) % 5);
    };
  
    $scope.searched = function (data) {
      var array = [];
      var max = 0;
      
      if (typeof data === 'object') {
        max = data.length;
      }
      
      for (var i = 0; i < max; i += 1) {
        if (typeof $scope.search == 'undefined' || data[i].Country.toLowerCase().indexOf($scope.search.toLowerCase()) != -1) {
          array.push(data[i]);
        }
      }
      
      return array;
    
    };

    $scope.$watch('search', function () {
      $scope.workers = $scope.searched($scope.data);
    })
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<body ng-app='app' ng-controller='appControl'>
    <input type='text' ng-model='search' />
    <table>
        <tr ng-repeat="work in workers | filter:getFiltered">
            <td>{{ work.Country }}</td>
            <td>{{ workers[$index+1].Country }}</td>
            <td>{{ workers[$index+2].Country }}</td>
            <td>{{ workers[$index+3].Country }}</td>
            <td>{{ workers[$index+4].Country }}</td>
        </tr>
    </table>
</body>
Rias
  • 1,956
  • 22
  • 33