How to make this asynchronous call, synchronous - angularjs

I have an associative array date as key, the value in this case is an array of objects. Now in this object
while (tempDate < endDate) {
$scope.dates.push(tempDate.format("DD-MM-YYYY"));
var dailyTrips = response.data[tempDate.format("DD-MM-YYYY")];
for (var i = 0; i < dailyTrips.length; i++) {
// console.log(moment(dailyTrips[i].trip.startTime).format("hh:mm a"));
// console.log(moment(dailyTrips[i].trip.endTime).format("hh:mm a"));
geocode(dailyTrips, i);
}
tempDate.add(1, 'days');
}
$scope.data = response.data;
var geocode = function(dailyTrips, i) {
(function() {
var latlng = {
lat: dailyTrips[i].trip.source.latitude,
lng: dailyTrips[i].trip.source.longitude
};
console.log(latlng);
var geocoder = new google.maps.Geocoder;
geocoder.geocode({
'location': latlng
}, function(result, status) {
if (result[1]) {
console.log(result[1].address_components[0].long_name+" "+result[1].address_components[2].long_name);
}
});
}(i));
};
Now This code is working but running at completely different times as it's a callback. I wanted to have this all at one time so that I can use it in ng-repeat and show everything nicely. How do I do that?
Expected output
Trip StartTime Trip from
Trip EndLine Trip To
EDIT 1: Still not working
while (tempDate < endDate) {
$scope.dates.push(tempDate.format("DD-MM-YYYY"));
var dailyTrips = response.data[tempDate.format("DD-MM-YYYY")];
var promises = [];
for (var i = 0; i < dailyTrips.length; i++) {
promises[i] = geocode(dailyTrips, i);
}
$q.all(promises).then(function(result) {
console.log(result); //line 39
});
tempDate.add(1, 'days');
}
$scope.data = response.data;
}, function(error) {
console.log(error.data);
});
var geocode = function(dailyTrips, i) {
var q = $q.defer();
var latlng = {
lat: dailyTrips[i].trip.source.latitude,
lng: dailyTrips[i].trip.source.longitude
};
console.log(latlng);
var geocoder = new google.maps.Geocoder;
geocoder.geocode({
'location': latlng
}, function(result, status) {
console.log(status);
if (status === google.maps.GeocoderStatus.OK) {
console.log(result[1].address_components[0].long_name + " " + result[1].address_components[2].long_name);
q.resolve(result[1].address_components[0].long_name + " " + result[1].address_components[2].long_name);
} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function() {
geocode(dailyTrips, i);
}, 500);
} else {
q.reject();
}
});
return q.promise;
};

You cannot make an async call synchronous, except by blocking your code, which you do no NOT want to do. Instead, I suggest you convert geocode into a promise
var geocode = function(dailyTrips, i) {
return this.$q((resolve, reject) => {
....
and then wait for all the promises to complete
var promises = [];
for (var i = 0; i < dailyTrips.length; i++) {
promises[i] = geocode(dailyTrips, i);
}
$q.all(promises).then( function(results) {...} );

Related

How can maintain the view in the bottom of the list when I add another element in my infinitescroll list ? angularjs

I have an issue I have a "chat" and when I add a new text in my infinite scroll container,
I go back to the top of the page, i'm not stuck to the bottom.
How can I maintain the page in the bottom of my page while people chat
my service
tabs.factory('chat', function ($http, $timeout, $q) {
return {
default: {
delay: 100
},
data: [],
dataScroll: [],
init: function (data) {
if (this.data.length == 0) {
for (var i = 0; i < data.length; i++) {
this.data[i] = data[i]
}
} else {
var tailleDataSaved = this.data.length
var dataAAjouter = data.slice(tailleDataSaved)
for (var i = 0; i < dataAAjouter.length; i++) {
this.data.push(dataAAjouter[i])
}
}
},
request: function (showAll) {
var self = this;
var deferred = $q.defer();
var index = this.dataScroll.length
var ndDataVisible = 7
var start = index;
var end = index + ndDataVisible - 1;
$timeout(function () {
if (!showAll) {
var item = []
if (start < end) {
for (var i = start; i < end; i++) {
console.log(start)
console.log(end)
console.log(self.data[i])
if (item = self.data[i]) {
self.dataScroll.push(item);
}
}
}
} else {
self.dataScroll = self.data
}
deferred.resolve(self.dataScroll);
}, 0);
return deferred.promise;
}
}
})
my js file
$scope.listChat= function () {
$scope.isActionLoaded = false;
$http.get(apiurl).then(function (response) {
chat.init(response.data)
$scope.isActionLoaded = true
})
}
$scope.listChatInfiniteScroll = function () {
$scope.isScrollDataLoaded = false
ticketListeActionScroll.request(false).then(function (response) {
$scope.actionsInfiniteScroll = response
$scope.isScrollDataLoaded = true
})
}
html file
<div ng-if="isActionLoaded" infinite-scroll='listChatInfiniteScroll ()' infinite-scroll-distance='1'>
<div ng-repeat="chat in actionsInfiniteScroll">
{{chat.text}}
</div>
</div>
Each time I add a new message it calls listChat

Localstorage is working for first time. If I refresh page at second it is working fine

I am using AngularJS local storage. I am facing an issue with local storage. At first when page is loaded the localstorage is assigning with null value. If I refresh at second time localstorage value is setting fine. I don't know what the issue.
My code is.
var app = angular.module('EntityApp', ['ngRoute', 'slickCarousel']);
app.controller('EntityAppCntroller', function($scope, $http, $window) {
if (localStorage.getItem('IsNewPinSet') != 1) {
var getLocation = function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
alert("Geolocation is not supported by this browser.");
}
};
getLocation();
function showPosition(position) {
var latitude;
var longitude;
latitude = position.coords.latitude;
longitude = position.coords.longitude;
localStorage.setItem('latitudeHome', latitude)
localStorage.setItem('longitudeHome', longitude)
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(latitude, longitude);
geocoder.geocode({
'latLng': latlng
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
for (var i = 0; i < results[0].address_components.length; i++) {
var types = results[0].address_components[i].types;
for (var typeIdx = 0; typeIdx < types.length; typeIdx++) {
if (types[typeIdx] == 'postal_code') {
var pin_all = results[0].address_components[i].short_name;
localStorage.setItem('pincodehome', pin_all)
$scope.pin_all = pin_all;
}
}
}
} else {
console.log("No results found");
}
}
});
};
}
// $window.localStorage.getItem('pincodehome') is null
// $window.localStorage.getItem('latitudeHome') is null
// $window.localStorage.getItem('longitudeHome') is null
//Common response in home page
$http.get('someurl?pincode=' + localStorage.getItem('pincodehome') + '&lat=' + localStorage.getItem('latitudeHome') + '&lang=' + localStorage.getItem('longitudeHome'), {}).success(function(response) {
$scope.Promotion = response.Promotion.Response;
});
});

Refresh multiple pages in a controller

I would like to know if it was possible to update several pages in a single controller?
I need to refresh my home page after adding data to my list.
For now I use a pull to refresh in my homepage, but I would like it to update after an addition in my list.
my controller :
.controller('addCRCtrl', function ($scope, $state, $stateParams, $ionicPopup, $ionicLoading, $timeout, AppService) {
let loadData = () => {
$ionicLoading.show();
$scope.loading=true;
$scope.form = {};
$scope.formProjet = {};
$scope.form.patient = idjeune;
$scope.form.dateVisite = new Date();
AppService.patient(idjeune).then(function (response) {
$scope.patient = response;
console.log(response);
});
AppService.user().then(function (response) {
$scope.bene1 = response;
console.log(response);
});
AppService.hopitaux().then(function (response) {
$scope.hopitaux = response;
});
AppService.lieuxlist().then(function (response) {
$scope.lieux = response;
});
AppService.userByAntenneAddCR().then(function (response) {
console.log(response);
$scope.listeBene = JSON.parse(JSON.stringify(response));
});
AppService.typeVisite().then(function (response) {
$scope.listeVisite = JSON.parse(JSON.stringify(response));
});
AppService.projet(idjeune).then(function (response) {
$scope.projets = response;
});
AppService.getCategorie().then(function (response) {
$scope.categorieprojet = response;
console.log(response);
if (update) {
$scope.updating = update;
$scope.form.dateVisite = new Date(cr.date);
for (let i in $scope.lieux) {
if ($scope.lieux[i].id == cr.idLieu) {
$scope.lieu = $scope.lieux[i];
break;
}
}
$scope.form.lieudetail = cr.lieudetail;
$scope.bene1 = {
id: cr.bene1,
nom: cr.benevole1
}
$scope.bene2 = {
id: cr.bene2,
nom: cr.benevole2
}
$scope.bene3 = {
id: cr.bene3,
nom: cr.benevole3
}
console.log("Benevole 1 : ", $scope.bene1);
console.log("Benevole 2 : ", $scope.bene2);
console.log("Benevole 3 : ", $scope.bene3);
$scope.form.description = cr.compteRenduVisite;
$scope.form.todo = cr.todo;
$scope.form.etatpatient = cr.etatPatient;
for (let i in $scope.listeVisite) {
if ($scope.listeVisite[i].id == cr.typeVisite) {
$scope.typeVisite = $scope.listeVisite[i];
break;
}
}
for (let i in $scope.projets) {
if ($scope.projets[i].id == cr.idProjet) {
$scope.projet = $scope.projets[i];
break;
}
}
$timeout(() => { $ionicLoading.hide(); $scope.loading=false;;}, 6000);
}
else
$timeout(() => { $ionicLoading.hide(); $scope.loading=false;}, 2000);
});
}
$scope.$on('$ionicView.beforeEnter', function (event, viewData) {
loadData();
});
$scope.addCr = function () {
$ionicLoading.show();
let isValid = $scope.form.dateVisite && $scope.patient && $scope.bene1 && $scope.form.description && $scope.form.todo;
isValid = isValid && $scope.form.etatpatient && $scope.typeVisite;
let formInvalid = () => {
$ionicLoading.hide();
var alertPopup = $ionicPopup.alert({
template: '<p style="text-align: center;">Veuillez renseigner tous les champs</p>'
});
}
if (!isValid) {
formInvalid();
return;
}
$scope.form.lieu = ($scope.lieu)? $scope.lieu.id:0;
$scope.form.bene1 = $scope.bene1.id;
$scope.form.bene2 = ($scope.bene2) ? $scope.bene2.id : null;
$scope.form.bene3 = ($scope.bene3) ? $scope.bene3.id : null;
$scope.form.lieudetail = ($scope.form.lieudetail) ? $scope.form.lieudetail : "-";
let temp = $scope.form.dateVisite;
//$scope.form.dateVisite = $scope.form.dateVisite.toISOString().slice(0, 10);
let newProject = false;
$scope.form.typeVisite = $scope.typeVisite.id;
switch ($scope.typeVisite.id) {
case 3:
newProject = true;
isValid = isValid && $scope.cprojet && $scope.formProjet.description && $scope.formProjet.titre;
break;
case 4:
case 5:
if ($scope.projet) $scope.form.projet = $scope.projet.id;
isValid = isValid && $scope.projet;
break;
default:
$scope.form.projet = 0;
break;
}
for (var i in $scope.hopitaux) {
if ($scope.hopitaux[i].nom === $scope.patient.hopital) {
$scope.form.hopital = $scope.hopitaux[i].id;
}
}
for (var j in $scope.form) {
if ($scope.form[j] == null) {
if (j == 'bene2' || j == 'bene3')
$scope.form[j] = 0;
else
delete $scope.form[j];
}
}
if (!isValid) {
formInvalid();
return;
}
let callService = () => {
var myform = angular.copy($scope.form);
if (update)
myform.dateVisite = new Date($scope.form.dateVisite.getTime() + 86400000).toISOString().slice(0, 10);
else
myform.dateVisite = $scope.form.dateVisite.toISOString().slice(0, 10);
console.log(myform);
let idtogo = (update) ? cr.id : null;
AppService.addCR(myform, idtogo).then(function (response) {
update = false;
cr = null;
var alertPopup = $ionicPopup.alert({
title: 'Ajout Réussie !',
template: '<p style="text-align: center;">Merci d\'avoir renseigné les informations relatives à la visite !</p>'
});
$scope.form.dateVisite = temp;
console.log(response);
$ionicLoading.hide();
$state.reload('menu.ficheJeune');
$state.go('menu.ficheJeune');
});
}
if (!newProject || update)
callService();
else {
$scope.formProjet.categorie = $scope.cprojet.id;
$scope.formProjet.patient = idjeune;
var myprojectform = angular.copy($scope.formProjet);
console.log(myprojectform);
AppService.addProject(myprojectform).then((response) => {
console.log(response);
if (response) {
AppService.projet(idjeune).then(function (response) {
for (let i in response) {
console.log("Response :", response);
let temp = false;
for (let j in $scope.projets) {
if (response[i].id == $scope.projets[j].id) {
temp = true;
}
}
if (!temp) {
$scope.form.projet = response[i].id;
callService();
break;
}
}
});
}
});
}
};
AppService.refreshToken().then(function (response) {
if ($scope.token) {
console.info('Refresh');
}
});
})
For now, to update my first page I do:
$state.reload('menu.ficheJeune');
$state.go('menu.ficheJeune');
But I would also like to update a second page called 'menu.home'.
I thank you in advance
You can use this in your homeCtrl :
$scope.$on('$ionicView.beforeEnter', function() {
console.log('beforeEnter');
// your code
});

nightmare how to looply select the selector

var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
var fs = require('fs');
var result;
nightmare
.goto('http://football-system.jp/fss/pub_penaltylist.php?lid=eBVesRz5C54=')
.wait('select[name="selectTeam"]')
.evaluate(function () {
var options = document.querySelectorAll('option'),i;
var values =[]
for (i = 1; i < options.length; ++i) {
values.push(options[i].value)
}
return values;
})
.then(function (values) {
console.log(values)
values.reduce(function(accumulator, value) {
return accumulator.then(function(results) {
return nightmare.goto("http://football-system.jp/fss/pub_penaltylist.php?lid=eBVesRz5C54=")
.wait('select[name="selectTeam"]')
.select('select[name="selectTeam"]', value)
.wait('button[onClick="selectData();"]')
.click('button[onClick="selectData();"]')
.wait('table[class="tableOutputDate"]')
.evaluate(function () {
return document.querySelector('table[class="tableOutputDate"]').textContent;
})
.then(function(result){
console.log(result)
results.push(result);
return results;
});
});
}, Promise.resolve([])).then(function(results){
console.log(results)
});
})
.catch(function (error) {
console.error('Search failed:', error);
});
That is my code .I want to looping select all the selector in that page and get the all html data.I asked a question in here that how to loop in nightmare,but that result cant solve this problem.please help me. Thank you.
I solve my question.the problem is happened in the deal time,not in the loop logic.I add some more wait(time).I think wait(time)is better than the wait(selector).so is over. thank u attention.
var run = function * () {
//var values = ['http://www.yahoo.com', 'http://example.com', 'http://w3c.org'];
var titles = [];
for (var i = 0; i < values.length; i++) {
var title = yield nightmare.goto('.............')
//.wait('select[name="selectTeam"]')
.wait(2000)
.select('select[name="selectTeam"]', values[i])
.wait(2000)
.click('button[onClick="selectData();"]')
//.wait('table[class="tableOutputDate"]')
.wait(2000)
.evaluate(function () {
//return document.querySelector('table[class="tableOutputDate"]').textContent;
var divs = document.querySelectorAll('table[class="tableOutputDate"]'),i;
var tables = []
for (i = 0; i < divs.length; ++i) {
tables.push(divs[i].textContent)
//result += divs[i].href.toString()+"\n";
}
return tables;
})
titles.push(title);
}
return titles;
}
vo(run)(function(err, titles) {
console.dir(titles);
});

Angularjs paging limit data load

I always manage pagination with angular
retrieve all the data from the server
and cache it client side (simply put it in a service)
now I have to cope with quite lot of data
ie 10000/100000.
I'm wondering if can get into trouble
using the same method.
Imo passing parameter to server like
page search it's very annoying for a good
user experience.
UPDATE (for the point in the comment)
So a possible way to go
could be get from the server
like 1000 items at once if the user go too close
to the offset (ie it's on the 800 items)
retrieve the next 1000 items from the server
merge cache and so on
it's quite strange not even ng-grid manage pagination
sending parameters to the server
UPDATE
I ended up like:
(function(window, angular, undefined) {
'use strict';
angular.module('my.modal.stream',[])
.provider('Stream', function() {
var apiBaseUrl = null;
this.setBaseUrl = function(url) {
apiBaseUrl = url;
};
this.$get = function($http,$q) {
return {
get: function(id) {
if(apiBaseUrl===null){
throw new Error('You should set a base api url');
}
if(typeof id !== 'number'){
throw new Error('Only integer is allowed');
}
if(id < 1){
throw new Error('Only integer greater than 1 is allowed');
}
var url = apiBaseUrl + '/' + id;
var deferred = $q.defer();
$http.get(url)
.success(function (response) {
deferred.resolve(response);
})
.error(function(data, status, headers, config) {
deferred.reject([]);
});
return deferred.promise;
}
};
};
});
})(window, angular);
(function(window, angular, undefined) {
'use strict';
angular.module('my.mod.pagination',['my.mod.stream'])
.factory('Paginator', function(Stream) {
return function(pageSize) {
var cache =[];
var staticCache =[];
var hasNext = false;
var currentOffset= 0;
var numOfItemsXpage = pageSize;
var numOfItems = 0;
var totPages = 0;
var currentPage = 1;
var end = 0;
var start = 0;
var chunk = 0;
var currentChunk = 1;
var offSetLimit = 0;
var load = function() {
Stream.get(currentChunk).then(function(response){
staticCache = _.union(staticCache,response.data);
cache = _.union(cache,response.data);
chunk = response.chunk;
loadFromCache();
});
};
var loadFromCache= function() {
numOfItems = cache.length;
offSetLimit = (currentPage*numOfItemsXpage)+numOfItemsXpage;
if(offSetLimit > numOfItems){
currentChunk++;
load();
}
hasNext = numOfItems > numOfItemsXpage;
totPages = Math.ceil(numOfItems/numOfItemsXpage);
paginator.items = cache.slice(currentOffset, numOfItemsXpage*currentPage);
start = totPages + 1;
end = totPages+1;
hasNext = numOfItems > (currentPage * numOfItemsXpage);
};
var paginator = {
items : [],
notFilterLabel: '',
hasNext: function() {
return hasNext;
},
hasPrevious: function() {
return currentOffset !== 0;
},
hasFirst: function() {
return currentPage !== 1;
},
hasLast: function() {
return totPages > 2 && currentPage!==totPages;
},
next: function() {
if (this.hasNext()) {
currentPage++;
currentOffset += numOfItemsXpage;
loadFromCache();
}
},
previous: function() {
if(this.hasPrevious()) {
currentPage--;
currentOffset -= numOfItemsXpage;
loadFromCache();
}
},
toPageId:function(num){
currentPage=num;
currentOffset= (num-1) * numOfItemsXpage;
loadFromCache();
},
first:function(){
this.toPageId(1);
},
last:function(){
this.toPageId(totPages);
},
getNumOfItems : function(){
return numOfItems;
},
getCurrentPage: function() {
return currentPage;
},
getEnd: function() {
return end;
},
getStart: function() {
return start;
},
getTotPages: function() {
return totPages;
},
getNumOfItemsXpage:function(){
return numOfItemsXpage;
},
search:function(str){
if(str===this.notFilterLabel){
if(angular.equals(staticCache, cache)){
return;
}
cache = staticCache;
}
else{
cache = staticCache;
cache = _.filter(cache, function(item){ return item.type == str; });
}
currentPage = 1;
currentOffset= 0;
loadFromCache();
}
};
load();
return paginator;
}
});
})(window, angular);
server side with laravel (All the items are cached)
public function tag($page)
{
$service = new ApiTagService(new ApiTagModel());
$items = $service->all();
$numOfItems = count($items);
if($numOfItems > 0){
$length = self::CHUNK;
if($length > $numOfItems){
$length = $numOfItems;
}
$numOfPages = ceil($numOfItems/$length);
if($page > $numOfPages){
$page = $numOfPages;
}
$offSet = ($page - 1) * $length;
$chunk = array_slice($items, $offSet, $length);
return Response::json(array(
'status'=>200,
'pages'=>$numOfPages,
'chunk'=>$length,
'data'=> $chunk
),200);
}
return Response::json(array(
'status'=>200,
'data'=> array()
),200);
}
The only trouble by now is managing filter
I've no idea how to treat filtering :(

Resources