Angular and Leaflet : Looping through a promise object and copying its values - angularjs

In my controller, I have a function executed on ng-init:
// Find a list of Messages
$scope.find = function() {
$scope.messages = Messages.query();
};
That's the service behind the query():
'use strict';
//Messages service used to communicate Messages REST endpoints
angular.module('messages').factory('Messages', ['$resource',
function($resource) {
return $resource('messages/:messageId', { messageId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
]);
That's how each messag looks (aka the model):
0: Resource
$$hashKey: "00O"
__v: 0
_id: "546fb196971ba6fd20c8db62"
body: "foobar"
created: "2014-11-21T21:41:42.814Z"
location: Object
lat: 50.827409075117785
lng: 4.318828582763672
Angular has a $scope.markers object in which we can push markers that have lat and lng properties.
I need to go through the $scope.messages, get all location.lat and location.lng values and put them in $scope.markers._id.lat , $scope.markers._id.lng ..
How can we achieve this? I used angular.forEach without getting anything logged:
// Find a list of Messages
$scope.find = function() {
$scope.messages = Messages.query();
console.log($scope.messages);
angular.forEach($scope.messages, function(i, location) {
console.log($scope.messages[i]);
});
};

To access the messages from your query you need to do this:
var messages = Messages.query(function() {
console.log(messages);
});
If that correctly returns your messages to your console, your query is ok and you could then add them to your $scope.markers object:
var messages = Messages.query(function() {
angular.forEach(messages, function(obj, key) {
$scope.markers[obj._id] = {
'lat': obj.location.lat,
'lng': obj.location.lng
};
});
});

Related

How to dynamical set de widgetDefinitions in malhar angular dashboard via rest client?

I have installed malhar-angular-dashboard module and I want to populate some widgetDefinitions with my rest data.
HTML
<div ng-controller="widgetCtrl">
<div dashboard-layouts="layoutOptions" class="dashboard-container"></div>
</div>
widgetRestService
.factory('widgetRestService',['$http','UrlService','$log','$q',
function($http,UrlService,$log,$q){
var serviceInstance = {};
serviceInstance.getInfo = function(){
var request = $http({method: 'GET', url: '/rest/widgets/getListInfoDashboards'})
.then(function(success){
serviceInstance.widgets = success.data;
$log.debug('serviceInstance.widgets SUCCESS',serviceInstance.widgets);
},function(error){
$log.debug('Error ', error);
$log.debug('serviceInstance.widgets ERROR',serviceInstance.widgets);
});
return request;
};
serviceInstance.getAllWidgets = function () {
if (serviceInstance.widgets) {
return serviceInstance.widgets;
} else {
return [];
}
};
return serviceInstance;
}])
My rest service returns me this array of 3 objects :[{"name":"widgetList","title":" "},{"name":"widgetPie","title":" "},{"name":"widgetTable","title":" "}]
OtherService
.factory("OtherService", ["widgetRestService", "$log", "$q",
function (widgetRestService, $log, $q) {
var deferred = $q.defer();
widgetRestService.getInfo().then(function () {
deferred.resolve(widgetRestService.getAllWidgets());
});
return deferred.promise;
}])
Controller
OtherService.then(function(response){
$scope.layoutOptions = { // layout with explicit save
storageId: 'demo-layouts-explicit-save',
storage: localStorage,
storageHash: 'fs4df4d51',
widgetDefinitions:response , //must be a list
defaultWidgets: [],
explicitSave: true,
defaultLayouts: [
{title: 'Layout 1', active: true, defaultWidgets: []}
]
};
$log.debug('layoutOptions =',$scope.layoutOptions);
});
Result
layoutOptions: Object{defaultLayouts:Array[1],
defaultWidgets:Array[0],
explicitSave:true,
storage:Storage,
storageHash:'fs4df4d51',
storageId: 'demo-layouts-explicit-save',
widgetDefinitions: Array[3]}
TypeError: Cannot read property '$$hashKey' of undefined
at Object.extend (http://localhost:9000/bower_components/angular/angular.js:406:14)
at Object.LayoutStorage (http://localhost:9000/bower_components/malhar-angular-dashboard/dist/malhar-angular-dashboard.js:1064:15)
I searched at line 2: Object.LayoutStorage and I found out this:
angular.extend(defaults, options); //options = undefined (should have some keys and my widgetDefinitions array)
angular.extend(options, defaults);
The options variable is undefined only when I want to setup the $scope.layoutOptions within the then callback function.
Any advice how to set / avoid this ?
The problem is that the dashboard-layouts directive will compile before the asynchronous call from OtherService has finished, which means $scope.layoutOptions will be undefined.
A simple solution is to prevent the dashboard-layouts directive from compiling before $scope.layoutOptions is available.
You can do this by using ng-if:
<div ng-if="layoutOptions" dashboard-layouts="layoutOptions" class="dashboard-container">
</div>

Restangular no BaseUrl when do PUT

i'm using Restangular and trying to PUT some data but it seems to lose the BaseUrl.
In the config function i define the BaseUrl for Restangular and others Restangular fields.
Constants.restangularBaseUrl is http://192.168.1.100/api/
RestangularProvider.setBaseUrl(Constants.restangularBaseUrl)
.setRestangularFields({
selfLink: '_links.self.href',
id: '_id',
etag: '_etag'
})
.addResponseInterceptor(function(data, operation, what, url, response, deferred){
if (operation === 'getList') {
var result = data._items;
result._meta = data._meta;
result._links = data._links;
return result;
}
return data;
});
Then i have some models like this:
(function(){
angular.module('models.ebayItems', ['services.constants', 'restangular'])
.service('EbayItems', ['Constants', 'Restangular', function (Constants, Restangular) {
Restangular.extendModel('ebayitems', function(model) {
model.toggleMonitor = function(){
var item = this;
Restangular.one('ebayitems', this._id).patch({active: this.active}, '', {'If-Match': this._etag})
.then(function(data){
item._etag = data._etag;
}, function(error){
console.log('error', error);
});
};
return model;
});
var ebayItems = Restangular.all('ebayitems');
var ebayItemsOneSearch = function(_id){
return ebayItems.customGETLIST('', {where: {searchId: _id}});
};
return {
items: ebayItems,
oneSearch: ebayItemsOneSearch
};
}])
})();
Now when i try to do a put request with an item based on that model:
item.put()
it uses the wrong url, i mean it loses the BaseUrl, so instead of putting at:
http://192.168.1.100/api/ebayitems/12345
it puts at
http://192.168.1.100/ebayitems/12345
resulting in a 404 error.
Why?
What am i doing wrong?
Any help really appreciated.
Thank you
The problem was that setting a selfLink field that was a relative url from the API backend it overrides the BaseUrl.
Removing that field from the config function it worked.
RestangularProvider.setBaseUrl(Constants.restangularBaseUrl)
.setRestangularFields({
id: '_id',
etag: '_etag'
})
.addResponseInterceptor(function(data, operation, what, url, response, deferred){
if (operation === 'getList') {
var result = data._items;
result._meta = data._meta;
result._links = data._links;
return result;
}
return data;
});

Getting the phoneNumber using $cordovaContacts

I'm trying to get all the contacts in the phone using ng-cordova, I success to do that like the following, I create a service in AngularJS:
.factory("ContactManager", function($cordovaContacts) {
return {
getContacts: function() {
var options = {};
options.filter = "";
options.multiple = true;
//get the phone contacts
return $cordovaContacts.find(options);
}
}
})
Also the method find in the ng-cordova is't like the following:
find: function (options) {
var q = $q.defer();
var fields = options.fields || ['id', 'displayName'];
delete options.fields;
navigator.contacts.find(fields, function (results) {
q.resolve(results);
},
function (err) {
q.reject(err);
},
options);
return q.promise;
}
And did the following inside the controller:
ContactManager.getContacts().then(function(result){
$scope.users= result;
}, function(error){
console.log(error);
});
I noticed that in the $scope.users I find the formatted, middleName ..., but I can't find the phoneNumber, how can I get also the phoneNumbers?
If you log the contacts you should see an object with a phoneNumbers array in it.
ContactManager.getContacts().then(function(result){
$scope.users= result;
console.log(result);
...
If you don't it's something else.
I also made a somewhat close mock json of what the return looks like.

AngularJS-MongoLab $resource update error

I am connecting AngularJS with MongoLab and trying to update the "users" collection.
AngularJS resource service:
angular.module("myApp.services", ["ngResource"])
.constant({
DB_URL: "https://api.mongolab.com/api/1/databases/mydb/collections/users/:id",
API_KEY: "[SOME_RANDOM_KEY]"
})
.factory("UsersService", ["$resource", "DB_URL", "API_KEY", function($resource, DB_URL, API_KEY) {
return $resource(DB_URL, { apiKey: API_KEY, id: "#_id.$oid" }, { update: { method: "PUT" }});
}]);
This is how I am trying to update my users collection:
angular.module("myApp", ["myApp.services"])
.controller("AppController", ["$scope", "UsersService", function($scope, UsersService) {
$scope.users = [];
$scope.getAllUsers = function() {
$scope.users = UsersService.query();
};
$scope.updateUser = function(user) { // user: firstName, lastName, email
//delete user._id;
UsersService.update({}, user, function() {
$scope.users = UsersService.query();
console.log("Users updated successfully");
}, function() {
console.log("Some problems updating the user", arguments);
});
};
}]);
When I try to update the user information, it throws an exception stating:
{ "message" : "cannot change _id of a document old:{ _id: ObjectId('[SOME_RANDOM_KEY]'), firstName: \"Anup\", lastName: \"Vasudeva\", email: \"anup.vasudeva#emal.com\" } new:{ _id: {}, firstName: \"Anup\", lastName: \"Vasudeva\", email: \"anup.vasudeva#email.com\" }"
I am new to MongoDB, so I don't understand why it is creating an empty _id object for the new user instance?
Try changing your $scope.updateUser function to the following:
$scope.updateUser = function (user) {
var userId = user._id.$oid;
user._id = undefined;
UsersService.update({id: userId}, user, function () {
$scope.users = UsersService.query();
console.log("Users updated successfully");
}, function () {
console.log("Some problems updating the user", arguments);
});
};
The update/replacement object ('user'), should not contain the _id property when being passed to UsersService.update(). Mongo will not replace the _id value, so the id will stay the same after the update.
One other thing that's changed in this function is that we're passing the user id as the first parameter of the UsersService.update() function so that mongo knows which document to update.

How do I do custom model data parsing in backbone.js?

While using backbone to hit an api, I've found that I need to only include some of the data in the response. The webserver is giving me back metadata in addition to data concerning my objects that I don't need.
The following solution works, but doesn't feel right. Is there a standard way of doing this?
var accountsCollection = new AccountsCollection();
accountsCollection.fetch({success : function(collection){
var results = new AccountsCollection();
collection.each(function(item){
results.add(new AccountModel({
id: item.toJSON().result[0].id,
messageText: item.toJSON().messageText,
address1: item.toJSON().result[0].address1,
address2: item.toJSON().result[0].address2
}));
});
onDataHandler(results);
}});
EDIT: This was my final solution based on the accepted answer:
parse: function(response) {
var accounts = [];
_.each(response['result'], function (account) {
accounts.push(account);
});
return accounts;
}
You could try overriding the Backbone.Collection.parse method and do some crazy underscore stuff. No idea if it fits your data..
var keysILike = ['foo', 'bar'];
AccountsCollection.extend({
parse: function(response) {
return _.compact(_.flatten(_.map(response, function (model) {
var tmp = {};
_.each(_.keys(model), function (key) {
if (_.contains(keysILike, key)) tmp[key] = model[key];
})
return tmp;
})));
}
});
With respect to #Sushanth's awesomeness you definitely want to use this solution:
var keysILike = ['foo', 'bar'];
AccountsCollection.extend({
parse: function(response) {
_.each(response, function (model) {
_.each(_.keys(model), function (key) {
if (!_.contains(keysILike, key)) delete model[key]
})
});
return response;
}
});

Resources