I am new with ionic framework.Currently i am working on ionicsidemenu app.
I have 100 plus records i want to display 20 records at once. When scroll down get next 20 records. For this i am using ion-infinite-scroll but i am unable to understand how to call next 20 records. I am using webservice for fetching records.
Please help me.
You have to use array instead of object in this case because pushing items in array is easier than pushing into object. Ionic documentaton also uses array in their example.
View:
<div ng-repeat="item in data">...</div>
<ion-infinite-scroll (ionInfinite)="getData()">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Controller:
$scope.data = [];
var page = 1;
$scope.getData = function(){
$http.get('http://example.com?page='+page).then(function(response){
page++;
$.each(response,function(key,item){
$scope.data.push(item);
});
}, function(error){
});
}
When scroll reach to ion-infinite-scroll function will called. at beginning there is no data on screen so without scrolling ion-infinite-scroll function called automatically to load first page.
use limitTo together with Infinite scrolling. AngularJS ng-repeat offers from version 1.1.4 the limitTo option. I slightly adapted the Infinite Scroll directive to make scrolling within a container possible that does not have height 100% of window.
ng-repeat="item in items | orderBy:prop | filter:query | limitTo:limit"
Notice that limit is a variable in the $scope, so changing it automatically adjusts the number of rendered items. And incrementing limit, only renders the added elements.
<table>
<tr ng-repeat="d in data | limitTo:totalDisplayed"><td>{{d}}</td></tr>
</table>
<button class="btn" ng-click="loadMore()">Load more</button>
//the controller
$scope.totalDisplayed = 20;
$scope.loadMore = function () {
$scope.totalDisplayed += 20;
};
$scope.data = data;
or try out this solution
<body>
<pane ng-controller="MainCtrl">
<header-bar title="'Infinite Scroll Example'">
</header-bar>
<content has-header="true" padding="true" on-infinite-scroll="addMoreItem">
<div class=" list padding">
<div ng-repeat="item in items | limitTo:numberOfItemsToDisplay" class="item" type="item-text-wrap">
<h3>{{item}}</h3>
</div>
</div>
</content>
</pane>
</body>
js code
angular.module('myApp', ['ionic'])
.controller('MainCtrl', function($scope) {
$scope.numberOfItemsToDisplay = 20; // number of item to load each time
$scope.items = getData();
function getData() {
var a = [];
for (var i=1; i< 1000; i++) {
a.push(i);
}
return a;
}
$scope.addMoreItem = function(done) {
if ($scope.items.length > $scope.numberOfItemsToDisplay)
$scope.numberOfItemsToDisplay += 20; // load 20 more items
done(); // need to call this when finish loading more data
}
});
while on scrolling will display 20 items.
Related
In AngularJS I used Limit To, but on the Angular2 this function was removed.
Example:
<div ng-repeat="elem in travel.cruise | limitTo:travel.limit" class="cruises">
....Content here...
</div>
Controller:
app.controller('TravelController', function($scope) {
var vm = this;
vm.cruise = cruises;
vm.limit = 3;
$scope.loadMore = function() {
var increamented = vm.limit + 3;
vm.limit = incremented > vm.cruise.length ? vm.cruise.length : increamented;
};
});
I guess you have to think of it as a function. Take a look at this.
<div *ngFor="let item of getItems(items, limit)">
</div>
getItems may apply caching to prevent multiple requests.
Or if the array is not lazy loaded. Try this.
<div *ngFor="let item of items | slice:0:limit">
</div>
I'm having a problem with setting checked on selected value using Icon collection-repeat with ion-radio.
Using the collection-repeat, if the selected item is the first item in the list, setting checked wouldn't work. To make it works I found, I need to make a delay assigning list data.
(If using ng-repeat, it works. But the list could be long, so I need to use the collection-repeat)
Example,
Template)
<ion-content class="has-header" ng-controller="Ctrl">
<div class="list">
<ion-radio
collection-repeat="item in list"
ng-model="selectedItem"
ng-value="item.id">
{{ item.n }}
</ion-radio>
</div>
</ion-content>
Controller)
angular.module('starter', ['ionic'])
.run(function($ionicPlatform) {
})
.controller('Ctrl',function($scope, $timeout) {
$scope.selectedItem = 1; // the first item
var list = [];
for (index = 1; index < 3; ++index) {
list.push({id: index, n: 'Item n. ' + index});
}
$scope.list = list;
});
The first item of the list wouldn't be checked. To make it works,
replace
$scope.list = list;
with
$timeout(function() {
$scope.list = list;
}, 500);
I want to know why it happened, and I don't think the 500ms is guaranteed, so I need to know right way to solve this. Please advice me.
It makes complete sense that you want to use collection-repeat over ng-repeat since the list could potentially be very long, and would be unnecessary to render all the items in the DOM at once using ng-repeat. Unfortunately this is a known bug within Ionic from what I have read and the work around to this is quite hacky. For instance the code below works with making active the 2nd radio:
Controller
.controller('Ctrl',function($scope, $timeout) {
$scope.data = {
selectedItem: 2
};
var list = [];
for (index = 1; index < 3; ++index) {
list.push({id: index, n: 'Item n. ' + index});
}
$scope.list = list;
});
HTML
<ion-content class="has-header" ng-controller="Ctrl">
<div class="list">
<ion-radio collection-repeat="item in list" ng-model="data.selectedItem" ng-value="item.id">
{{ item.n }}
</ion-radio>
</div>
</ion-content>
But when you change the selected item to 1, it does not show. Below is a workaround for what you are looking for. Start your loop at 0 and then hide that item using CSS (like I said "hacky"), give it a try.
Controller
.controller('Ctrl',function($scope, $timeout) {
$scope.data = {
selectedItem: 1
};
var list = [];
for (index = 0; index < 5; ++index) {
list.push({id: index, n: 'Item n. ' + index});
}
$scope.list = list;
});
HTML
<ion-content class="has-header" ng-controller="Ctrl">
<div class="list">
<ion-radio
collection-repeat="item in list" ng-model="data.selectedItem" ng-value="item.id" item-height="54" item-width="100.5%">
{{ item.n }}
</ion-radio>
CSS
.item-radio:first-of-type {
display: none;
}
.item-radio {
margin-top: -54px !important;
}
Hope this helps.
I have a database witch contains 1000 products. I have a list which displays 10 products at one time. This grid is scrollable. I want to load products 10 by 10.
What is the best way to do this with angularjs ? I am looking for a method which need shortest code.
Thanks
The concept is called pagination and if you want to achieve this in less amount of time then you must go for any already available module.
I have used Infinite Scroll It is very easy to use and would help you to implement things in no time.
You are looking for lib called "infinite scroll". You can find this app here https://github.com/ifwe/infinite-scroll
Where in the controller you put this code:
var app = angular.module('MyApp', ['tagged.directives.infiniteScroll']);
app.controller('MainController', ['$scope', '$http', function($scope, $http) {
$scope.page = 1;
$scope.items = [];
$scope.fetching = false;
// Fetch more items
$scope.getMore = function() {
$scope.page++;
$scope.fetching = true;
$http.get('/my/endpoint', { page : $scope.page }).then(function(items) {
$scope.fetching = false;
// Append the items to the list
$scope.items = $scope.items.concat(items);
});
};
}]);
And this is your view:
<div ng-app="MyApp">
<div ng-controller="MainController">
<ul tagged-infinite-scroll="getMore()">
<li ng-repeat="item in items">
{{ item.title }}
</li>
</ul>
</div>
</div>
Once it detect you scroll is at the end of the ng-repeat items it calls getMore function to load new items. Remember to add to the endpoint limit, and offset to load rest of the data, not same data every time.
When the Infinite Scroll in this example (copied from the Angular Material docs) is shown with the button the items do not appear.
If ng-show=ctrl.show is changed to ng-show=true the items appear.
Why don't the items appear with ng-show?
Markup
<div ng-controller="AppCtrl as ctrl" ng-cloak="" class="virtualRepeatdemoInfiniteScroll" ng-app="MyApp">
<md-content layout="column">
<p>
Display an infinitely growing list of items in a viewport of only 7 rows (height=40px).
<br><br>
This demo shows scroll and rendering performance gains when using <code>md-virtual-repeat</code>;
achieved with the dynamic reuse of rows visible in the viewport area. Developers are required to
explicitly use <code>md-virtual-repeat-container</code> as a wrapping parent container.
<br><br>
To enable infinite scroll behavior, developers must pass in a custom instance of
mdVirtualRepeatModel (see the example's source for more info).
</p>
<button ng-click="ctrl.show=!ctrl.show" style="width:100px">Show</button>
<md-virtual-repeat-container id="vertical-container" ng-show=ctrl.show>
<div md-virtual-repeat="item in ctrl.infiniteItems" md-on-demand="" class="repeated-item" flex="">
{{item}}
</div>
</md-virtual-repeat-container>
</md-content>
</div>
JS
(function () {
'use strict';
angular
.module('MyApp')
.controller('AppCtrl', function($timeout) {
// In this example, we set up our model using a plain object.
// Using a class works too. All that matters is that we implement
// getItemAtIndex and getLength.
this.infiniteItems = {
numLoaded_: 0,
toLoad_: 0,
// Required.
getItemAtIndex: function(index) {
if (index > this.numLoaded_) {
this.fetchMoreItems_(index);
return null;
}
return index;
},
// Required.
// For infinite scroll behavior, we always return a slightly higher
// number than the previously loaded items.
getLength: function() {
return this.numLoaded_ + 5;
},
fetchMoreItems_: function(index) {
// For demo purposes, we simulate loading more items with a timed
// promise. In real code, this function would likely contain an
// $http request.
if (this.toLoad_ < index) {
this.toLoad_ += 20;
$timeout(angular.noop, 300).then(angular.bind(this, function() {
this.numLoaded_ = this.toLoad_;
}));
}
}
};
});
})();
http://codepen.io/anon/pen/KdxjvM
works. Changed ng-show to style="visibility:hidden/visible"
I think it has to do with the scrolling distance of the initial list. When it is not visible, there is no height. And this height is computed before the element is visible.
I hate asking this question, because it seems like all pagination questions have been answered. However, I do not follow what is making the pagination pages shorten. I believe that my example is very similar to other examples.
I am getting the correct number of tabs, current page is changing correctly as well. However, the length is not matching the assigned items-per-page limit.
Here is my controller
viewsModule.controller('CountryCtrl', ['$scope', 'cacCountries', function($scope, cacCountries) {
$scope.loading = true;
$scope.countries = [];
$scope.currentPage = 1;
$scope.itemsPerPage = 20;
$scope.maxSize = 20;
cacCountries().then(function(countries) {
// console.log(countries);
$scope.loading = false;
$scope.countries = countries;
$scope.totalItems = countries.length;
});
}]);
I have set my itemsPerPage to 20
In my html I made sure to reference the itemsPerPage
<pagination
total-items="totalItems"
items-per-page= "itemsPerPage"
ng-model="currentPage"
class="pagination-sm">
</pagination>
I am getting back 13 tabs for 250 objects in the array. However, all 250 objects are showing up. I am expecting 20 per page.
The ng-repeat is plain
<tr ng-repeat="country in countries |filter:search ">
What could I be missing that would bind current page?
The pagination directive gives you a way to present to the user the list of selectable pages based on the size of the data and other parameters, and lets the user easily control the current page.
It does not actually filter the data for you. You still have to apply the itemsPerPage, currentPage etc within your ng-repeat.
One way to do this is to add an additional filter to help with skipping
app.filter('offset', function() {
return function(input, start) {
return input.slice(start);
};
})
and then use this with limitTo to control the paging
<div ng-repeat="country in countries | filter:search | offset: (currentPage - 1) * itemsPerPage | limitTo:itemsPerPage">
{{country.name}}
</div>
JSFiddle here
Old question.. but it worth to answer with the simple method.
<tr ng-repeat="country in countries.slice((currentPage -1) * itemsPerPage, currentPage * itemsPerPage) ">
Fork JSFiddle from #sheilak