Filter PHP list with angularJS

I am trying to create a blog page and I chose WordPress over AngularJS so Google can index the page ( or at least that’s what i think it works). So for now I have a list which looks like this

<ul>
    <li id="1">
        <h2>My first Post</h2>
        <p>The Message...</p>
    </li>
    <li id="2">
        <h2>My second Post</h2>
        <p>The Message...</p>
    </li>
    <li id="3">
        <h2>My third Post</h2>
        <p>The Message...</p>
    </li>
</ul>

but PHP is pretty static so I want to create a angular filter to filter posts by title, but I don’t really know how to do this.

Read More

I was thinking to create a hide class for <li> items and somehow if a post should be deleted because of the filter, to add the hide class to it. I try to mix this angular so I can have a dynamic search instad loading the page again after searching.

Related posts

Leave a Reply

3 comments

  1. Considering you don’t have a service that will return only the JSON formatted items, the best approach would be creating a directive that remove the li, parse their contents to an object and use ng-repeat in a template. Something like this:

    var app = angular.module('plunker', []);
    
    app.directive('filtered', function() {
      return {
        scope: {
          criteria: '=filtered'
        },
        compile: function(elm, attr) {
          var entries = [];
    
          elm.find('li').each(function(index, item) {
            var entry;
    
            $item = angular.element(item);
    
            entries.push({
                  id: $item.attr('id'),
              title: $item.find('h2').text(),
              body: $item.find('p').text()
            });
          }).remove();
    
          elm.append(
            '<li ng-repeat="entry in entries | filter:{title: criteria}" id={{entry.id}}>' +
              '<h2>{{entry.title}}</h2>' +
              '<p>{{entry.body}}</p>' +
            '</li>'
          );
    
          return function(scope) {
            scope.entries = entries;
          };
        }
      };
    });
    

    And in your HTML you just decorate the list with the directive:

    <input ng-model="userCriteria">
    
    <ul filtered="userCriteria">
      <li id="1">
        <h2>My first Post</h2>
        <p>The Message...</p>
      </li>
      <li id="2">
        <h2>My second Post</h2>
        <p>The Message 2...</p>
      </li>
      <li id="3">
        <h2>My third Post</h2>
        <p>The Message 3...</p>
      </li>
    </ul>
    

    I’ve put together a Plnkr here. Go ahead and change the HTML list and it will automatically include that items.

  2. You could create a directive to wrap the html content you receive from php, pass the filter term and which element of the list you want to check).

    Here is a plunker: http://plnkr.co/edit/Bv2opi5CHfJa0pQyFrBc?p=preview

    (this require jquery to hide and show, but you can use css({‘display’:’none|block’}) too)

    (maybe you could modify the directive to apply the filter term to ignore the case of the words)

    app.js

    var app = angular.module('plunker', []);
    
    app.controller('MainCtrl', function($scope) {
        $scope.model = {
            filter: ''
        };
    });
    
    app.directive('myHtmlFilter', [function() {
        return {
            restrict: 'A',
            scope: {
              filter: '=myHtmlFilter',
              element: '@'
            },
            link: function(scope, elem, attrs) {
              scope.$watch('filter', function(newval, oldval) {
                elem
                  .find('ul>li')
                      .hide()
                      .find(scope.element)
                      .filter(':contains("'+scope.filter+'")')
                   .parent()
                      .show();
              })
            }
        }
    }]);
    

    index.html

    <input type="text" ng-model="model.filter" />
    
    <div my-html-filter="model.filter" element="h2">
      <ul>
        <li id="1">
            <h2>My first Post</h2>
            <p>The Message...</p>
        </li>
        <li id="2">
            <h2>My second Post</h2>
            <p>The Message...</p>
        </li>
        <li id="3">
            <h2>My third Post</h2>
            <p>The Message...</p>
        </li>
      </ul>
    </div>
    

    Edit I updated the plunker with a more complete example than the code shown here.

  3. If you can have the JSON approach, then Angular automatically does that for you.

    Just go with a simple filter solution:

    <input ng-model="criteria"/>
    
    <ul>
      <li ng-repeat="entry in entries | filter:{title: criteria}" id="{{entry.id}}">
        <h2>{{entry.title}}</h2>
        <p>{{entry.body}}</p>
      </li>
    </ul>
    

    In your controller (or any JS with access to the container scope):

    app.controller('MainCtrl', function($scope) {
      $scope.criteria = "Title";
    
      $scope.entries = [
        {
          id: 1,
          title: 'My title',
          body: 'contents...'
        },
        {
          id: 2,
          title: 'The other content',
          body: 'contents...'
        },
        {
          id: 3,
          title: 'Another title',
          body: 'contents...'
        },
        {
          id: 4,
          title: 'Something completely different',
          body: 'contents...'
        }
      ];
    });
    

    You can even use $http service to retrieve the JSON file:

    app.controller('MainCtrl', function($scope) {
      $scope.criteria = "Title";
      $scope.entries = $http.get('path/to/entries.json');
    });