0

I'm creating an app using fake JSONplaceholder API. I'm displaying a list of posts and I want the ng-repeated post titles to link to the post view.

Here's the HTML:

    <body layout="column" ng-app="myApp" ng-cloak ng-controller="controller">
    <h1>{{apptitle}}</h1>
    <script type="text/ng-template" id="allposts.htm">
        <a href="#addpost">
    <button type="button" class="btn btn-primary addbtn" ng-model="singleModel" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
        Add a post
    </button>
</a>
        View
        <select ng-model="viewby" ng-change="setItemsPerPage(viewby)">
            <option>9</option>
            <option>18</option>
            <option>36</option>
            <option>100</option>
        </select>posts
        <div class="row" ng-repeat="collatedPostList in collatedPosts">
            <div class="onepost col-xs-4 box" ng-repeat="post in collatedPostList">
                 <div class="inner">
                <a href="#/posts/{{post.indexOf(post)}}">{{post.title}}</a>
                <p>{{post.body | limitTo: 60}}{{post.body.length < 20 ? '' : '...'}}</p>
            </div>
            </div>
        </div>
        <div class="text-center">
        <ul uib-pagination total-items="totalItems" ng-model="currentPage" class="pagination-sm"
            items-per-page="itemsPerPage" ng-change="pageChanged(currentPage)"></ul>
        </div>
    </script>
    <script type="text/ng-template" id="posts.htm">
  </script>
    <script type="text/ng-template" id="addpost.htm">
    <form ng-submit="addPost()" class="adding">
        <input id="titleadd" type="text" name="title" ng-model="newPost.title" placeholder="Add title">
        <br>
        <input id="textadd" type="text" name="body" ng-model="newPost.body" placeholder="Add some text">
        <br>
        <button type="submit" ng-click="addAlert(msg,'success')" class="btn btn-primary" id="submit" value="Submit">
        Post it
        </button>
        <a href="#allposts">
        <button type="button" class="btn btn-primary" >
            Go back to post list
        </button></a>
            <br>
        <uib-alert 
              ng-repeat="alert in alerts" 
              type="{{alert.type}}" 
              dismiss-on-timeout="5000" 
              close="alerts.splice($index, 1);">{{alert.msg}}
    </uib-alert>    </form>
  </script>
    <div ng-view></div>
    <script src="app.js"></script>
</body>

and JS:

Array.prototype.collate = function(collateSize) {
    var collatedList = [];

    if (collateSize <= 0) {
        return [];
    }
    angular.forEach(this, function(item, index) {
        if (index % collateSize === 0) {
            collatedList[Math.floor(index / collateSize)] = [item];
        } else {
            collatedList[Math.floor(index / collateSize)].push(item);
        }
    });

    return collatedList;
};

var myApp = angular.module('myApp', ['ngRoute', 'ui.bootstrap']);

myApp.config(function($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: 'allposts.htm',
        controller: 'PostsController'
    }).when('/posts', {
        templateUrl: 'posts.htm',
        controller: 'PostController'
    }).when('/addpost', {
        templateUrl: 'addpost.htm',
        controller: 'AddController'
    }).otherwise({
        redirectTo: '/'
    });
});

myApp.controller('PostsController', function($scope) {});

myApp.controller('PostController', function($scope) {});

myApp.controller('AddController', function($scope) {});


myApp.controller('controller', function($scope, $http) {
    $scope.apptitle = "My app";

    $http({
        method: 'GET',
        url: "http://jsonplaceholder.typicode.com/posts"
    }).then(function(response) {
        $scope.posts = response.data;
        $scope.viewby = 9;
        $scope.totalItems = $scope.posts.length;
        $scope.currentPage = 1;
        $scope.itemsPerPage = $scope.viewby;
        $scope.maxSize = 5;
        $scope.collatedPosts = getCollatedPosts($scope.posts);
        $scope.newPost = {};


    function getCollatedPosts(posts) {
        if (!posts) {
            return [];
        }

        var paginatedPosts = posts.slice((($scope.currentPage - 1) * $scope.itemsPerPage), (($scope.currentPage) * $scope.itemsPerPage));
        return paginatedPosts.collate(3);
    }

    $scope.setPage = function(pageNo) {
        $scope.currentPage = pageNo;
    };

    $scope.setItemsPerPage = function(num) {
        $scope.itemsPerPage = num;
        $scope.currentPage = 1; //reset to first page
        $scope.collatedPosts = getCollatedPosts($scope.posts);
    };

    $scope.pageChanged = function(currentPage) {
        $scope.currentPage = currentPage;
        $scope.collatedPosts = getCollatedPosts($scope.posts);
    };
        $scope.addPost = function(){
          $http.post("http://jsonplaceholder.typicode.com/posts",{
            title: $scope.newPost.title,
            body: $scope.newPost.body,
            usrId: 1
          })
          .success(function(data, status, headers, config){
            console.log(data);
            $scope.posts.push($scope.newPost);
            $scope.newPost = {};
          })
          .error(function(error, status, headers, config){
            console.log(error);
          });
    };});


    $scope.alerts = [];

    $scope.msg = "Well done! Your post was added";

    $scope.addAlert = function(msg, type) {
      $scope.alerts.push({
        msg: msg,
        type: type
      });
    };

});

My code is not working. There is 100 ng-repeated posts and I want each post title to link to the post view. Current code links every title to #/posts. I also tried <a href="#/posts/{{post.id}}">{{post.title}}</a>, but with no success. What is the correct way to do this?

You can see full code here:

4
  • doesn't work with that either Commented Sep 8, 2016 at 6:15
  • do I have to change something in the route provider? Commented Sep 8, 2016 at 6:16
  • 1
    inspect the repeated element and check the href value Commented Sep 8, 2016 at 6:24
  • I created a codepen: codepen.io/summerfreeze/pen/ORVQYz Commented Sep 8, 2016 at 6:52

2 Answers 2

1

You can debug the code by following way.

console.log(response.data) // will give you data in success http get

then

you can print those data in HTML by {{posts}}, if you get the data there, you're on the right track.

Please try my following snippet to link the posts

var myApp = angular.module('myApp', []);
myApp.controller('PostController', ['$scope','$http', function($scope, $http) {
  var root = 'http://jsonplaceholder.typicode.com';
  
  $http({
    method: 'GET',
    url: root+'/posts'
  }).then(function successCallback(response) {
     $scope.posts= response.data;
  }, function errorCallback(response) {
    
  });
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="PostController">
  <div ng-repeat="post in posts track by $index">
    <a ng-href="http://jsonplaceholder.typicode.com/posts/{{post.id}}">{{post.title}}</a> <br/>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

but you're getting the data directly from the API, I want it to be displayed as a view
Can you create jsfiddle to know the exact problem?
1

First i write your route provider like this :

myApp.config(function($stateProvider, $routeProvider) {
    $routeProvider.otherwise('/posts');

    $stateProvider.state('posts', {
      url: '/posts',
      templateUrl: 'allposts.htm',
      controller: 'PostsController'
    }).state('posts.detail', {
      url: '/:postId',
      templateUrl: 'posts.htm',
      controller: 'PostController'
    }).state('posts.add', {
      url: '/add',
      templateUrl: 'addpost.htm',
      controller: 'AddController'
    });
});

Then to create your link you can do :

<a ui-sref="posts.detail({postId: post.id})">{{ posts.title }}</a>

1 Comment

Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to: TypeError: $routeProvider.state is not a function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.