Make change inside app.config() in angularjs - angularjs

I am using googlePlace api in angularJs and I want to change type of places dynamically as needed. Like I use controllers to bind the values in view part using $scope but it's not working in this situation also tried $rootScope.
Tried many other things too but they all are not working and I'm also new to angularJs so don't know much.
Here is code:-
app.config(function(ngGPlacesAPIProvider){
ngGPlacesAPIProvider.setDefaults({
radius:1000000,
types:['electronics_store','bakery','bank','beauty_salon','bicycle_store','book_store','cafe','car_dealer','car_wash','car_repair','clothing_store','dentist','department_store'],
nearbySearchKeys: ['name','geometry', 'reference'],
placeDetailsKeys: ['name','formatted_address', 'formatted_phone_number',
'reference', 'website', 'geometry', 'email'],
});
});
Controller code:-
app.config(function(ngGPlacesAPIProvider, ngGPlacesDefaults){
ngGPlacesAPIProvider.setDefaults(ngGPlacesDefaults);
});
app.controller('scdfindCustomerCtrl',function($scope,ngGPlacesAPI,$http,ngGPlacesDefaults){
ngGPlacesDefaults.types = ["atm"];
$scope.getDetails = function(ref){
$scope.details = ngGPlacesAPI.placeDetails({reference:ref}).then(
function (data) {
$scope.det=data;
console.log(data);
return data;
});
}
$scope.positions = [{lat:37.7699298,lng:-122.4469157}];
$scope.addMarker = function(event) {
var ll = event.latLng;
$scope.positions.push({lat:ll.lat(), lng: ll.lng()});
$scope.data = ngGPlacesAPI.nearbySearch({latitude:ll.lat(), longitude:ll.lng()}).then(
function(data){
$scope.person=data;
console.log(data);
return data;
});
}
So basically I want to change "types:[]" array from view part.
Any help would be appreciated.

You could have those set of default values as an constant, so that you could get those value inside config phase directly, as angular constants are accessible over there & in all other component of angular like controller, factory, directive, etc just by injecting dependency of it.
Constant
app.constant('ngGPlacesDefaults', {
radius:1000000,
types:['electronics_store','bakery','bank','beauty_salon','bicycle_store','book_store','cafe','car_dealer','car_wash','car_repair','clothing_store','dentist','department_store'],
nearbySearchKeys: ['name','geometry', 'reference'],
placeDetailsKeys: ['name','formatted_address', 'formatted_phone_number',
'reference', 'website', 'geometry', 'email'],
});
})
Config
app.config(function(ngGPlacesAPIProvider, ngGPlacesDefaults){
ngGPlacesAPIProvider.setDefaults(ngGPlacesDefaults);
});
Whenever you wanted to change the value of ngGPlacesDefaults configuration, you can have handle to those value by injecting ngGPlacesDefaults dependency
app.controller('myController', function($scope, ngGPlacesDefaults){
//other code here
ngGPlacesDefaults.types = ["some", "different", "values"]; //you could change value like this
})

I found a different way to solve this problem. You don't need to extra just pass the types:[] as an argument in 'nearBySearch' function
$scope.data = ngGPlacesAPI.nearbySearch({latitude:ll.lat(), longitude:ll.lng(), types:[$scope.business.selected.businessType]}).then(
function(data){
$scope.person=data;
console.log(data);
return data;
});
"$scope.business.selected.businessType" is bindable dynamically from view, that's it.

Related

Angular Restangular on sortable, how to save?

I need to change the order of scope, save but me back an error that save() is not a function.
I'm using restangular to create the objects.
The function is triggered Onsort, I tried using http, but also gives me error.
$scope.onChange = function() {
ApiRestangular.all($scope.section).getList($scope.query).then(function(res){
$scope.items = res;
order = ApiRestangular.copy(res);
console.log(order);
$scope.sortOptions = {
animation : 150,
onSort: function(){
order.put().then(function(){
toast.msgToast($scope.section+ ' ...Ordem atualizada!');
});
}
};
});
};

Can I change variables of pre defined constants in angularJs?

I defined a constant 'ngGPlacesDefaults' which sets default values of 'google place search' config file. But now I want to change the values of defaults dynamically i.e types:['airport'], types['backery'] etc as needed. And for this I injected the above constant inside my controller and tried to set defaults from inside my controller. But it's not working I mean It's not changing the values.
I am providing code for config file, constant and controller.
Any help would be much appreciated!!
map config code->
app.config(function(ngGPlacesAPIProvider, ngGPlacesDefaults){
ngGPlacesAPIProvider.setDefaults(ngGPlacesDefaults);
});
app.constant code->
app.constant('ngGPlacesDefaults', {
radius:1000000,
types:['shoe_store'],
nearbySearchKeys: ['name','geometry', 'reference'],
placeDetailsKeys: ['name','formatted_address', 'formatted_phone_number',
'reference', 'website', 'geometry', 'email']
});
controller code ->
app.controller('scdfindCustomerCtrl',function($scope,ngGPlacesAPI,$http,ngGPlacesDefaults){
ngGPlacesDefaults.types = ["electronics_store"];
$scope.getDetails = function(ref){
$scope.details = ngGPlacesAPI.placeDetails({reference:ref}).then(
function (data) {
$scope.det=data;
console.log(data);
return data;
});
}
$scope.positions = [{lat:37.7699298,lng:-122.4469157}];
$scope.addMarker = function(event) {
var ll = event.latLng;
$scope.positions.push({lat:ll.lat(), lng: ll.lng()});
$scope.data = ngGPlacesAPI.nearbySearch({latitude:ll.lat(), longitude:ll.lng()}).then(
function(data){
$scope.person=data;
console.log(data);
return data;
});
}
....some more code...
});
In current scenario I want this code to show the list of 'electronics_store' but It's showing list of 'shoe_store'.

Call action on page loading in angular

I have the following angular code:
application.controller('ImageController', function ImageController($scope, ImageService, ngDialog) {
$scope.open = function (image) {
ngDialog.open({
className: 'modal',
plain: false,
scope: scope,
template: 'image'
});
}
};
On page loading, when the url has the parameters source and key:
http://www.google.pt/?source=1&key=sdfd-sd-sf
I would like to call open and pass an image with:
image.source = 1;
image.key = sdfd-sd-sf;
How can I do this?
UPDATE
I tried to use ngroute:
$routeProvider
.when('/:source?/:key?',
{
controller: "ImageController"
}
)
with the following route:
domain.com/?source=ddf&key=23jf-34j
On ImageController I tried to get the parameters source and key using:
var image = { source: $routeParams.source, key: $routeParams.key };
if (image.source != null && image.key != null) {
open(image);
}
But both source and key are undefined. Any idea why?
If you're using ngRoute, you can inject $routeParams into your controller and simply do:
image.source = $routeParams.source;
image.key = $routeParams.key;
Nice egghead video about it: https://thinkster.io/egghead/routeparams-api/
UPDATE
There's no need to specify query parameter names in when (it's only needed when using paths like domain.com/source/123/key/456), so this is wrong:
.when('/:source?/:key?',
It should be just:
.when('/',
While your URL has the hashbang (or html5mode):
domain.com/#/?source=ddf&key=23jf-34j
then this will work just fine:
var image = { source: $routeParams.source, key: $routeParams.key };
Note that if you're not using ng-view the parameters won't be available due to their async nature, so you need to use this watcher in your controller:
$scope.$on('$routeChangeSuccess', function() {
console.log($routeParams);
});
or, if you inject $route instead of $routeParams, you can use:
$scope.$on('$routeChangeSuccess', function() {
console.log($route.current.params);
});
it will return the same object.
UPDATE 2
After a little research, seems like by far the easiest way to do it is to inject $location service, and simply use:
var params = $location.search();
var image = { source: params.source, key: params.key };
Here is a simple example with html5 mode on (will work with your original URL): http://run.plnkr.co/sElZhTrI4JvGc0if/?source=SomeSrc&key=SomeKey
And the full Plunker: http://plnkr.co/edit/Jxol8e7YaghbNScICHqW

Service - Cannot read property of undefined

I am trying to put together a service for my controllers. But I keep getting an error saying
"Cannot read property 'industriesArr' of undefined". I'm pretty sure I'm misunderstanding something fundamental, so please educate me.
Service:
angular.module('core').service('FormService', function() {
var data = {
'industriesArr': [
'Alcoholic Drinks','Animals and Pets','Arts and Entertainment',
'Baby and Toddler','Banking','Beauty and Personal Care','Building and Construction',
'Clothing and Footwear','Communication Services','Confectionary and Snacks',
'Dining and Nightlife',
'Education and Jobs','Electronics and Technology',
'Family and Community','Fast food and Restaurant','Financial Services','Food and Groceries',
'Games and Toys','Government and Law',
'Health','Home and Garden',
'Insurances','Internet, Telecom and Software',
'Jewelry and Luxury',
'Leisure',
'Media and Publications',
'News','Non-alcoholic Drinks','Non-profit Organisation',
'Occasions and Gifts','Office Supplies','Other',
'Personal Accessories','Pharmaceutical and Medical','Political Organisation','Professional Services','Public Interest',
'Real Estate','Retail Services and Wholesaler',
'Sports Accessories','Sports and Fitness',
'Tobacco','Tourism and Travel','Transport',
'Utilities',
'Vehicles'
]
};
return data;
});
Controller:
angular.module('core').controller('SignupController', ['$scope', 'FormService', function($scope, FormService) {
$scope.industriesArr = FormService.data.industriesArr;
});]);
HTML is simply:
<p ng-repeat="industry in industriesArr">{{industry}}</p>
The way you are returning data you should use factory. So instead of this
angular.module('core').service('FormService', function() {
Use this
angular.module('core').factory('FormService', function() {
When the service syntax is used Angular treats it as Constructor function. If you want to use service do not do return and define your properties\functions on this such as
this.industriesArr=[...];
Write your module like this :
angular.module('core').service('FormService', function() {
return{
getData: function() {
return { 'industriesArr': [...]; }
}
}
});
Made a silly mistake and put FormService in the incorrect order when associating it with my controller.

Proper place for data-saving logic in AngularJS

App design question. I have a project which has a very large number of highly customized inputs. Each input is implemented as a directive (and Angular has made this an absolute joy to develop).
The inputs save their data upon blur, so there's no form to submit. That's been working great.
Each input has an attribute called "saveable" which drives another directive which is shared by all these input types. the Saveable directive uses a $resource to post data back to the API.
My question is, should this logic be in a directive at all? I initially put it there because I thought I would need the saving logic in multiple controllers, but it turns out they're really happening in the same one. Also, I read somewhere (lost the reference) that the directive is a bad place to put API logic.
Additionally, I need to introduce unit testing for this saving logic soon, and testing controllers seems much more straightforward than testing directives.
Thanks in advance; Angular's documentation may be… iffy… but the folks in the community are mega-rad.
[edit] a non-functional, simplified look at what I'm doing:
<input ng-model="question.value" some-input-type-directive saveable ng-blur="saveModel(question)">
.directive('saveable', ['savingService', function(savingService) {
return {
restrict: 'A',
link: function(scope) {
scope.saveModel = function(question) {
savingService.somethingOrOther.save(
{id: question.id, answer: question.value},
function(response, getResponseHeaders) {
// a bunch of post-processing
}
);
}
}
}
}])
No, I don't think the directive should be calling $http. I would create a service (using the factory in Angular) OR (preferably) a model. When it is in a model, I prefer to use the $resource service to define my model "classes". Then, I abstract the $http/REST code into a nice, active model.
The typical answer for this is that you should use a service for this purpose. Here's some general information about this: http://docs.angularjs.org/guide/dev_guide.services.understanding_services
Here is a plunk with code modeled after your own starting example:
Example code:
var app = angular.module('savingServiceDemo', []);
app.service('savingService', function() {
return {
somethingOrOther: {
save: function(obj, callback) {
console.log('Saved:');
console.dir(obj);
callback(obj, {});
}
}
};
});
app.directive('saveable', ['savingService', function(savingService) {
return {
restrict: 'A',
link: function(scope) {
scope.saveModel = function(question) {
savingService.somethingOrOther.save(
{
id: question.id,
answer: question.value
},
function(response, getResponseHeaders) {
// a bunch of post-processing
}
);
}
}
};
}]);
app.controller('questionController', ['$scope', function($scope) {
$scope.question = {
question: 'What kind of AngularJS object should you create to contain data access or network communication logic?',
id: 1,
value: ''
};
}]);
The relevant HTML markup:
<body ng-controller="questionController">
<h3>Question<h3>
<h4>{{question.question}}</h4>
Your answer: <input ng-model="question.value" saveable ng-blur="saveModel(question)" />
</body>
An alternative using only factory and the existing ngResource service:
However, you could also utilize factory and ngResource in a way that would let you reuse some of the common "saving logic", while still giving you the ability to provide variation for distinct types of objects / data that you wish to save or query. And, this way still results in just a single instantiation of the saver for your specific object type.
Example using MongoLab collections
I've done something like this to make it easier to use MongoLab collections.
Here's a plunk.
The gist of the idea is this snippet:
var dbUrl = "https://api.mongolab.com/api/1/databases/YOURDB/collections";
var apiKey = "YOUR API KEY";
var collections = [
"user",
"question",
"like"
];
for(var i = 0; i < collections.length; i++) {
var collectionName = collections[i];
app.factory(collectionName, ['$resource', function($resource) {
var resourceConstructor = createResource($resource, dbUrl, collectionName, apiKey);
var svc = new resourceConstructor();
// modify behavior if you want to override defaults
return svc;
}]);
}
Notes:
dbUrl and apiKey would be, of course, specific to your own MongoLab info
The array in this case is a group of distinct collections that you want individual ngResource-derived instances of
There is a createResource function defined (which you can see in the plunk and in the code below) that actually handles creating a constructor with an ngResource prototype.
If you wanted, you could modify the svc instance to vary its behavior by collection type
When you blur the input field, this will invoke the dummy consoleLog function and just write some debug info to the console for illustration purposes.
This also prints the number of times the createResource function itself was called, as a way to demonstrate that, even though there are actually two controllers, questionController and questionController2 asking for the same injections, the factories get called only 3 times in total.
Note: updateSafe is a function I like to use with MongoLab that allows you to apply a partial update, basically a PATCH. Otherwise, if you only send a few properties, the entire document will get overwritten with ONLY those properties! No good!
Full code:
HTML:
<body>
<div ng-controller="questionController">
<h3>Question<h3>
<h4>{{question.question}}</h4>
Your answer: <input ng-model="question.value" saveable ng-blur="save(question)" />
</div>
<div ng-controller="questionController2">
<h3>Question<h3>
<h4>{{question.question}}</h4>
Your answer: <input ng-model="question.value" saveable ng-blur="save(question)" />
</div>
</body>
JavaScript:
(function() {
var app = angular.module('savingServiceDemo', ['ngResource']);
var numberOfTimesCreateResourceGetsInvokedShouldStopAt3 = 0;
function createResource(resourceService, resourcePath, resourceName, apiKey) {
numberOfTimesCreateResourceGetsInvokedShouldStopAt3++;
var resource = resourceService(resourcePath + '/' + resourceName + '/:id',
{
apiKey: apiKey
},
{
update:
{
method: 'PUT'
}
}
);
resource.prototype.consoleLog = function (val, cb) {
console.log("The numberOfTimesCreateResourceGetsInvokedShouldStopAt3 counter is at: " + numberOfTimesCreateResourceGetsInvokedShouldStopAt3);
console.log('Logging:');
console.log(val);
console.log('this =');
console.log(this);
if (cb) {
cb();
}
};
resource.prototype.update = function (cb) {
return resource.update({
id: this._id.$oid
},
angular.extend({}, this, {
_id: undefined
}), cb);
};
resource.prototype.updateSafe = function (patch, cb) {
resource.get({id:this._id.$oid}, function(obj) {
for(var prop in patch) {
obj[prop] = patch[prop];
}
obj.update(cb);
});
};
resource.prototype.destroy = function (cb) {
return resource.remove({
id: this._id.$oid
}, cb);
};
return resource;
}
var dbUrl = "https://api.mongolab.com/api/1/databases/YOURDB/collections";
var apiKey = "YOUR API KEY";
var collections = [
"user",
"question",
"like"
];
for(var i = 0; i < collections.length; i++) {
var collectionName = collections[i];
app.factory(collectionName, ['$resource', function($resource) {
var resourceConstructor = createResource($resource, dbUrl, collectionName, apiKey);
var svc = new resourceConstructor();
// modify behavior if you want to override defaults
return svc;
}]);
}
app.controller('questionController', ['$scope', 'user', 'question', 'like',
function($scope, user, question, like) {
$scope.question = {
question: 'What kind of AngularJS object should you create to contain data access or network communication logic?',
id: 1,
value: ''
};
$scope.save = function(obj) {
question.consoleLog(obj, function() {
console.log('And, I got called back');
});
};
}]);
app.controller('questionController2', ['$scope', 'user', 'question', 'like',
function($scope, user, question, like) {
$scope.question = {
question: 'What is the coolest JS framework of them all?',
id: 1,
value: ''
};
$scope.save = function(obj) {
question.consoleLog(obj, function() {
console.log('You better have said AngularJS');
});
};
}]);
})();
In general, things related to the UI belong in a directive, things related to the binding of input and output (either from the user or from the server) belong in a controller, and things related to the business/application logic belong in a service (of some variety). I've found this separation leads to very clean code for my part.

Resources