1

I've just started using angularjs and I'm trying to connect a wordpress back-end to an Angularjs front end.

this is my index.html

<!DOCTYPE html>
<html ng-app="applicazioneIndex">
<head>
<title>AngularJS GET request with PHP</title>
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular-sanitize.min.js"></script>
  <link data-require="bootstrap-css@2.3.2" data-semver="2.3.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" />
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.0/ui-bootstrap-tpls.min.js"></script>
  <script data-require="angular-resource@*" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular-resource.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
  <meta charset="UTF-8">
</head>

  <body >

 <div class="row">
    <div class="container">  
<div ng-controller="ApplicazioneController">
      <input type="text" ng-model="searchFilter" class="form-control">
    <table class="table table-hover">
      <thead>
        <tr>
          <th>{{currentPage}} di {{totalItems}} {{watchPage}}</th>
          <th>post_content</th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="post in filteredArticoli | filter:searchFilter">
          <td>{{post.title}}</td>
          <td><a ng-href="{{post.featured_image.source}}"><img ng-src="{{post.featured_image.attachment_meta.sizes.thumbnail.url}}"></a></td>
          <td ng-bind-html="post.excerpt"></td>

        </tr>
      </tbody>
    </table>



       <pagination boundary-links="true" 
          max-size="5"
          items-per-page="itemsPerPage"
          total-items="totalItems" 
          ng-model="currentPage" 
          ng-change="pageChanged(page)"></pagination>




</div>
</div>



 </div>
  </body>



</html>

and this is my script.js with angular code (I know it's all in one file and it's bad)

var req = new XMLHttpRequest();
var URL = "/wp-json/posts";
req.open('GET', URL, false);
req.send(null);
var maxpagine = req.getResponseHeader("X-WP-TotalPages");
var totarticoli = req.getResponseHeader("X-WP-Total");
var currentPage = '';
var newPage = '';


  var app = angular.module('applicazioneIndex', ['ui.bootstrap','ngSanitize','ngResource']);

  app.controller('ApplicazioneController', function ($scope, applicazioneFactory) {



applicazioneFactory.get({ id: 1 }, function(data) {
$scope.posts = data;
alert(posts);
});

    $scope.articoli = applicazioneFactory.query();

    $scope.itemsPerPage = 3;
    $scope.currentPage = 1;
    $scope.totalItems = totarticoli;

    $scope.articoli.$promise.then(function () {


    $scope.$watch('currentPage + itemsPerPage', function() {

        var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
        end = begin + $scope.itemsPerPage;
    $scope.filteredArticoli = $scope.articoli.slice(begin, end);

    });

  });

      $scope.$watch('currentPage', function(newPage){
    $scope.watchPage = newPage;
    alert(newPage);

  });  

});


app.factory('applicazioneFactory', function ($resource) {

  return $resource( "/wp-json/posts?page=" + currentPage);

});

Pagination is working perfectly, I get the values from a XMLHttpRequest, the bootstrap menu is populated, but I can't populate content with different JSON.

My goal is to load different JSON files using $currentPage value, changing while bootstrap pagination is working (for that purpose there is an alert to pop up currentPage value).

using $scope.$watch('currentPage', function(newPage) I can get currentPage value inside the controller

I've also a Plunker here http://plnkr.co/edit/hplfuBIOLDHUgUp6lU0A where I've put a static JSON file instead of the dynamic RESTful request url.

How can I put the $currentPage value inside app.factory?

2 Answers2

0

It will be easier when you load all of your posts and stores them into an $scope variable. And on this variable you can apply an filter. In AngularJS it is possible to create your custom filters.

Lets have a look in module documentation filter.

Example

angular.module('App.filters', []).filter('postFilter', [function () {
    return function (posts, startPost, endPost) {
        if (!angular.isUndefined(posts) && !angular.isUndefined(startPost) && !angular.isUndefined(endPost)) {
            var tempPosts = [];

            for(var i=startPost;i<endPost;i++){
                tempPosts.push(posts[i]);
            }

            return tempPosts;
        } else {
            return posts;
        }
    };
}]);

Normally it should be possible to control the number of given posts via REST-interface.

UPDATE

Okay I believe now what you want. You can add your own resource actions. Something like this:

app.factory('applicazioneFactory', ['$resource', function ($resource) {
    var url = '/wp-json/:action/';
    return $resource(url, {}, {
        getNextPosts: { params: {action: 'posts'}, method: 'GET', isArray: true },
    });
}]);

You can call this method like this:

applicazioneFactory.getNextPosts({'count': 5, 'page': 1, 'post_type': 'Category1'})
applicazioneFactory.getNextPosts({'count': 5, 'page': 1, 'post_type': 'Category2'})
applicazioneFactory.getNextPosts({'count': 5, 'page': 1, 'post_type': 'Category3'})

HTTP-Requests:

http://<yourhost>/wp-json/posts/?count=5&page=1&post_type=Category1 http://<yourhost>/wp-json/posts/?count=5&page=1&post_type=Category2 http://<yourhost>/wp-json/posts/?count=5&page=1&post_type=Category3

More information you will find in the documentation: ngResource

UPDATE 2

You don't need an variable inside your factory and it is no problem to use bootstrap pagination. Please show below I have an function pageChange() inside from your controllers $scope.

var app = angular.module('applicazioneIndex', ['ui.bootstrap','ngSanitize','ngResource']);

app.controller('ApplicazioneController', function ($scope, applicazioneFactory) {

    $scope.itemsPerPage = 3;
    $scope.currentPage = 1;
    $scope.totalItems = 0;

    $scope.pageChange = function(){
      applicazioneFactory.query({'count': $scope.itemsPerPage, 'page': $scope.currentPage}).$promise.then(function(data, status, headers, config){
      $scope.totalItems = headers["X-WP-Total"];
      $scope.filteredArticoli = data;
      });
    }
    // Init on page load
    $scope.pageChange();
});


app.factory('applicazioneFactory',  function ($resource) {
  return $resource('/wp-json/posts');
});

HTML-Snippet

<div class="row">
    <div class="container">  
        <div ng-controller="ApplicazioneController">
            <input type="text" ng-model="searchFilter" class="form-control">
                <table class="table table-hover">
                    <thead>
                        <th>{{currentPage}} di {{totalItems}} {{watchPage}}</th>
                        <th>post_content</th>
                    </thead>
                    <tbody>
                        <tr ng-repeat="post in filteredArticoli | filter:searchFilter">
                            <td>{{post.title}}</td>
                            <td><a ng-href="{{post.featured_image.source}}"><img ng-src="{{post.featured_image.attachment_meta.sizes.thumbnail.url}}"></a></td>
                            <td ng-bind-html="post.excerpt"></td>

                        </tr>
                    </tbody>
                </table>
        </div>
    </div>
</div>

<pagination boundary-links="true" max-size="5" items-per-page="itemsPerPage" total-items="totalItems" ng-model="currentPage" ng-change="pageChange()"></pagination>

Everytime you click on pagination the function pageChange() will be called and send the following HTTP-Requests:

http://<yourhost>/wp-json/posts/?page=1

Hope this will help you

Sven Schürmann
  • 602
  • 3
  • 4
  • I think loading all posts data together it should be avoidable because in the case of loading thousands of articles it should take too much loading time: splitting them in smaller json files it's useful. thnks anyway for your quick answer – Cristiano Zanca Oct 07 '14 at 16:56
  • I agree! My solution is okay for less post. Your REST-Interface should be capable of to control the number of given posts via parameterized HTTP-Requests. So you can load the required posts with click on pagination dynamically. Example for REST-Call: `http:///wp-json/posts/all?start=1&end=3` – Sven Schürmann Oct 08 '14 at 07:04
  • Dear Sven Pagination using [link](http://angular-ui.github.io/bootstrap/) is working perfectly. What is not working is to get `$currentPage` value inside app.factory, it is possible in the controller using $watch and I test it with an alert `$scope.$watch('currentPage', function(newPage){ $scope.watchPage = newPage; alert(newPage);` but I can't be able to get the same value even if using `$watch` – Cristiano Zanca Oct 08 '14 at 09:14
  • I try to make it in a Plunker [link](http://plnkr.co/edit/hplfuBIOLDHUgUp6lU0A?p=info) – Cristiano Zanca Oct 08 '14 at 09:29
  • Try this for registration your watcher: `$scope.$watch('[currentPage,itemsPerPage]', function () { ... }, true);` – Sven Schürmann Oct 08 '14 at 09:51
  • I've tried it, but declaring $scope other than $resource in factory is impossible. – Cristiano Zanca Oct 08 '14 at 10:07
  • Now the Plunker is working [link](http://plnkr.co/edit/hplfuBIOLDHUgUp6lU0A) , you can see what I mean about the working part. In that Plunker I changed the /wp-json/posts/ with a static JSON file – Cristiano Zanca Oct 08 '14 at 10:09
  • Dear Sven this is useful for single post. Every `wp-json/posts?page=` in Wordpress JSON API is a collection of 5 articles, every `$currentPage` ID should be equal to a link to 5 articles. if `$currentPage` could be attached to `wp-json/posts?page=` inside `app.factory` I could load content in Pagination, the goal is loading different JSON files with different collections of articles with their excerpt, like in the usual Wordpress homepage. – Cristiano Zanca Oct 08 '14 at 12:04
  • I don't see the problem... You can add more resource actions for other collections of articles. You don't typically use $scope inside a factory, service or provider. I have shown in WP JSON API and you can get all by appending GET-Parameters.Do you load the article from different WP systems? If yes you should better use `$http` instead of `$resource`. – Sven Schürmann Oct 08 '14 at 13:03
  • It's my fault, I don't explain myself very well. What is the idea: intercepting the pagination value $currentPage value as I did with $watch.scope/alert() . I don't want to use scope, I want to intercept the pagination value so that it will be attached to `wp-json/posts?page=` . Using customized pagination system, not bootstrap's `http://angular-ui.github.io/bootstrap/`, maybe your ideas could be usable. doing test including `var currentPage = 2;` inside the app.factory it obviously work. If is impossible to include any kind of var value inside an angularjs factory my idea is to be changed. – Cristiano Zanca Oct 08 '14 at 16:34
0

Thanks to this article: How to load json into my angular.js ng-model?

I've found the solutions: Delete the useless app.factory, load all data in controller and rotate the JSON using currentPage change from bootstrap pagination.

This is the working script.js code:

var req = new XMLHttpRequest();
var URL = "/wp-json/posts";
req.open('GET', URL, false);
req.send(null);
var maxpagine = req.getResponseHeader("X-WP-TotalPages");
var totarticoli = req.getResponseHeader("X-WP-Total");
var currentPage = '';
var newPage = '';


var app = angular.module('applicazioneIndex', ['ui.bootstrap','ngSanitize','ngResource']);


app.controller('ApplicazioneController', function($scope, $http) {
    $scope.itemsPerPage = 5;
    $scope.currentPage = 1;
    $scope.totalItems = totarticoli;

$scope.$watch('currentPage', function(newPage){
    $scope.watchPage = newPage;


  $http.get('/wp-json/posts?page=' + newPage)
       .then(function(res){
          $scope.filteredArticoli = res.data; 
$scope.$watch('currentPage + itemsPerPage', function() {

        var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
        end = begin + $scope.itemsPerPage;
    $scope.filteredArticoli = $scope.articoli.slice(begin, end);

      });

    });

  });  

});

Many thanks to Sven Schürmann that helped me in looking for different directions.

Community
  • 1
  • 1