How to implement load more posts with Angular2? - angularjs

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>

Related

Call JSON after user has made the filter

I have an extremely large JSON (5000 keys with 5 values each), and i want to know if there's a better way to improve performance of this one. For example I'm using AngularJS with a Backend in Drupal 7.
My View
<ul class="list-group border-0">
<form class="form-inline m-3">
<div class="col-sm p-0 float-left w-50">
<label class="col-form-label text-primary lead form-group" for="inputsm" for="name" for="inlineFormInput">Year: </label>
</div>
<div class="col-sm p-0 float-left w-50">
<input class="form-control" ng-model="searchYear"/>
</div>
</form> //I have more filters than this one...
<li class="list-group-item border-0" ng-repeat="item in filterData = (informes | filter:{year: searchYear}) | limitTo:10:10*(currentPage-1)">
<div class="wrapper">
<div class="informes">
<a href="#!/node-informes" ng-value="{{item.nid}}">
<p class="text-left">
<p ng-click="nodeID(item)">{{item.title}}</p>
</p>
</a>
</div>
</div>
</li>
</ul>
And the JS
informes.factory('InformesFtry', ['$http', function ($http) {
return {
getAll: function () {
return $http.get('https://myjsonurl/json');
}
};
}]);
informes.controller('InformesCtrl', ['drupal', '$rootScope', '$scope', '$http', 'InformesFtry', '$localStorage', function(drupal, $rootScope, $scope, $http, InformesFtry, $localStorage) {
InformesFtry.getAll().success(function(rows) {
$scope.informes = (rows, function(items) {
return rows.nodes;
})();
$scope.output();
});
$scope.loading = true;
$scope.loaded = false;
$scope.totalItems = [];
$scope.currentPage = 1;
$scope.itemsPerPage = 10;
$scope.output = function() {
$scope.loading = false;
$scope.loaded = true;
$scope.totalItems = $scope.informes.length;
$scope.viewby = 10;
$scope.maxSize = 5;
$scope.itemsPerPage = $scope.viewby;
$scope.displayItems = $scope.informes.slice(0, 10);
var currentPage = $scope.currentPage;
$scope.setItemsPerPage = function(num) {
$scope.itemsPerPage = num;
$scope.currentPage = 1;
}
$scope.pageChanged = function() {
var startPos = ($scope.currentPage - 1) * 10;
$scope.displayItems = $scope.informes.slice(startPos, startPos + 10);
};
}
$scope.nodeID = function(item) {
$localStorage.nid = item.nid;
console.log("nodeID");
}
}]);
I tried from my Backend to separate those files and iterate from the controller, but it's better for performance to search in JSON after the query has been made from the view, like an inverse from what i'm doing. Search everywhere but i couldn't get to a possible resolution.
I thought about using json after the query from the view has been made.
I don't know how to achieve that. Separating the files will give me the same result unless there's some way to make the filter before calling JSON. Thanks in advance.
Yes there is absolutely ways to make this more performant. You can improve the performance by moving your filter logic from your ng-repeat to the controller. Then update the list of item you want to repeat over in your controller. Here is a great article that talks about this exactly.
https://toddmotto.com/use-controller-filters-to-prevent-digest-performance-issues/
Brief Explanation as to why this helps is that your ng-repeat will continually be processed for changes on digest cycles even if the values around it never changed, this means its filtering those 5,000 records each time. You can move your filtering logic to the controller and then trigger when you update your list by using ng-change on your filters (like your year input).
So implementing that would look like the following:
JavaScript:
$scope.updateData = function(){
var filteredData = $filter('filter')($scope.informes, {'year': $scope.searchYear});
filteredData = $filter('limitTo')(filteredData, 10, (10 * (currentPage - 1)));
$scope.filteredData = filteredData;
}
HTML:
<!-- Your Inputs should have ng-change -->
<input class="form-control" ng-model="searchYear" ng-change="updateData()"/>
<!-- Remove filters from html and loop over your filtered list -->
<li class="list-group-item border-0" ng-repeat="item in filteredData">
Edit: Added additional explanation & example code changes.

IONIC: unable to load dynamic content in `ion-infinite-scroll`

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.

how to get calculated values(totalPriceAmt) from js to html in by using angular js

Js
var myApp = angular.module("DataEntryApp", []);
myApp.controller("DataEntryController",function($scope) {
alert("totalPrice?" + $scope.totalPriceAmt);
}
$scope.Add = function() {
alert("Total amount commint:" +$scope.totalPriceAmt);
};
Html side
<div ng-app="DataEntryApp" ng-controller="DataEntryController">
<button ng-click="Add()">Submit</button>
<span>Total: {{ totalPriceAmt }} </span>
</div>
I am not able to get the values totalPriceAmt in HTML side after clicking on submit button or I want to directly display totalPrice in HTML.
there is syntax error
function is defined outside controller
var myApp = angular.module("DataEntryApp", []);
myApp.controller("DataEntryController",function($scope) {
$scope.totalPriceAmt =10;
$scope.Add = function() {
$scope.totalPriceAmt =$scope.totalPriceAmt+10;
};
});
http://codepen.io/vkvicky-vasudev/pen/xOOBGq
If you want to display $scope value in html, you need to assign some value to that. As i can see from your code , no assignment of value is happening.
var myApp = angular.module("DataEntryApp", []);
myApp.controller("DataEntryController",function($scope) {
$scope.totalPriceAmt = 10;
}
$scope.Add = function() {
$scope.totalPriceAmt = 10;
};
<div ng-app="DataEntryApp" ng-controller="DataEntryController">
<button ng-click="Add()">Submit</button>
<span>Total: {{ totalPriceAmt }} </span>
</div>
Now if you run the app, after clicking the button , it will work.
Hey you must bind the variable using the ng-bind and then give access to the controller and use the $scope and perform the operation.
There was a syntax error in your example for registering the controller with the angular application. Fixing that, in the attached code snippet, you can see that I initialize the value totalPriceAmount to 0 in the controller, and then increment it by 10 each time the Add method is called when clicking the button. You'll also see that the data-binding to the scope variable occurs correctly as well.
var myApp = angular.module("DataEntryApp", []);
myApp.controller("DataEntryController", function($scope) {
$scope.totalPriceAmt = 0;
$scope.Add = function() {
$scope.totalPriceAmt += 10;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<div ng-app="DataEntryApp" ng-controller="DataEntryController">
<button ng-click="Add()">Submit</button>
<span>Total: {{ totalPriceAmt }} </span>
</div>

dynamically updating contents from the results of the cloud api using angular js

i am using angular js, bootstrap thumbnail and google cloud endpoints for my app.
The .html looks part looks like:
<body ng-controller="SearchController as searchCtrl">
<div class="row">
<div class="col-sm-2 col-md-2" ng-repeat="result in searchCtrl.searchResults">
<div class="thumbnail">
<img ng-src="{{result.thumbnailUrl}}">
</div>
</div>
</div>
The .js looks like below
(function(){
var app = angular.module('InstaMonitorAdmin', []);
app.controller('SearchController', function(){
this.searchResults = {};
this.searchTags = function(keyword){
//this.searchResults = results;
gapi.client.instagramApi.searchTags({'keyword':keyword}).execute(function(resp) {
if(resp && resp.hasOwnProperty('error')) {
// error
alert(resp.error.message);
}else{
var myJsonString = JSON.stringify(resp.items);
this.searchResults = myJsonString;
console.log(myJsonString);
}
});
};
});
In the console debugger it shows data for myJsonString as:
{"userName":"vikceo",
"caption":"#sandsculpture #sandcastle",
"tags":"[mountains, breathtaking, love, skyporn, minion]",
"thumbnailUrl":"https://scontent.cdninstagram.com/t51.2885-15/s150x150/e35/13108860_653673808116072_1235622514_n.jpg",
"kind":"instagramApi#resourcesItem"},
{"userName":"neetipari","caption":"My love #passion",
"tags":"[weddingcake, love, fondantcakes, foodporn]",
"thumbnailUrl":"https://scontent.cdninstagram.com/t51.2885-15/s150x150/e35/12940136_423862367814317_252510398_n.jpg",
"kind":"instagramApi#resourcesItem”}]
The issue is that the page does not render the search results returned from the google end point. I have tested that it return the results fine.
if i comment it and uncomment the top line where i am passing a hard coded array then it works fine.
Is it because it takes more time for response to come and assign to array? I thought it will continue to listen to this array. Please advise
so the problem turned out to be how i assigned the returned results. this is the final method:
app.controller('SearchController', function(){
this.searchResults = {};
this.searchTags = function(keyword){
var data = this;
data.searchResults = [];
gapi.client.instagramApi.searchTags({'keyword':keyword}).execute(function(resp) {
if(resp && resp.hasOwnProperty('error')) {
// error
alert(resp.error.message);
}else{
//successful login
console.log(resp);
data.searchResults = resp.items;
}
});
};
To have a synchronous assignment to the array , you could wait for the execution such as:
gapi.client.instagramApi.searchTags({'keyword':keyword}).execute(function(resp)).then(function(ress) {
//console.log(ress.items);
this.searchResults = ress;
});
Just add an ng-if, if you add ng-if element creates after data is come
<div ng-if="searchCtrl.searchResults.length" class="col-sm-2 col-md-2" ng-repeat="result in searchCtrl.searchResults.items">
<div class="thumbnail">
<img ng-src="{{result.thumbnailUrl}}">
</div>
</div>

Determine layers in wms address angularjs

I am using angularjs and I want to enter a wms address and check what are the available layers that I could select. Ive tried http.Capabilities but its not working.
Check the sample below. This might help you.
<div ng-app ng-controller="WMSCtrl">
<ul>
<li ng-repeat="num in nums">{{num}}</li>
{{data}}
<button ng-click="get_data()">Get stuff</button>
</ul>
function WMSCtrl($scope, $http) {
$scope.nums = [1,2,3]
$scope.data = null;
$scope.get_data = function() {
var url2 = 'http://giswebservices.massgis.state.ma.us/geoserver/wms?VERSION=1.1.1&LAYERS=massgis:GISDATA.ACECS_POLY&SRS=EPSG:26986&BBOX=11830.0,776202.9449152543,348201.0,961492.0550847457&WIDTH=708&HEIGHT=390&INFO_FORMAT=text/javascript&FEATURE_COUNT=10&QUERY_LAYERS=massgis:GISDATA.ACECS_POLY&X=120&Y=109&FORMAT&STYLES=&SERVICE=WMS'
$http.jsonp(url2, {params : {REQUEST: 'GetFeatureInfo'}});
}
window.parseResponse = function(data) {
$scope.data = data
}
}
Plunker given below link

Resources