Display more items when more link selected using Angularjs - angularjs

I am trying to display list of items, when I click more link it should display 10 more items in the list.
Here is my current code:
<div ng-repeat="items in itemList()">
{{items.name}}
</div>
and my controller is:
$scope.itemsList = function(){
return service.getItemList();
}
How do I add more link under the items, display 10 more items when I click 'more'

The easiest way would be to use the limitTo filter and use a button with ngModel to change the value that is limited. Documentation: https://docs.angularjs.org/api/ng/filter/limitTo
<div ng-repeat="items in itemList() | limitTo: displayNum">
{{items.name}}
</div>
<button ng-click="increaseBy(10)">Show More</button>
Controller Function:
$scope.displayNum = 10;
$scope.increaseBy = function(num) {
$scope.displayNum +=num;
}

Related

How can I add a style to specific items in my ng-repeat list?

I am using Ionic which is using Angular.js
My html page has a ng-init which calls a function from my controller. the function hits a service which goes to the database to retrieve all the songs.
$scope.getAllSongs = function(){
songService.getAllSongs()
.success(function(data){
//the data is an array of songs
//songs get organize by being pushed to other arrays the html page uses
**//for loop
// if(x[i].visibility === false
//change the background color to red **
}
})
On the html file, I use ng-repeat to show the items in the specific array like so.
<ion-item ng-repeat="song in ASongs | orderBy:'title'">
<div class="row responsive-sm">
<div>
<a>
<h2>{{song.title}}</h2>
</a>
</div>
</div>
</ion-item>
the songs in the ASongs array all have a property called "visibility" which is a boolean. ng-repeat will display the list of items in the ASongs Array. Now I'm trying to figure out how to change the background color of all the songs with a visibility that are false.
You can use ngClass directive.
CSS :
.background-with-false {
background-color : your-color;
}
HTML :
<div ng-class"{ 'background-with-false' : song.visibility === false }" class="row responsive-sm">
<div>
<a>
<h2>{{ song.title }}</h2>
</a>
</div>
</div>
You can also ngStyle

Get $index after filter

I have a small image gallery which has a search box and when the user clicks on a image it'll open a lightbox with that same image.
Basically I'm passing the $index to a function which opens the item in $scope.list[lb.index].
my code:
HTML
<input type="text" ng-model="query.name" />
<ul class="list" ng-show="list.length>0">
<li ng-repeat="item in list | filter:query">
<a class="img" ng-style="{'background-image':'url(/uploads/<%item.image%>)'}" ng-click="openLB($index)"></a>
</li>
</ul>
<div class="lightbox" ng-if="lb.show">
<a class="prev" ng-show="list.length>1" ng-click="changeItemLB(lb.index, 'prev')"></a>
<a class="next" ng-show="list.length>1" ng-click="changeItemLB(lb.index, 'next')"></a>
<div class="holder">
<img ng-if="list[lb.index].image.length" ng-src="/uploads/<%list[lb.index].image%>" />
</div>
</div>
Angular
$scope.openLB = function(index) {
$scope.lb.show = true;
$scope.lb.index = index;
};
$scope.changeItemLB = function(index, action) {
var tot = $scope.list.length-1,
goto = 0;
if(action=='prev') goto = index==0 ? tot : index-1;
if(action=='next') goto = index==tot ? 0 : index+1;
$scope.openLB(goto);
}
The problem is after the user filters the results (search input), the click still maintains the index from the list without the filter which makes the lightbox open the wrong image. Does anyone know how to solve this?
Thanks
Pass object instead of index
Suppose you have 5 item in your list
filter showing two result.
If you click then $index value will be your current view's index
but your list still then have 5 item.
Try like this
<a class="img" ng-style="{'background-image':'url(/uploads/<%item.image%>)'}" ng-click="openLB(item)"></a>
controller
$scope.openLB = function(item) {
var index = $scope.list.indexOf(item);
$scope.lb.show = true;
$scope.lb.index = index;
};
EDIT
How to get Filtered result
Try like this
view
<li ng-repeat="item in filtered= (list | filter:query)">
controller
$scope.filtered=[];
Now you can get yor filtered list from $scope.filtered

ng-repeat Circular Reference Screen Refresh

I'm a noob to AngularJS. As a learning exercise I am creating a typeahead control.
The typeahead is comprised of a text box for filtering the options, an unordered list for displaying the menu of short-listed options, and a Show/Hide button for manually toggling the list.
The text box filters the li elements using ng-repeat. When selecting an li item from the list, I populate the text box with the selected value, and then hide the list.
<div class="xtab-typeahead" ng-controller="xTabTypeAheadCtrl">
<input type="text" class="xtab-typeahead-search" placeholder="{{type}}" ng-model="query.id" ng-focus="showMenu()" ng-init="query.id = undefined" />
<button ng-click="toggleMenu()">Show/Hide</button>
<ul class="xtab-typeahead-menu" ng-class="{true:'active',false:''}[isActive]">
<li ng-repeat="item in menuItems | filter:query"
ng-click="hideMenu(); query.id = item.id">
{{item.id}}
</li>
</ul>
</div>
My issue is that when the value is assigned to the text box, the list is momentarily filtered to the one option selected (because the text box is also the source of the ng-repeat filter), before hiding the menu. What I want id for the menu to be hidden without being refreshed with the filter first.
It should be noted that this only occurs when using CSS transitions which I am using to fade the menu out.
Here is a plnkr to illustrate.
Here's a working Plnkr. I basically gave your menu time to finish its animation before setting the value. Relevant code is as follows:
$scope.selectItem = function(id){
$scope.isActive = false;
$timeout(function(){
$scope.query.id = id;
}, 250);
}
...and the HTML using the newly created selectItem method:
<div class="xtab-typeahead" ng-controller="xTabTypeAheadCtrl">
<input type="text" class="xtab-typeahead-search" placeholder="{{type}}" ng-model="query.id" ng-focus="showMenu()" ng-init="query.id = undefined" />
<button ng-click="toggleMenu()">Show/Hide</button>
<ul class="xtab-typeahead-menu" ng-class="{true:'active',false:''}[isActive]">
<li ng-repeat="item in menuItems | filter:query"
ng-click="selectItem(item.id)">
{{item.id}}
</li>
</ul>
</div>

How do I trigger an Angular custom filter on click and populate with the filtered data?

I want that the .prerequisites container be shown and populated only when the .popPrereq link(which can become a button) is clicked.
The json data is already available in the main controller and the filter works fine. I just need a way to tell angular to populate the data on click.
Prerequisites
<div class="prerequisites" style="background:pink">
<div class="prerequisite" data-ng-repeat="prerequisite in courses | getPrerequisites:course.CoursePrerequisites">
<p>{ {prerequisite.ProgramCode} } <br> <b>{ {prerequisite.pagetitle} }</b></p>
</div>
</div>
here is my custom filter
coursesSearchApp.filter('getPrerequisites', function(){
return function(prerequisites, ids){
var searchIds = ids.split(',');
var arrayToReturn = [];
for (var i=0; i<prerequisites.length; i++){
if (searchIds.indexOf(prerequisites[i].id) != -1) {
arrayToReturn.push(prerequisites[i]);
}
}
return arrayToReturn;
};
});
Thank you
Add to the popPrereq hyperlink ngClick directive where set show/hide status for prerequisites container to true. And add ngIf directive with this flag value to the prerequisites.
<a href="#" data-ng-show="course.CoursePrerequisites"
data-ng-click="showPrerequisites = true"
class="popPrereq">Prerequisites</a>
<div data-ng-if="showPrerequisites" class="prerequisites" style="background:pink">
<div class="prerequisite" data-ng-repeat="prerequisite in courses | getPrerequisites:course.CoursePrerequisites">
<p>{ {prerequisite.ProgramCode} }
<br> <b>{ {prerequisite.pagetitle} }</b>
</p>
</div>
</div>

How to show / hide a list of items with a button based on the number of items (Angular)

I have a list of items like:
<ul>
<li ng-repeat="show in data_shows">
<span class="program_shows_show_day">{{show[2]*1000 | amDateFormat:'ddd D MMM'}}</span>
<span class="program_shows_show_time">{{show[2]*1000 | amDateFormat:'H:mm'}} - {{show[3]*1000 | amDateFormat:'H:mm'}}</span>
</li>
</ul>
When there are more than 4 items I would like to show only the first 4 items and hide the rest with a button ('Show all').
With jQuery I would just count the items and if they're over 4 items apply a class to the <ul>. In Angular it's a bit more difficult- I know ng-repeat produces a $index variable, but I can only use that within the <li> items right? So what's the best way to apply a class on the <ul> element?
ngClass is your best bet:
<ul ng-class="{'my-hiding-class': data_shows.length > 4}">
...
This just says add the class 'my-hiding-class' to the ul when your collection size is greater than 4. Documentation here
EDIT:
For the button you'd need to do something like this:
<button ng-click="toggleList()"></button>
Then in your directive:
scope.toggleList = function() {
scope.showList = !scope.showList;
};
Then change your ngClass declaration slightly:
<ul ng-class="{'my-hiding-class': data_shows.length > 4 && showList}">
Edit 2:
Using the limitTo filter seems nice, but you might want to wrap it with custom functionality if you decide to go the filter route:
angular.module('myApp').filter('limitlessFilter', function($filter){
return function(objects, limit, showAll) {
if(showAll){
return objects;
} else {
return $filter('limitTo')(objects, limit);
}
}
});
In your HTML:
<li ng-repeat="show in data_shows | limitlessFilter:4:showAll">
...
<button ng-bind="showAll && 'Show Less' || 'Show More'" ng-click="toggleShowAll()"></button>
In your controller/directive
scope.toggleShowAll = function() {
scope.showAll = !scope.showAll;
};
On a side note, if you want to limit the number of renders your li go through, be sure to use track by on your ng-repeat. Documentation here
You can use Angular's limitTo filter to originally limit the number of displayed items to 4.
Additonally, you can have 2 buttons (one for showing all items, one for limiting the displayed items to 4) and show/hide them (or disable/enable them) according to the currently displayed items and the total number of items.
E.g.:
// VIEW
<ul>
<li ng-repeat="item in items | limitTo:limit">{{item}}</li>
</ul>
<button ng-click="setLimit(4)" ng-disabled="(limit===4)||(items.length<=4)">
Show few
</button>
<button ng-click="setLimit(0)" ng-disabled="items.length<=limit">
Show all
</button>
// CONTROLLER
$scope.items = [...];
$scope.limit = 4;
$scope.setLimit = function (lim) {
$scope.limit = (lim <= 0) ? $scope.items.length : lim;
};
See, also, this short demo.
Only add 4 items to your data_shows collection in your controller. That way you can test the logic, testing the view would be more tricky.
This should do the trick
<ul>
<li ng-repeat="show in data_shows | limitTo:4">
<span class="program_shows_show_day">{{show[2]*1000 | amDateFormat:'ddd D MMM'}}</span>
<span class="program_shows_show_time">{{show[2]*1000 | amDateFormat:'H:mm'}} - {{show[3]*1000 | amDateFormat:'H:mm'}}</span>
</li>
</ul>
<button ng-hide="data_shows.length < 4">Show more</button>
You could replace the first "4" with a variable in your scope and modify this value when clicking the button.
But yeah, BenCr's answer sounds better in some ways.

Resources