Angular leaflet - Showing multiple marker issue - angularjs

I am using the following code to add markers in leaflet:
.controller('MapController',
[ '$scope',
'$cordovaGeolocation',
'$stateParams',
'$ionicModal',
'$ionicPopup',
'$http',
function(
$scope,
$cordovaGeolocation,
$stateParams,
$ionicModal,
$ionicPopup,
$http
) {
$scope.$on("$stateChangeSuccess", function() {
$scope.map = {
defaults: {
tileLayer: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
maxZoom: 18,
zoomControlPosition: 'bottomleft'
},
markers : {},
events: {
map: {
enable: ['context'],
logic: 'emit'
}
}
};
$scope.locate();
});
$scope.locate = function(){
$scope.map.center = {
lat : location.lat,
lng : location.lng,
zoom : 12,
};
var Location = function() {
if ( !(this instanceof Location) ) return new Location();
this.lat = "";
this.lng = "";
this.name = "";
};
$ionicModal.fromTemplateUrl('templates/addLocation.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.map.markers.push=({
lat:35.654,
lng:73.244,
message:'demo 1'
})
$scope.map.markers.push=({
lat:38.654,
lng:73.244,
message:'demo 2'
})
$scope.$on('leafletDirectiveMap.click', function(event, locationEvent){
$scope.newLocation = new Location();
$scope.newLocation.lat = locationEvent.leafletEvent.latlng.lat;
$scope.newLocation.lng = locationEvent.leafletEvent.latlng.lng;
$scope.modal.show();
});
$scope.saveLocation = function(lat, lang) {
//LocationsService.savedLocations.push($scope.newLocation);
//alert(lat + " - " + lang);
var link = 'http://192.168.5.110/server/addLocation.php';
var json1 = {l1 : lat, l2 : lang , l3: sessionStorage.getItem('loggedin_phone')};
$http.post(link, { data: json1 })
.then(function (res){
$scope.response = res.data.result;
if($scope.response.created=="1"){
$scope.title="Thank You";
$scope.template="Mobile Toilet Added!";
//no back option
/*
$ionicHistory.nextViewOptions({
disableAnimate: true,
disableBack: true
});
$state.go('login', {}, {location: "replace", reload: true});
*/
}else if($scope.response.exists=="1"){
$scope.title="Duplication";
$scope.template="This Location is already added!";
}else{
$scope.title="Failed";
$scope.template="Contact Our Technical Team";
}
var alertPopup = $ionicPopup.alert({
title: $scope.title,
template: $scope.template
});
});
$scope.modal.hide();
};
$cordovaGeolocation
.getCurrentPosition()
.then(function (position) {
$scope.map.center.lat = position.coords.latitude;
$scope.map.center.lng = position.coords.longitude;
$scope.map.center.zoom = 18;
$scope.map.markers.now = {
lat:position.coords.latitude,
lng:position.coords.longitude,
focus: true,
draggable: false,
//message: ''
};
}, function(err) {
// error
console.log("Location error!");
console.log(err);
});
};
}]);
But only the demo2 marker is displaying.
Is there a way to show multiple markers on the leaflet map by using JSON data of latitudes and longitudes loaded from API?

<leaflet defaults="defaults" event-broadcast="events" lf-center="center" markers="markers" layers="layers" id="global-map" width="100%" height="240px"></leaflet>
<leaflet defaults="defaults2" event-broadcast="events2" lf-center="center2" markers="markers2" layers="layers2" id="global-map2" width="100%" height="240px"></leaflet>

Related

AngularJS - moving Material mdDialog to service

I'm trying to cleanup code of one of my controllers which became too big. First I have decided to move attendee registration, which uses AngularJS Material mdDialog, to the service.
Original (and working) controller code looks like:
myApp.controller('RegistrationController', ['$scope','$routeParams','$rootScope','$location','$filter','$mdDialog', function($scope, $routeParams, $rootScope, $location, $filter, $mdDialog){
var attendee = this;
attendees = [];
...
$scope.addAttendee = function(ev) {
$mdDialog.show({
controller: DialogController,
templateUrl: 'views/regForm.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
controllerAs: 'attendee',
fullscreen: $scope.customFullscreen, // Only for -xs, -sm breakpoints.
locals: {parent: $scope}
})
.then(function(response){
attendees.push(response);
console.log(attendees);
console.log(attendees.length);
})
};
function DialogController($scope, $mdDialog) {
var attendee = this;
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.save = function(response) {
$mdDialog.hide(response);
};
}
}]);
and the code for the controller after separation:
myApp.controller('RegistrationController', ['$scope','$routeParams','$rootScope','$location','$filter','$mdDialog','Attendees', function($scope, $routeParams, $rootScope, $location, $filter, $mdDialog, Attendees){
...
$scope.attendees= Attendees.list();
$scope.addAttendee = function (ev) {
Attendees.add(ev);
}
$scope.deleteAttendee = function (id) {
Attendees.delete(id);
}
}]);
New service code looks like:
myApp.service('Attendees', ['$mdDialog', function ($mdDialog) {
//to create unique attendee id
var uid = 1;
//attendees array to hold list of all attendees
var attendees = [{
id: 0,
firstName: "",
lastName: "",
email: "",
phone: ""
}];
//add method create a new attendee
this.add = function(ev) {
$mdDialog.show({
controller: DialogController,
templateUrl: 'views/regForm.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
controllerAs: 'attendee',
fullscreen: this.customFullscreen, // Only for -xs, -sm breakpoints.
//locals: {parent: $scope}
})
.then(function(response){
attendees.push(response);
console.log(attendees);
console.log(attendees.length);
})
};
//simply search attendees list for given id
//and returns the attendee object if found
this.get = function (id) {
for (i in attendees) {
if (attendees[i].id == id) {
return attendees[i];
}
}
}
//iterate through attendees list and delete
//attendee if found
this.delete = function (id) {
for (i in attendees) {
if (attendees[i].id == id) {
attendees.splice(i, 1);
}
}
}
//simply returns the attendees list
this.list = function () {
return attendees;
}
function DialogController($mdDialog) {
this.hide = function() {
$mdDialog.hide();
};
this.cancel = function() {
$mdDialog.cancel();
};
this.save = function(response) {
$mdDialog.hide(response);
};
}
}]);
but I'm not able to "save" from the spawned mdDialog box which uses ng-click=save(attendee) neither close the dialog box.
What I'm doing wrong?
I'm not able to "save" from the spawned mdDialog box which uses ng-click=save(attendee) neither close the dialog box.
When instantiating a controller with "controllerAs" syntax, use the name with which it is instantiated:
<button ng-click="ctrl.save(ctrl.attendee)">Save</button>
this.add = function(ev) {
$mdDialog.show({
controller: DialogController,
templateUrl: 'views/regForm.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
controllerAs: ̶'̶a̶t̶t̶e̶n̶d̶e̶e̶'̶ 'ctrl',
fullscreen: this.customFullscreen, // Only for -xs, -sm breakpoints.
//locals: {parent: $scope}
})
.then(function(response){
attendees.push(response);
console.log(attendees);
console.log(attendees.length);
return response;
});
To avoid confusion, choose a controller instance name that is different from the data names.
$scope is not available to be injected into a service when it's created. You need to refactor the service and its methods so that you don't inject $scope into it and instead pass the current scope to the service methods when you call them.
I actually have a notification module that I inject which uses $mdDialog. Below is the code for it. Perhaps it will help.
(() => {
"use strict";
class notification {
constructor($mdToast, $mdDialog, $state) {
/* #ngInject */
this.toast = $mdToast
this.dialog = $mdDialog
this.state = $state
/* properties */
this.transitioning = false
this.working = false
}
openHelp() {
this.showAlert({
"title": "Help",
"textContent": `Help is on the way for ${this.state.current.name}!`,
"ok": "OK"
})
}
showAlert(options) {
if (angular.isString(options)) {
var text = angular.copy(options)
options = {}
options.textContent = text
options.title = " "
}
if (!options.ok) {
options.ok = "OK"
}
if (!options.clickOutsideToClose) {
options.clickOutsideToClose = true
}
if (!options.ariaLabel) {
options.ariaLabel = 'Alert'
}
if (!options.title) {
options.title = "Alert"
}
return this.dialog.show(this.dialog.alert(options))
}
showConfirm(options) {
if (angular.isString(options)) {
var text = angular.copy(options)
options = {}
options.textContent = text
options.title = " "
}
if (!options.ok) {
options.ok = "OK"
}
if (!options.cancel) {
options.cancel = "Cancel"
}
if (!options.clickOutsideToClose) {
options.clickOutsideToClose = false
}
if (!options.ariaLabel) {
options.ariaLabel = 'Confirm'
}
if (!options.title) {
options.title = "Confirm"
}
return this.dialog.show(this.dialog.confirm(options))
}
showToast(toastMessage, position) {
if (!position) { position = 'top' }
return this.toast.show(this.toast.simple()
.content(toastMessage)
.position(position)
.action('OK'))
}
showYesNo(options) {
options.ok = "Yes"
options.cancel = "No"
return this.showConfirm(options)
}
uc() {
return this.showAlert({
htmlContent: "<img src='img\\underconstruction.jpg'>",
ok: "OK",
title: "Under Construction"
})
}
}
notification.$inject = ['$mdToast', '$mdDialog', '$state']
angular.module('NOTIFICATION', []).factory("notification", notification)
})()
Then inject notification (lower case) into my controllers in order to utilize it. I store notification in a property of the controller and then call it with something like this:
this.notification.showYesNo({
clickOutsideToClose: true,
title: 'Delete Customer Setup?',
htmlContent: `Are you sure you want to Permanently Delete the Customer Setup for ${custLabel}?`,
ariaLabel: 'Delete Dialog'
}).then(() => { ...
this.notification.working = true
this.ezo.EDI_CUSTOMER.remove(this.currentId).then(() => {
this.primaryTab = 0
this.removeCustomerFromList(this.currentId)
this.currentId = 0
this.notification.working = false
}, error => {
this.notification.working = false
this.notification.showAlert({
title: "Error",
htmlContent: error
})
})

AngularJS: Not able to store data to an object

I'm trying to store captured data from the form in an object using angular-material for dialog box with the form to capture.
Related part of the controller looks like
$scope.attendees = [{
firstName: "",
lastName: "",
email: "",
phone: ""
}];
$scope.addAttendee = function(ev) {
$mdDialog.show({
controller: DialogController,
templateUrl: 'views/regForm.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
})
};
function DialogController($scope, $mdDialog) {
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.saveAttendee = function(attendee) {
str = JSON.stringify(attendee, null, 4);
$mdDialog.hide(attendee);
console.log('Attendee ' + str);
$scope.attendees.push(attendee);
console.log('Attendees ' + $scope.attendees);
};
}
Output for Attendee is correct but later it crashed on push(attendee) as Cannot read property 'push' of undefined or push will overwrite added previously data (based on given answer)
Any tips on that?
Just move the $scope.attendees inside the controller.
function DialogController($scope, $mdDialog) {
$scope.attendees = [{
firstName: "",
lastName: "",
email: "",
phone: ""
}];
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.saveAttendee = function(attendee) {
str = JSON.stringify(attendee, null, 4);
$mdDialog.hide(attendee);
console.log('Attendee ' + str);
$scope.attendees.push(attendee);
console.log('Attendees ' + $scope.attendees);
};
}
What you saying about to send data from controller who calls the mdDialog, a alld a plnkr with a basic example.
example plnkr
cour code modificated should be.
function DialogController($scope, $mdDialog, attendees) {
$scope.attendees = attendees;
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.saveAttendee = function(attendee) {
str = JSON.stringify(attendee, null, 4);
$mdDialog.hide(attendee);
console.log('Attendee ' + str);
$scope.attendees.push(attendee);
console.log('Attendees ' + $scope.attendees);
};
}
and in the controller who calls for example
$modal.show({
// configuration like you have.
}).then(function(response){
//when hide the modal
$scope.attendees = response;
});
Check if out if this help.
If someone will need "fixed" code for the dialog box controller is below
var attendee = this;
attendees = [];
$scope.addAttendee = function(ev) {
$mdDialog.show({
controller: DialogController,
templateUrl: 'views/regForm.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
controllerAs: 'attendee',
fullscreen: $scope.customFullscreen, // Only for -xs, -sm breakpoints.
locals: {parent: $scope}
})
.then(function(response){
attendees.push(response);
console.log(attendees);
console.log(attendees.length);
})
};
function DialogController($scope, $mdDialog) {
var attendee = this;
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.save = function(response) {
$mdDialog.hide(response);
};
}

Angular Service or Root Function

I want to re-organize my code so that I can share a dialog page with different controllers (ie. each controller opens the same dialog)
Should my dialog be a service or a directive... I'm not sure how to make it available to the controllers and have access to scopes
Something like this:
app.controller('PropertiesCtrl', function($scope,$rootScope,$http, DTOptionsBuilder, DTColumnBuilder, apiserv, $filter, $mdDialog, $mdMedia){
$scope.getProperties = function(){
$scope.data=[];
//var url = 'http://www.filltext.com/?rows=10&fname={firstName}&lname={lastName}&delay=3&callback=JSON_CALLBACK';
var data = "?db="+ $rootScope.globals.currentUser.agents[$rootScope.globals.currentDB].db_name;
var url = apiserv+"api.properties.test.php"+data;
$http.jsonp(url).success(function(data){
$scope.data=data;
});
};
var vm = this;
function stateChange(iColumn, bVisible) {
console.log('The column', iColumn, ' has changed its status to', bVisible);
}
// TO-DO: Rather load from a Factory promise, like here: https://github.com/l-lin/angular-datatables/issues/14
// Example here: http://embed.plnkr.co/B9ltNzIRCwswgHqKD5Pp/preview
var data = "?db="+ $rootScope.globals.currentUser.agents[$rootScope.globals.currentDB].db_name;
var url = apiserv+"api.properties.test.php"+data;
vm.dtOptions = DTOptionsBuilder.fromSource(url)
.withBootstrap()
// Active Buttons extension
.withButtons([
//'columnsToggle',
'colvis',
'copy',
'print',
'excel'
])
.withOption('fnRowCallback',myCallback)
.withOption('order', [[ 3, "desc" ]])
.withOption('stateSave',true);
vm.dtColumns = [
DTColumnBuilder.newColumn('File_Num').withTitle('File'),
DTColumnBuilder.newColumn('Description').withTitle('Description'),
DTColumnBuilder.newColumn('street').withTitle('Street'),
DTColumnBuilder.newColumn('bedrooms').withTitle('Bed'),
DTColumnBuilder.newColumn('bathrooms').withTitle('Bath'),
DTColumnBuilder.newColumn('garages').withTitle('Garages'),
DTColumnBuilder.newColumn('car_port').withTitle('Car Ports').notVisible(),
DTColumnBuilder.newColumn('Current_Monthly_Rental').withTitle('Rental').renderWith(function(data, type, full) {
return $filter('currency')(data, 'R ', 2); //could use currency/date or any angular filter
})
];
})
.controller('PagesListCtrl', function($scope,$rootScope,$http, DTOptionsBuilder, DTColumnBuilder, apiserv, $filter, $mdDialog, $mdMedia){
$scope.page = {
title: 'Dashboard',
subtitle: 'Place subtitle here...'
};
});
function myCallback(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td', nRow).bind('click', function() {
//$scope.$apply(function() {
showTabDialog(aData);
//});
});
return nRow;
};
function showTabDialog(ev) {
console.log(ev.file_id);
var data = "?db="+ $rootScope.globals.currentUser.agents[$rootScope.globals.currentDB].db_name+"&file="+ev.file_id;
var url = apiserv+"api.properties.view.php"+data;
console.log(url);
$http({url:url}).then(function(rs){
console.log(rs.data[0]);
$scope.propdata=rs.data[0];
$mdDialog.show({
controller: DialogController,
templateUrl: 'pages/properties/tabDialog.tmpl.html',
//parent: angular.element(document.body),
targetEvent: ev,
//onComplete: afterShowAnimation,
//scope:$scope,
//preserveScope: true
locals: { propdata: $scope.propdata }
})
.then(function(propdata) {
console.log(propdata);
//$scope.$parent.propdata = propdata; // Still old data
//vm.sname = propdata.street;
});
}, function(rs){
console.log("error : "+rs.data+" status : "+rs.status);
});
};
function DialogController($scope, $mdDialog, propdata) {
$scope.propdata = propdata;
$scope.form_size = "form-group-sm";
$scope.font_size = "font-size-sm";
$scope.hide = function(ret) {
//$scope.$apply(); Throws an error
$mdDialog.hide(ret);
}
$scope.changesize = function() {
var fsize = $scope.form_size.split("-").pop(); // "form-group-xs";
switch(fsize) {
case "sm" : fsize = "md";
break;
case "md" : fsize = "lg";
break;
case "lg" : fsize = "sm";
break;
}
$scope.form_size = "form-group-" + fsize;
$scope.font_size = "font-size-" + fsize;
}
}
This is how I had it and it worked, but as you can see the dialog is nested inside the controller and only usefull to that controller:
app
.controller('PropertiesCtrl', function($scope,$rootScope,$http, DTOptionsBuilder, DTColumnBuilder, apiserv, $filter, $mdDialog, $mdMedia){
$scope.page = {
title: 'Dashboard',
subtitle: 'Place subtitle here...'
};
$scope.getProperties = function(){
$scope.data=[];
//var url = 'http://www.filltext.com/?rows=10&fname={firstName}&lname={lastName}&delay=3&callback=JSON_CALLBACK';
var data = "?db="+ $rootScope.globals.currentUser.agents[$rootScope.globals.currentDB].db_name;
var url = apiserv+"api.properties.test.php"+data;
$http.jsonp(url).success(function(data){
$scope.data=data;
});
};
var vm = this;
function stateChange(iColumn, bVisible) {
console.log('The column', iColumn, ' has changed its status to', bVisible);
}
// TO-DO: Rather load from a Factory promise, like here: https://github.com/l-lin/angular-datatables/issues/14
// Example here: http://embed.plnkr.co/B9ltNzIRCwswgHqKD5Pp/preview
var data = "?db="+ $rootScope.globals.currentUser.agents[$rootScope.globals.currentDB].db_name;
var url = apiserv+"api.properties.test.php"+data;
vm.dtOptions = DTOptionsBuilder.fromSource(url)
.withBootstrap()
// Active Buttons extension
.withButtons([
//'columnsToggle',
'colvis',
'copy',
'print',
'excel'
])
.withOption('fnRowCallback',$scope.myCallback)
.withOption('order', [[ 3, "desc" ]])
.withOption('stateSave',true);
vm.dtColumns = [
DTColumnBuilder.newColumn('File_Num').withTitle('File'),
DTColumnBuilder.newColumn('Description').withTitle('Description'),
DTColumnBuilder.newColumn('street').withTitle('Street'),
DTColumnBuilder.newColumn('bedrooms').withTitle('Bed'),
DTColumnBuilder.newColumn('bathrooms').withTitle('Bath'),
DTColumnBuilder.newColumn('garages').withTitle('Garages'),
DTColumnBuilder.newColumn('car_port').withTitle('Car Ports').notVisible(),
DTColumnBuilder.newColumn('Current_Monthly_Rental').withTitle('Rental').renderWith(function(data, type, full) {
return $filter('currency')(data, 'R ', 2); //could use currency/date or any angular filter
})
/*DTColumnBuilder.newColumn('file_id').withTitle('').withClass('dt-right').renderWith(function(data, type, full) {
//return "<a href='#/app/statement/"+full.id+"' class='btn btn-default'>View</a>";
return "<a class=\"btn btn-default\" onclick='$(\"#myview\").click()'>View</a>";
}).notSortable()*/
];
$scope.showTabDialog = function(ev) {
console.log(ev.file_id);
var data = "?db="+ $rootScope.globals.currentUser.agents[$rootScope.globals.currentDB].db_name+"&file="+ev.file_id;
var url = apiserv+"api.properties.view.php"+data;
console.log(url);
$http({url:url}).then(function(rs){
console.log(rs.data[0]);
$scope.propdata=rs.data[0];
$mdDialog.show({
controller: DialogController,
templateUrl: 'pages/properties/tabDialog.tmpl.html',
//parent: angular.element(document.body),
targetEvent: ev,
//onComplete: afterShowAnimation,
//scope:$scope,
//preserveScope: true
locals: { propdata: $scope.propdata }
})
.then(function(propdata) {
console.log(propdata);
//$scope.$parent.propdata = propdata; // Still old data
//vm.sname = propdata.street;
});
}, function(rs){
console.log("error : "+rs.data+" status : "+rs.status);
});
};
function DialogController($scope, $mdDialog, propdata) {
$scope.propdata = propdata;
$scope.form_size = "form-group-sm";
$scope.font_size = "font-size-sm";
$scope.hide = function(ret) {
//$scope.$apply(); Throws an error
$mdDialog.hide(ret);
}
$scope.changesize = function() {
var fsize = $scope.form_size.split("-").pop(); // "form-group-xs";
switch(fsize) {
case "sm" : fsize = "md";
break;
case "md" : fsize = "lg";
break;
case "lg" : fsize = "sm";
break;
}
$scope.form_size = "form-group-" + fsize;
$scope.font_size = "font-size-" + fsize;
}
}
$scope.myCallback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td', nRow).bind('click', function() {
$scope.$apply(function() {
$scope.showTabDialog(aData);
});
});
return nRow;
};
});
Here is factory to store and retrieve user from any controller:
app.factory('Auth', [, function () {
function getUser() {
return user;
}
var currentUser = getUser();
return {
currentUser: currentUser
}]);
And use it:
app.controller('controller', ['Auth', function(Auth) {
var currentUser = Auth.currentUser;
}]);
And don't forget to include new factory on page before controller.

Factory property not updating in controller

I have a property in my factory and a sync() method to update it, but when accessing from controller the value never changes.
My router: (Initialise events with resolve)
'use strict';
myApp
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('app', {
abstract: true,
views: {
'header': {
controller: 'HeaderCtrl',
templateUrl: 'views/header/_header.html'
},
'footer': {
templateUrl: 'views/footer/_footer.html'
}
}
})
.state('app.events', {
url: '^/',
views: {
'content#': {
controller: 'EventsCtrl',
templateUrl: 'views/events/_events.html',
resolve: {
postPromise: ['EventsServ', function(EventsServ) {
return EventsServ.getAll();
}]
}
}
}
})
.state('app.about', {
url: '^/sobre',
views: {
'content#': {
templateUrl: 'views/about/_about.html'
}
}
})
.state('app.contact', {
url: '^/contato',
views: {
'content#': {
controller: 'ContactCtrl',
templateUrl: 'views/contact/_contact.html'
}
}
});
}]);
My controller: (Now sync with facebook and update events)
'use strict';
myApp
.controller('EventsCtrl', ['$scope', 'EventsServ', '$filter', '$window', 'Facebook', 'postPromise', '$log', '$timeout', function($scope, EventsServ, $filter, $window, Facebook, postPromise, $log, $timeout) {
$scope.alerts = [];
$scope.events = EventsServ.all(); // <<<< Never update, keep the same value obtained in router.
$scope.periods = [{
label: 'HOJE',
labelColor: 'success',
startTime: $filter('clearTime')(new Date()),
endTime: $filter('clearTime')(new Date()),
events: []
}, {
label: 'PRÓXIMOS DIAS',
labelColor: 'primary',
startTime: $filter('clearTime')($filter('addDay')(new Date(), 1)),
endTime: $filter('clearTime')($filter('addDay')(new Date(), 8)),
events: []
}, {
label: 'PRÓXIMAS SEMANAS',
labelColor: 'warning',
startTime: $filter('clearTime')($filter('addDay')(new Date(), 9)),
events: []
}];
if (postPromise.status >= 200 && postPromise.status < 300) {
angular.forEach($scope.events, (function(event) {
var eventDate = $filter('clearTime')(event.start_time);
angular.forEach($scope.periods, (function(period) {
if (eventDate >= period.startTime && (eventDate <= period.endTime || !period.endTime)) {
period.events.push(event);
}
}));
}));
Facebook.getLoginStatus(function(response) {
if(response.status === 'connected') {
EventsServ.sync();
$log.info($scope.events);
} else {
$log.info('notLoggedIn');
}
});
} else {
$scope.alerts.push({
type: 'danger',
msg: 'Ooops! Não foi possível buscar os eventos.'
});
}
$scope.openEvent = function(event) {
$window.open('http://facebook.com/events/' + event.id, '_blank');
};
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
}])
.filter('addDay', function() {
return function(date, days) {
return new Date(date.setDate(date.getDate() + days));
};
})
.filter('clearTime', function() {
return function(date) {
var d = new Date(date);
d.setHours(0,0,0,0);
return d;
};
});
I build my view looping through $scope.events.
My factory:
'use strict';
myApp
.factory('EventsServ', ['$http', '$q', 'Facebook', 'PagesServ', '$log', function($http, $q, Facebook, PagesServ, $log) {
var factory = {
events: []
};
factory.all = function() {
return factory.events;
};
factory.getAll = function() {
return $http.get('/events.json')
.success(function(response) {
angular.copy(response, factory.events);
})
.error(function(response) {
$log.error('Failed to get events.');
});
};
factory.sync = function() {
PagesServ.getAll().then(function(response) {
var pages = PagesServ.pages;
var events = [];
var pagesPromises = [];
var eventsPromises = [];
angular.forEach(pages, function(page, key) {
pagesPromises.push(Facebook.api(page.facebook_id, function(response) {
page.facebook_id = response.id;
page.name = response.name;
page.image = 'image.jpg';
delete page.events;
delete page.created_at;
delete page.updated_at;
}));
eventsPromises.push(Facebook.api(page.facebook_id + '/events', function(response) {
var pageEvents = response.data;
angular.forEach(pageEvents, function(event, key) {
event.page = page;
});
events = events.concat(pageEvents);
}));
});
$q.all(pagesPromises).then(function() {
$log.info(pages);
}, function(reason) {
$log.error('Failed to syncs pages: ' + reason);
});
$q.all(eventsPromises).then(function() {
factory.events = [];
angular.forEach(events, function(event, key) {
var eventSynced = {
facebook_id: event.id,
image: '',
name: event.name,
description: event.description,
start_time: event.start_time,
end_time: event.end_time,
going: 397,
address: '...',
page: event.page
}
factory.events.push(eventSynced);
});
$log.info(factory.events); // <<<<< Here the new value is correct!
}, function(reason) {
$log.error('Failed to syncs events: ' + reason);
});
});
};
return factory;
}]);
The new value of the property inside factory is correct when printing to console, but in controller the value never changes, is always [ ].
When have data I want to stay in sync between a controller and a factory, or a factory and multiple controllers, I set the data item I want to access in my controller to the object or array in the factory:
// in your controller change this
$scope.events = EventsServ.all();
// to use the object
$scope.events = EventsServ.events;
In your sync function where you are iterating over the events, push each one into a temporary array, then use angular.copy to make the update to the array available to the controller.
// at the line right before you log the events in the factory use
angular.copy(tempArray, factory.events);
$log.info(factory.events);
More info: http://www.justinobney.com/keeping-angular-service-list-data-in-sync-among-multiple-controllers/

angular, try to display object in ng-repeat fails

i'm writing an mobile application in javascript with angularJS and ionicframework (last beta v.11), i create dinamically an object and want to display all objects inside in a ng-repeat. Why nr-repeat don't display anything?
This is screen from my object:
I use this code for put values in scope:
$scope.distanceSuppliers = myCar;
And this is the code in html:
<ion-item ng-repeat="(id, supplier) in distanceSuppliers">
<div class="items item-button-right" ng-click="openDetails(id)">
{{supplier.name}}<br />
{{supplier.address}}<br />
</div>
</ion-item>
This is my complete code for JS:
.controller('suppliers', function($scope, cw_db, $ionicPopup, $ionicActionSheet, appdelegate, $rootScope, $firebase, $location, $ionicLoading, cw_position) {
$ionicLoading.show({
template: 'Updating data..'
});
var geocoder;
var tot = 0;
var done = 0;
geocoder = new google.maps.Geocoder();
cw_db.getData(cw_db.getSuppliers(), "", function(suppliers) {
cw_position.getPosition(function (error, position) {
suppliers.on('value', function(supp) {
$scope.distanceSuppliers = {};
tot = 0;
done = 0;
supp.forEach(function(childSnapshot) {
tot++;
var childData = childSnapshot.val();
if (childData.address) {
calculateDistance(childData, position.coords.latitude, position.coords.longitude);
}
});
});
$ionicLoading.hide();
});
});
function calculateDistance(childData, usrLat, usrLon) {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [new google.maps.LatLng(usrLat, usrLon)],
destinations: [childData.address],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
done++;
var results = response.rows[0].elements;
childData.distance = results[0].distance.value;
$scope.distanceSuppliers.push(childData);
if (done == tot) {
console.log($scope.distanceSuppliers);
}
}
});
}
$scope.openDetails = function(index) {
//appdelegate.setCallId(index);
//$location.path("/app/supplierDetails");
}
})
what's wrong?
Not sure, but I believe you have a data binding update problem.
Try using the $timeout to force the render:
w_position.getPosition(function (error, position) {
$timeout(function() {
suppliers.on('value', function(supp) {
$scope.distanceSuppliers = {};
tot = 0;
done = 0;
supp.forEach(function(childSnapshot) {
tot++;
var childData = childSnapshot.val();
if (childData.address) {
calculateDistance(childData, position.coords.latitude, position.coords.longitude);
}
});
});
$ionicLoading.hide();
});
});
And don't forget to add the $timeout parameter to the controller:
.controller('suppliers', function($scope, ...<other parameters here>..., $timeout) {
I found the problem! Fix using $scope.$apply();
The problem was that i was writing in a different $scope using this code:
cw_position.getPosition(function (error, position) {
suppliers.on('value', function(supp) {
tot = 0;
done = 0;
supp.forEach(function(childSnapshot) {
tot++;
var childData = childSnapshot.val();
if (childData.address) {
calculateDistance(childData, position.coords.latitude, position.coords.longitude);
}
});
});
$ionicLoading.hide();
});
where cw_position.getPosition call a js with this code:
angular.module('cw_position', [])
.service('cw_position', function() {
this.getPosition = function(callback) {
navigator.geolocation.getCurrentPosition(
function (position) {
return callback(null, position);
},
function(error) {
return callback(error, null);
}
);
}
// Built google maps map option
//
this.getGoogleMapOptions = function (lat, lon, zoom, type) {
if (type == null) {
type = google.maps.MapTypeId.ROADMAP;
}
var mapOptions = {
center: new google.maps.LatLng(lat, lon),
zoom: zoom,
mapTypeId: type
};
return mapOptions;
}
});
navigator.geolocation.getCurrentPosition causes the 'problem'
Thx to all for your help

Resources