Allow dynamic parameter name for Angular ngResource call - angularjs

I'm trying to use a custom Angular directive with a custom attribute, i.e. :filterBy=:filter. This is being done with a custom directive like this:
<foo filterBy=location filter=ABC></foo>
The service:
function Foo($resource) {
return $resource(base + 'Foo');
}
The ngResource call:
var filterBy = attrs.filterBy;
var getSegments = Foo.get({filterBy: attrs.filter, limit: attrs.limit, offset: attrs.offset});
returns this:
http://localhost:8000/base/Foo?filterBy=ABC&limit=30 (notice it says "filterBy" instead of location")
It should be returning this resource instead:
http://localhost:8000/base/Foo?locations=Bar&limit=30
It seems the filterBy is being turned into a string in the ngResource call. I wan't it to use the value of the attrs.filterBy, but it doesn't like dot notation in the parameter value.
I've also tried this:
var getFilter = function() {
return attrs.filterBy;
};
But when I do that, the resource URL turns into:
http://localhost:8000/base/Foo?getFilter=Bar&limit=30
Note the "getFilter" is the parameter now. So is there any way to create a custom parameter?

var filterBy = attrs.filterBy;
var params = {limit: attrs.limit, offset: attrs.offset};
params[filterBy] = attrs.filter;
var getSegments = Foo.get(params);
When you write filterBy: value then filterBy is an identifier. It's static. It has no relation whatsoever to any variable.
params[filterBy] = attrs.filter; on the other hand dynamically adds a property and the value within the brackets is an expression that can be resolved to a string. So it can be a variable.

Related

Value from $rootScope is not loaded properly

So I'm basically trying to get a property from my $rootScope when the page loads. I need this property so I can display the value in my form.
After testing this:
console.log("DEBUG $rootScope", $rootScope);
console.log("DEBUG $rootScope.localClient", $rootScope.localClient);
I've noticed that $rootScope contains a localClient property, but $rootScope.localClient is undefined. Why is this?
See console screen below.
Here is where I fill the localClient object
function setClient(client, tvaNumber) {
if (tvaNumber) {
if (angular.isUndefined($rootScope.localClient))
$rootScope.localClient = {};
$rootScope.localClient[tvaNumber] = client;
}
}
Try accessing it like this,
console.log("DEBUG $rootScope.localClient", $rootScope['localClient']);
You must make sure the attribute loaded before use it, because JavaScripte always pass a reference to an object. Or you can try console.log(JSON.parse(JSON.stringify($rootScope)) get the real value.
One example:
var a = {}; console.log(a);a.test = '1';

Accessing single json value via Angular?

my API returns this value:
{"id":1,"name":"Test"}
In Angular I did this call to retrieve that value:
$scope.supplier = Suppliers.query({supplierId: $routeParams.id});
But now in my template I do this:
{{supplier.name}}
Even {{ supplier }} does not give me anything.
but this is empty. Why is this the case?
Thanks!
The query function returns a callback, try this:
Suppliers.query({supplierId: $routeParams.id}, function(suppliers) => {
$scope.supplier = suppliers[0];
});
Since query returns a list you need to take only the first from the list.
var supplier = Suppliers.query({supplierId: $routeParams.id},{_id:0,name:1});
$scope.supplier=supplier[0].name;

Use constant property to build another property inside the same constant angularjs

In short my problem is this: I want to use angular constant functionality to save values that I will need in my app. I was wandering if one could build a property using the value of another property of the same constant. Like this:
app.constant("url", {
basicUrl: "/svc",
managementPanel: basicUrl + "/managemnent.html"
// and so on...
});
Is there any way one can achieve this? I tried using the "this" keyword but it referenced the window object.
You can put it all to function:
(function() {
var constant = {};
constant.base = 'base';
constant.nested = constant.base + '/nested';
constant.nested2 = constant.nested + '/nested2';
app.constant('test', constant)
})();
You will need to use a factory instead of the constant shorthand for this.
app.factory("url", function() {
var url = {};
url.basicUrl = "/svc";
url.managementPanel = url.basicUrl + "/managemnent.html";
return url;
})

backbone.js set in model initialize not effecting models in collection

While performing a fetch() on my backbone collection, and instantiating models as children of that collection, I want to add one more piece of information to each model.
I thought that I could do this using set in the model initialize. (My assumption is that fetch() is instantiating a new model for each object passed into it. And therefore as each initialize occurs the extra piece of data would be set.
To illustrate my problem I've pasted in four snippets, first from my collection class. Second the initialize function in my model class. Third, two functions that I use in the initialize function to get the needed information from the flickr api. Fourth, and finally, the app.js which performs the fetch().
First the collection class:
var ArmorApp = ArmorApp || {};
ArmorApp.ArmorCollection = Backbone.Collection.extend({
model: ArmorApp.singleArmor,
url: "https://spreadsheets.google.com/feeds/list/1SjHIBLTFb1XrlrpHxZ4SLE9lEJf4NyDVnKnbVejlL4w/1/public/values?alt=json",
//comparator: "Century",
parse: function(data){
var armorarray = [];
var entryarray = data.feed.entry;
for (var x in entryarray){
armorarray.push({"id": entryarray[x].gsx$id.$t,
"Filename": entryarray[x].gsx$filename.$t,
"Century": entryarray[x].gsx$century.$t,
"Date": entryarray[x].gsx$date.$t,
"Country": entryarray[x].gsx$country.$t,
"City": entryarray[x].gsx$city.$t,
"Type": entryarray[x].gsx$type.$t,
"Maker": entryarray[x].gsx$maker.$t,
"Recepient": entryarray[x].gsx$recipient.$t,
"Flickrid": entryarray[x].gsx$flickrid.$t,
"FlickrUrl": "", //entryarray[x].gsx$flickrurl.$t,
"FlickrUrlBig": ""//entryarray[x].gsx$flickrurlbig.$t,
});
}
return armorarray;
}
});
Second, the initialization in my model.
initialize: function(){
//console.log("A model instance named " + this.get("Filename"));
item = this;
var flickrapi = "https://api.flickr.com/services/rest/?&method=flickr.photos.getSizes&api_key=<my_apikey>&photo_id=" + this.get("Flickrid") + "&format=json&jsoncallback=?";
sources = getFlickrSources(flickrapi);
sources.then(function(data){
sourceArray = parseFlickrResponse(data);
FlickrSmall = sourceArray[0].FlickrSmall;
console.log (FlickrSmall);
item.set("FlickrUrl", FlickrSmall);
console.log(item);
});
Notice here how I'm getting the "Flickrid" and using to get one more piece of information and then trying to add it back into the model with item.set("FlickrUrl", FlickerSmall);
console.log confirms that the property "FlickrUrl" has been set to the desired value.
Third, these are the functions my model uses to get the information it needs for the flicker api.
var getFlickrSources = function(flickrapi){
flickrResponse = $.ajax({
url: flickrapi,
// The name of the callback parameter, as specified by the YQL service
jsonp: "callback",
// Tell jQuery we're expecting JSONP
dataType: "jsonp"})
return flickrResponse;
}
var parseFlickrResponse = function(data){
flickrSourceArray = []
if (data.stat == "ok"){
sizeArray = data.sizes.size;
for (var y in sizeArray){
if (sizeArray[y].label == "Small"){
flickrSourceArray.push({"FlickrSmall": sizeArray[y].source});
}
else if (sizeArray[y].label == "Large"){
flickrSourceArray.push({"FlickrLarge": sizeArray[y].source});
}
}
}
return flickrSourceArray
}
But, fourth, when I try to perform the fetch and render the collection, I only get objects in my collection without the FlickrUrl property set.
//create an array of models and then pass them in collection creation method
var armorGroup = new ArmorApp.ArmorCollection();
armorGroup.fetch().then(function(){
console.log(armorGroup.toJSON());
var armorGroupView = new ArmorApp.allArmorView({collection: armorGroup});
$("#allArmor").html(armorGroupView.render().el);
});
var armorRouter = new ArmorApp.Router();
Backbone.history.start();
The console.log in this last snippet prints out all the objects/models supposedly instantiated through the fetch. But none of them include the extra property that should have been set during the initialization.
Any ideas what is happening?
What is this function ? getFlickrSources(flickrapi)
Why are you using this.get in the initialize function. Honestly it looks over-complicated for what you are trying to do.
If you want to set some parameter when you instantiate your model then do this var model = new Model({ param:"someparam", url:"someurl",wtv:"somewtv"});
If the point is to update your model just write an update function in your model something like update: function (newparam) { this.set;... etc and call it when you need it.
If I read you well you just want to set some params when your model is instantiated, so just use what I specified above. Here is some more doc : http://backbonejs.org/#Model-constructor
I hope it helps.
edit:
Put your call outside your model, you shouldn't (imo) make call inside your model this way it seems kinda dirty.
Sources.then(function(flickrdata) {
var mymodel = new Model({flicker:flickrdata.wtv});
});
It would be cleaner in my opinion.

How can I pass a parameter to an ng-click function?

I have a function in my controller that looks like the following:
AngularJS:
$scope.toggleClass = function(class){
$scope.class = !$scope.class;
}
I want to keep it general by passing the name of the class that I want to toggle:
<div class="myClass">stuff</div>
<div ng-click="toggleClass(myClass)"></div>
But myClass is not being passed to the angular function. How can I get this to work? The above code works if I write it like this:
$scope.toggleClass = function(){
$scope.myClass = !$scope.myClass;
}
But, this is obviously not general. I don't want to hard-code in the class named myClass.
In the function
$scope.toggleClass = function(class){
$scope.class = !$scope.class;
}
$scope.class doesn't have anything to do with the paramter class. It's literally a property on $scope called class. If you want to access the property on $scope that is identified by the variable class, you'll need to use the array-style accessor:
$scope.toggleClass = function(class){
$scope[class] = !$scope[class];
}
Note that this is not Angular specific; this is just how JavaScript works. Take the following example:
> var obj = { a: 1, b: 2 }
> var a = 'b'
> obj.a
1
> obj[a] // the same as saying: obj['b']
2
Also, the code
<div ng-click="toggleClass(myClass)"></div>
makes the assumption that there is a variable on your scope, e.g. $scope.myClass that evaluates to a string that has the name of the property you want to access. If you literally want to pass in the string myClass, you'd need
<div ng-click="toggleClass('myClass')"></div>
The example doesn't make it super clear which you're looking for (since there is a class named myClass on the top div).

Resources