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
Related
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>
I have code like this
(function (app) {
app.controller('productListController', productListController)
productListController.$inject = ['$scope', 'apiService', 'notificationService', '$ngBootbox', '$filter'];
function productListController($scope, apiService, notificationService, $ngBootbox, $filter) {
$scope.products = [];
$scope.page = 0;
$scope.pagesCount = 0;
$scope.getProducts = getProducts;
$scope.keyword = '';
$scope.search = search;
$scope.deleteProduct = deleteProduct;
$scope.selectAll = selectAll;
$scope.deleteMultiple = deleteMultiple;
function deleteMultiple() {
var listId = [];
$.each($scope.selected, function (i, item) {
listId.push(item.ID);
});
var config = {
params: {
checkedProducts: JSON.stringify(listId)
}
}
apiService.del('/api/product/deletemulti', config, function (result) {
notificationService.displaySuccess('Deleted successfully ' + result.data + 'record(s).');
search();
}, function (error) {
notificationService.displayError('Can not delete product.');
});
}
$scope.isAll = false;
function selectAll() {
if ($scope.isAll === false) {
angular.forEach($scope.products, function (item) {
item.checked = true;
});
$scope.isAll = true;
} else {
angular.forEach($scope.products, function (item) {
item.checked = false;
});
$scope.isAll = false;
}
}
$scope.$watch("products", function (n, o) {
var checked = $filter("filter")(n, { checked: true });
if (checked.length) {
$scope.selected = checked;
$('#btnDelete').removeAttr('disabled');
} else {
$('#btnDelete').attr('disabled', 'disabled');
}
}, true);
function deleteProduct(id) {
$ngBootbox.confirm('Are you sure to detele?').then(function () {
var config = {
params: {
id: id
}
}
apiService.del('/api/product/delete', config, function () {
notificationService.displaySuccess('The product hase been deleted successfully!');
search();
}, function () {
notificationService.displayError('Can not delete product');
})
});
}
function search() {
getProducts();
}
function getProducts(page) {
page = page || 0;
var config = {
params: {
keyword: $scope.keyword,
page: page,
pageSize: 20
}
}
apiService.get('/api/product/getall', config, function (result) {
if (result.data.TotalCount == 0) {
notificationService.displayWarning('Can not find any record.');
}
$scope.products = result.data.Items;
$scope.page = result.data.Page;
$scope.pagesCount = result.data.TotalPages;
$scope.totalCount = result.data.TotalCount;
}, function () {
console.log('Load product failed.');
});
}
$scope.getProducts();
}
})(angular.module('THTCMS.products'));
So my problem is when i loading data the application take me some time to load data.
I need load data as soon as
Is the any solution for this?
Since you are loading data via api call, there will be a delay. To handle this delay, you should display a loading screen. Once the data is loaded, the loading screen gets hidden and your main screen is visible. You can achieve this using $http interceptors.
See : Showing Spinner GIF during $http request in angular
The api-call is almost certainly causing the delay. Data may be received slowly via the api-call so you could display any sort of loading text/image to notify the use that the data is being loaded.
If u want the data ready at the time when controller inits, u can add a resolve param and pass the api call as a $promise in the route configuration for this route.
I have to improve my code with reverse geocoding. Now my app get the position by device's GPS.
This is my controller:
.controller('MapCtrl', function($scope, $ionicLoading, $compile) {
function initialise() {
function onSuccess(position){
var myLatlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var mapOptions = {
zoom: 15,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
var map = new google.maps.Map(document.getElementById('map'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
});
$scope.map = map;
}
function onError(error){
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
google.maps.event.addDomListener(window, 'load', initialise);
});
I found in this link a solution, but I'm not be able to integrate it with my code.
Anyone can help me?
This is the function to get address from lat and long.
$scope.geocoder.geocode({ 'latLng': $scope.latlng }, function (results, status)
And you need to include google api's:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&ver=2014-07-18"></script>
After this you must handle the response.
I post some example code.
$scope.geocoder.geocode({ 'latLng': $scope.latlng }, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (results[1]) {
$scope.address = results[1].address_components;
$scope.gps_data.address = $scope.address;
//your code here
// some example results parsing code
var i;
$scope.comune = undefined;
for (i = 0; i < $scope.gps_data.address.length; i += 1) {
if ($scope.gps_data.address[i].types.indexOf("administrative_area_level_3") > -1) {
$scope.comune = $scope.gps_data.address[i].short_name;
console.log($scope.comune);
}
}
if ($scope.comune === undefined) {
for (i = 0; i < $scope.gps_data.address.length; i += 1) {
if ($scope.gps_data.address[i].types.indexOf("locality") > -1) {
$scope.comune = $scope.gps_data.address[i].short_name;
}
}
}
} else {
console.log('Location not found');
$scope.firstExecution = false;
}
} else {
console.log('Geocoder failed due to: ' + status);
$scope.firstExecution = false;
}
});
Anyway, you need to check this documentation for better knwoledgment
https://developers.google.com/maps/documentation/javascript/examples/geocoding-reverse
Here you can find all the tags about the object structure that you recieve from google's api.
I am struggling with angular translate for my ionic app. The thing is that I have a service with data to share between views but I need to translate this data. Unfortunately I just see blank screen without any errors in console.
I would appreciate if someone could help if there is something wrong with that code (I use useStaticFilesLoader):
app.service('customService', function($q, $rootScope, $filter, $translate) {
$rootScope.$on('$translateChangeSuccess', function () {
var $translate = $filter('translate');
return {
items: [
{
id: '1',
title:$translate('TITLE');
}
]
],
getItems: function() {
return this.items;
},
getItem: function(itemId) {
var dfd = $q.defer();
this.items.forEach(function(item) {
if (item.id === itemId) dfd.resolve(item);
});
return dfd.promise;
}
};
});
});
Try something like this:
app.factory('customService', function($rootScope, $translate) {
var items = [],
updateItems = function() {
items.length = 0;
$translate('TITLE').then(function(title) {
items.push({
id: '1',
title: title;
});
});
};
updateItems();
$rootScope.$on('$translateChangeSuccess', updateItems);
return {
items: items,
getItem: function(itemId) {
var result;
items.forEach(function(item) {
if (item.id === itemId) {
result = item;
}
});
return result;
}
}
});
Prettyphoto stopped working after I changed the href url to an angular tag: {{something.uri}}
Javascript:
jQuery(".prettyphoto").prettyPhoto({
theme: 'pp_default',
overlay_gallery: false,
social_tools: false,
deeplinking: false,
theme: 'dark_rounded'
});
$("a[rel^='prettyPhoto']").prettyPhoto();
HTML:
<div ng-show="model.fileList" ng-repeat="fileList in model.fileList">
<a ng-href="{{fileList.uri}}" class="prettyphoto">
<img ng-src="{{fileList.uri}}" class="img-thumbnail" width="100" alt="" />
</a>
</div>
Angular scope from blobstorage:
fileList: [
{
parentContainerName: documents
uri: https://xxxxxx.blob.core.windows.net/documents/20140702.jpg
filename: 20140702.jpg
fileLengthKilobytes: 293
}
]
app.factory('storageService',
["$http", "$resource", "$q",
function ($http, $resource, $q) {
//resource to get summaryRoles
var resourceStorageManager = $resource('/api/storageManager/:id', { id: '#id' });
return {
getFileList: function () {
var deferred = $q.defer();
resourceStorageManager.query(, function (data) {
deferred.resolve(data);
}, function (status) {
deferred.reject(status);
}
);
return deferred.promise;
}
};
}]);
app.controller('startController', ['$scope', '$http', '$timeout', '$upload', 'storageService', 'settings',
function startController($scope, $http, $timeout, $upload, storageService, settings, profileRepository, notificationFactory, $q) {
$http.defaults.headers.common = { 'RequestVerificationToken': $scope.__RequestVerificationToken };
$scope.model = {};
$scope.model.fileList = null;
$scope.model.roundProgressData = {
label: 0,
percentage: 0.0
};
$scope.$on("pic_profileone_main", function (event, profileExtInfo1) {
$scope.changeprofilepicmodel1 = angular.copy(profileExtInfo1);
refreshServerFileList();
});
$scope.$on("pic_profiletwo_main", function (event, profileExtInfo2) {
$scope.changeprofilepicmodel2 = angular.copy(profileExtInfo2);
refreshServerFileList2();
});
$scope.onFileSelect = function ($files, callernumber, foldername, blobtype) {
if (callernumber == 1) {
$scope.blobModel = angular.copy($scope.changeprofilepicmodel1);
$scope.blobModel.folderName = foldername;
$scope.blobModel.blobTypeCode = blobtype;
} else if (callernumber == 2) {
$scope.blobModel = angular.copy($scope.changeprofilepicmodel2);
$scope.blobModel.folderName = foldername;
$scope.blobModel.blobTypeCode = blobtype;
}
$scope.selectedFiles = [];
$scope.model.progress = 0;
// Assuming there's more than one file being uploaded (we only have one)
// cancel all the uploads
if ($scope.upload && $scope.upload.length > 0) {
for (var i = 0; i < $scope.upload.length; i++) {
if ($scope.upload[i] != null) {
$scope.upload[i].abort();
}
}
}
$scope.upload = [];
$scope.uploadResult = [];
$scope.selectedFiles = $files;
// Ok, we only want one file to be uploaded
// let's take the first one and that's all
var $file = $files[0];
// Only first element, single file upload
(function (index) {
$scope.upload[index] = $upload.upload({
url: settings.constants.uploadURL,
headers: { 'myHeaderKey': 'myHeaderVal' },
method: 'POST',
data: $scope.blobModel,
file: $file,
fileFormDataName: 'myFile'
}).then(function (response) {
var look = response;
$scope.model.progress = 100;
// you could here set the model progress to 100 (when we reach this point we now that the file has been stored in azure storage)
$scope.uploadResult.push(response.data);
$scope.$emit('ClearUploadPics');
refreshServerFileList();
}, null, function (evt) {
// Another option is to stop here upadting the progress when it reaches 90%
// and update to 100% once the file has been already stored in azure storage
$scope.model.progress = parseInt(100.0 * evt.loaded / evt.total);
$scope.model.roundProgressData.label = $scope.model.progress + "%";
$scope.model.roundProgressData.percentage = ($scope.model.progress / 100);
});
})(0);
};
function refreshServerFileList() {
storageService.getFileList().then(function (data) {
$scope.model.fileList = data;
}
);
}
function initialize() {
refreshServerFileList();
}
initialize();
$scope.$on("ClearProgressBar", function (event) {
$scope.selectedFiles = null;
});
}]);
I hope this is okay and more readable.