prozaek.prozaek prozaek.prozaek - 1 month ago 31
Javascript Question

How make filter for object?

Please help fix the script.

PLUNKER

I make newsfeed. Data stored in json-file. I output dataitems in Repeat.

html:

<input class="filter" type="text" ng-model="searchPhrase" placeholder="Фильтр по заголовку">

<div class="news-list" ng-if="!detailsShow">
<h2 class="md-display-1 ng-binding">список чего-то из json-файла</h2>
<input class="filter" type="text" ng-model="searchPhrase" placeholder="Фильтр по заголовку">

<ul class="news-list-inner">
<li class="news-item" ng-repeat="(key, val) in news | filter:searchPhrase" ng-click="openDetails(key)">
<div class="poster" style="background-image: url('{{newsImagesStoragepath}}{{val.poster}}');"></div>
<div class="title">{{val.title}}</div>
<div class="description">{{val.description | cutText:100}}</div>
</li>
</ul>
</div>


angular-controller:

function($rootScope, $scope, $timeout, $http) {
$scope.newsImagesStoragepath = '/';
$scope.detailsShow = false;

$scope.getNews = function() {
$http.get('news.json')
.then(function successCallback(resp){
$scope.news = resp.data.values;
}, function errorCallback(resp) {
console.log('error', resp);
});
};

$scope.getNews();
}


json(fragment):

{
"headers": {
"title":{"title":"Заголовок","type":"text"},
"description":{"title":"Описание","type":"text"},
"poster":{"title":"Изображение","type":"file"}
},
"values":{
"id1": {"title":"Lorem ipsum dolor sit.", "poster": "1.jpg", "description": "Lorem ipsum dolor sit amet, re."},
"id2": {"title":"Sequi alias, cumque at.", "poster": "3.jpg", "description": "Architecto, placeat! C"},


I need add filter by phrase for titles. But console display follow error message:


angular.js:13920 Error: [filter:notarray] Expected array but received:

Answer

angular.js:13920 Error: [filter:notarray] Expected array but received:

This error occurs when filter is not used with an array. To filter an object by the value of its properties you can create your own custom filter.

In your case, you can create filter like this :

JS:

.filter('custom', function() {
  return function(input, search) {
    console.log(input, search);
    if (!input) return input;
    if (!search) return input;
    var expected = ('' + search).toLowerCase();
    var result = {};
    angular.forEach(input, function(value, key) {
      console.log(value);
      var actual = ('' + value.title).toLowerCase();
      if (actual.indexOf(expected) !== -1) {
        result[key] = value;
      }
    });
    return result;
  }
});

HTML:

ng-repeat="(key, val) in news |custom:searchPhrase"

This filter will filter by phrase for titles as your requirement. Plunker Link(I have made some changes in your code)