2

first and foremost, this is my first encouter with Angular.

What I am aiming to achieve is, I have a list of notifications, that I somehow must limit with limitTo, so the elements are limited to three and after I click the button, the rest should load up.

What I dont understand how to do:

  • set up the "view" and how to apply ng-repeat
  • load the JSON data that I have set up and somehow parse it as pure HTML from the *json into the view
  • after everything goes well, use limitTo so I Can limit the items to 3 from the start and after I click the button, I want the rest to load under.

I request assistance, this is as far as I've come.

Sample code because SO requires it:

var app = angular.module('notifyApp', []);

app.controller('mainController', function($scope, $http) {

$http({
    method: 'GET',
    url: 'notifications.json'
}).success(function(){
    console.log('success');
}).error(function(){
    console.log('error');
});

$scope.loadmore = true;
});

Here is a Plunker

Thank You in advance!

1
  • Have you completed the tutorial at the angularjs site? It pretty much demonstrates how to do all of this, including how to use ngAnimate. Commented May 16, 2016 at 20:13

7 Answers 7

1

Your plunker has a couple of errors.

First of all, your ng-app in index.html should be notifyApp, since that's what you've set in your script.js - var app = angular.module('notifyApp', []);

Secondly: you have to assign your notifications to $scope.notifications in your success function.

$http({
    method: 'GET',
    url: 'notifications.json'
}).then(function(res){
    $scope.notifications = res;
});

After that you should already see the first 3 elements.

Last thing you need is to remove notifications = !notifications from the load more button's ng-click attr.

Modified Plunker here.

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

1 Comment

This clears things out. This is close to what I tried to do earlier, but in this case it works. Thank You very much!
1

Setting up the view and using ng-repeat.

You'll want to store the notifications somewhere (probably an array) and then use ng-repeat="data in yourArray" in your html file within a tag (div for example). You can then apply filters to it if you want to show specific notifications. In your case, you want to initially show 3 and then move onto the rest if a button is clicked. You could create a separate array that stores the first 3 notifications and and another that contains the whole array and use ng-if in your tag to display the results.

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

myApp.controller('notificationController', ['$scope',
  function($scope) {
    $scope.buttonNotClicked = true;

    $scope.fullArray = [item1, item2, item3, item4, item5];
    $scope.partialArray = [fullArray[0], fullArray[1], fullArray[2]];


    function onButtonClick() {
      $scope.buttonNotClicked = false;
    }
  }
]);
<div ng-if="buttonNotClicked">
  <div ng-repeat="data in partialArray"></div>
</div>

<div ng-if="!buttonNotClicked">
  <div ng-repeat="data in fullArray"></div>
</div>

How to use parameters within the filter in AngularJS?

Comments

1

So the first step is that on the success callback you should save then returning data somewhere in your scope, like:

.success(function (data) {

   $scope.myList = data;

   $scope.myListLimit = 3; // lets also set a limit for our list
}

Then, you can write your view as descendant of the element that points to the ng-controller directive:

<div ng-controller="mainController">
  <ul ng-repeat="item in myList | limitTo: myListLimit">
    <li>{{item}}</li>
  </ul>
  <button type="button" ng-show="anyResultsPending()" ng-click="showMoreResults()">Show more results</button>
</div>

After that your list should be shown with 3 results, and to be able to show more as a result of the user interaction, we create a new method on the controller:

$scope.showMoreResults = function () {

   $scope.myListLimit += 3;
}

// this is to hide the "show more results" button after the all items was shown
$scope.anyResultsPending = function () {

   return $scope.myList && $scope.myListLimit < $scope.myList.length; 
}

Comments

1

Here's a solution that does what some other answers don't provide:

  • Animation
  • Loads objects directly from your JSON using an angular factory and promises
  • Limits to 3 items and loads the rest on a button click

JavaScript:

(function () {
    "use strict";

    var module = angular.module('app', ['ngAnimate']);

    module.factory('NotificationsService', ['$http', function ($http) {
        return {
            fetch: function () {
                return $http.get('notifications.json').then(function (response) {
                    return response.data
                });
            }
        };
    }]);

    module.controller('Controller', ['$scope', '$filter', 'NotificationsService', function ($scope, $filter, NotificationsService) {
        $scope.notifications = [];
        $scope.limit = 3;
        $scope.allLoaded = false;

        NotificationsService.fetch().then(function (data) {
            $scope.notifications = data;
        });

        $scope.loadAll = function () {
            $scope.limit = $scope.notifications.length;
            $scope.allLoaded = true;
        };
    }]);
})();

Html/CSS

<!doctype html>
<html ng-app="app">

<head>
    <title>ng-limit</title>

    <style>
        .my-repeat-animation.ng-enter,
        .my-repeat-animation.ng-leave,
        .my-repeat-animation.ng-move {
            -webkit-transition: 0.5s linear all;
            transition: 0.5s linear all;
            position: relative;
        }

        .my-repeat-animation.ng-enter {
            top: -20px;
            opacity: 0;
        }

        .my-repeat-animation.ng-enter.ng-enter-active {
            top: 0;
            opacity: 1;
        }

        .my-repeat-animation.ng-leave {
            top: 0;
            opacity: 1;
        }

        .my-repeat-animation.ng-leave.ng-leave-active {
            top: -20px;
            opacity: 0;
        }

        .my-repeat-animation.ng-move {
            opacity: 0.5;
        }

        .my-repeat-animation.ng-move.ng-move-active {
            opacity: 1;
        }
    </style>

    <script src="node_modules/angular/angular.js"></script>
    <script src="node_modules/angular-animate/angular-animate.js"></script>
    <script src="app.js"></script>
</head>

<body ng-controller="Controller">
    <button ng-show="!allLoaded" ng-click="loadAll()">Load all</button>
    <div ng-repeat="notification in notifications | limitTo:limit" class="my-repeat-animation">
        <div>
            <h4>Notification: {{$index+1}}</h4>
            <div>
                Avatar: {{notification.avatar}}
            </div>
            <div>
                Type: {{notification.type}}
            </div>
            <div>
                Name: {{notification.userName}}
            </div>
            <div>
                Action: {{notification.userAction}}
            </div>
            <div>
                Target: {{notification.targetObject}}
            </div>
        </div>
    </div>
</body>

</html>

Comments

1

In addition, as explained in AngularJS : Insert HTML into view , when using HTML contained in JSON, you need to Sanitize. Use this module:

<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>

In your JS, I was surprised, it seems to be as simple as adding a dependency:

  var ricksiteControllers = angular.module('ricksiteControllers', ["ngSanitize"]);

  ricksiteControllers.controller('PagesCtrl', ['$scope', 'Page',
          function($scope, Page) {
              $scope.pages = Page.query();
  }]);

And my services.js has the angular-resource code:

var ricksiteServices = angular.module('ricksiteServices', ['ngResource']);

ricksiteServices.factory('Page', ['$resource',
  function($resource){
    return $resource('pages/:pageId.json', {}, {
      query: {method:'GET', params:{pageId:'pages'}, isArray:true}
    });
  }]);
// actually, the pageID parameter has only one value, only the default 'pages' is used.

5 Comments

I tried using it earlier, but I didn't got much success with it. What do I need to do in order for it to work? Add it as a dependancy in the module , [ ] ?
The answer is now updated to show the JS. Suspiciously simple.
In my case: var app = angular.module('notifications', ["ngSanitize"]); followed by the second .controller snippet , but doesn't seem to work. Where did I went terribly wrong?
Is that code in your plnker? I did not see it. Maybe the diff is in my use of services, as will be added to the JS in a moment.
I wrote this code while looking at the tutorial for ng 1.5
0

I've got a solution. Try it in your plnkr.

Note how I've hardcoded $scope.notifications. You'll want to retrieve the actual data - can't figure out how to do it in plnkr. When you do retrieve the JSON, you will have to trust the data like so:

var app = angular.module('notifications', []);
app.controller('mainController', function($scope, $http, $sce) {
   $http({
        method: 'GET',
        url: 'notifications.json'
    }).success(function(data){
        console.log('success');
        $scope.notifications = data;
        for (var i=0; i<$scope.notifications.length; i++){
             $scope.notifications[i].userAction = $sce.trustAsHtml($scope.notifications[i].userAction)
        }
    }).error(function(data){
        console.log('error');
    });
    $scope.myLimit = 3;

    $scope.loadmore = true;
});

EDIT because perhaps explanations are due. Here are the changes I made:

  • Angular Module had an error (wrong name) so I changed the first line of JS.
  • $scope.notifications must be declared in the JS.
  • Added $scope.myLimit so we can modify this variable for limitTo
  • In ng-click, removed notifications = !notifications, added myLimit = notifications.length so it can show all results.
  • Finally, added ng-bind-html instead of {{notification.userAction}} so it can be displayed as HTML.

JS:

var app = angular.module('notifications', []);

app.controller('mainController', function($scope, $http) {

$http({
    method: 'GET',
    url: 'notifications.json'
}).success(function(){
    console.log('success');
}).error(function(){
    console.log('error');
});

$scope.notifications = [
{
    "avatar" : "images/otherUser.png",
    "type" : "",
    "userName" : "Ivana Stankova",
    "userAction" : "<span class=\"heart\">&#10084;</span>&nbsp;your photo",
    "targetObject" : "images/targetPhoto.jpg"
},
{
    "avatar" : "images/otherUser2.png",
    "type" : "",
    "userName" : "Ivana Stankova",
    "userAction" : "<span class=\"heart\">&#10084;</span>&nbsp;your photo",
    "targetObject" : "images/targetPhoto.jpg"
},
{
    "avatar" : "images/otherUser4.png",
    "type" : "checkedIn",
    "userName" : "Dave Peters",
    "userAction" : "Checked in<br/><a href=\"#\">962 Grant Street Victoria</a>",
    "targetObject" : "images/place.jpg"
},
{
    "avatar" : "images/otherUser4.png",
    "type" : "commented",
    "userName" : "Dave Peters",
    "userAction" : "Commented on <a href=\"#\">your post</a><p>Hey guys,&nbsp8 o’clock? Let’s get some food first? How<br/>about that fancy restaurant we wanted to try for...</p>",
    "targetObject" : "images/targetPhoto.jpg"
},
{
    "avatar" : "images/otherUser.png",
    "type" : "",
    "userName" : "Ivana Stankova",
    "userAction" : "<span class=\"heart\">&#10084;</span>&nbsp;your photo",
    "targetObject" : "images/targetPhoto.jpg"
},
{
    "avatar" : "images/otherUser.png",
    "type" : "",
    "userName" : "Ivana Stankova",
    "userAction" : "<span class=\"heart\">&#10084;</span>&nbsp;your photo",
    "targetObject" : "images/targetPhoto.jpg"
},
{
    "avatar" : "images/otherUser4.png",
    "type" : "",
    "userName" : "Dave Peters",
    "userAction" : "<a href=\"#\">Made a new post.</a>",
    "targetObject" : "images/targetPhoto.jpg"
},
{
    "avatar" : "images/otherUser.png",
    "type" : "",
    "userName" : "Ivana Stankova",
    "userAction" : "Started following you.",
    "targetObject" : ""
},
{
    "avatar" : "images/fivePeople.png",
    "type" : "",
    "userName" : "",
    "userAction" : "Five people Started following You.",
    "targetObject" : ""
}
]

$scope.myLimit = 3;

    $scope.loadmore = true;
});

Index.html

<!DOCTYPE html>
<html lang="en" ng-app="notifications">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>App</title>
    <link rel="stylesheet" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
    <script src="script.js"></script>
</head>
<body class="container" ng-controller="mainController">
    <header>
        <a id="logo" href="www.google.com"><img src="images/logo.png" alt="logo"></a>
        <nav id="menu">
            <ul>
                <li><a href="#"><img src="images/bell.png" alt="bell icon"></a></li>
                <li>
                    <a href="#">
                        <img src="images/message.png" alt="message icon">
                        <div id="nCount">22</div>
                    </a>
                </li>
                <li><a href="#"><img src="images/profilePic.png" alt="girl profile pic"></a></li>
            </ul>
        </nav>
    </header>
    <main>
        <div class="wrapper">
            <div id="list">
                <h1>My notifications</h1>
                <ul id="mainList" ng-show="notifications" class="slideInDown" ng-init="limit = myLimit">
                    <li ng-repeat="notification in notifications | limitTo: limit">
                        <figure>
                            <img src="{{notification.avatar}}" alt="other user photo">
                        </figure>

                        <div class="infoLine {{notification.type}}">
                            <a class="userName" href="#">{{notification.userName}}</a>
                            &nbsp;<span ng-bind-html="notification.userAction"></span>
                        </div>

                        <div class="whenWhat">
                            <span>
                                <img src="images/clock.png" alt="clock illustration">
                                2m
                            </span>
                            <img src="{{notification.targetObject}}" alt="photo">
                        </div>
                    </li>
                </ul>
            </div>
            <a id="loadMore" href="#" ng-show="loadmore" ng-click=" loadmore = false ; limit = notifications.length; myLimit = notifications.length" ng-class="{ active: notifications }" >Load More</a>
        </div>
    </main>
</body>
</html>

10 Comments

Someone downvoted another solution as well. As a tradition I give an upvote to all participants. Wasn't me.
@chakeda My wild guess would be other solutions has better explanations, more details.
@Sqnkov See my edited answer. When you get the JSON from say, an API, you will have to $sce.trustAsHtml the data. I'd recommend creating a new question for the ng-animate.
@Sqnkov Edited again. The main edit up top should work copy pasted into script.js.
@Sqnkov Hmm are you getting an error in the console?
|
0

First of all, you should use then() promisse instead success() and error(). This is the current way that promisses should be used.

You can limit your nrRepeat looping using ´limitTo=val´ in your ng-repeat attribute.

I made a snippet to show you a solution for your problem:

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

myApp.controller('myAppController', ['$scope', function($scope){
  $scope.defaultLimit = 3; // the default limit
  $scope.list = ['item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6', 'item 7'];
  $scope.showAll = function(){
    $scope.defaultLimit = $scope.list.length; // show all reccords
  }  
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="myAppController">
    <ul>
      <li ng-repeat="item in list | limitTo:defaultLimit">{{item}}</li>
    </ul>
    <button ng-click="showAll()" type="button">Show all</button>
  </div>
</div>

3 Comments

So you are creating a scope, which is assigned to the json list and you append "length" to it, that is another way to do it. Mine was unecessary complex right? I don't fully understand it though, I found it somewhere in Google.
I wouldn't say yours was unnecessary complex, rather a bit buggy. It's more like a matter of preference if anything.
The point here is the ´$scope.defaultLimit´ variable that is used to limit the ng-repeat. Its default value is 3 as you want. what I do is change this variable assignin the array length to it, so your limit will be the entire array.

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.