i am new to AngularJs. I am trying to get the values from json based on search key word and displaying that related data.
Below is my json format
{"abc":[
{ "url":"abc.json"}
],
"bbc":[
{"url":"bbc.json"}
]
}
i am comparing the key with entered search word. If it matches then i need to load the separate json which is related to found key. I am able to compare the search word with key, but when i am trying to get the value am getting total value like url=abc.json, instead of this i've to get only abc.json. My controller code is as follows
function getDetailsController($scope,$http) {
$scope.search = function() {
$http.get("searchInfo.json").success(function(response) {
angular.forEach(response, function(value, key) {
if(angular.equals(key, $scope.searchText)){
$scope.url = value;
$http.get(url).success(function(response) {
$scope.details = response;
});
}
});
});
};
}
I have tried in diffrent ways but i was not able to get the value. Could you please help me on this.
In your JSON, '"abc"': is a key, and its corresponding value is
[{ "url":"abc.json"}]
That is an array containing a single object, the object containing a single key: "url".
So, to access this URL, you simply need
value[0].url
This structure is quite strange though. I don't really understand the point of wrapping the object inside an array.
Related
I am working on Angular 6 and i want to post an array of JSON objects using a service class.
The following is my function
getrerun(data,file){
this.post=[];
for(var i=0;i<data.length;i++)
{
this.rerun.storeno=data[i].storeNo;
this.rerun.filetype=data[i].loadtype;
this.rerun.outboundsystem[0]=file;
this.rerun.createdate=data[i].createdDate;
this.post[i]=this.rerun;
console.log("------>"+JSON.stringify(this.rerun)+"------->"+JSON.stringify(this.post));
}
this.newurl=this.devurl+"rerun";
return this.http.post<any>(this.newurl,this.post);
}
newurl is the url of the rest api that i want to hit and this.post is the array that i am sending
The value of data is following:
[{"lastDate":"2019-02-20 12:36:27","storeNo":"G015","country":"SG","serviceStatus":"FAIL","createdDate":"2019-01-04 11:53:56","loadtype":"F"},{"lastDate":"2019-02-20 10:54:00","storeNo":"G121","country":"SG","serviceStatus":"FAIL","createdDate":"2019-01-23 16:29:33","loadtype":"F"}]
and file is 'TP';
However the post array that I am getting is this:
[{"outboundsystem":["TP"],"storeno":"G121","filetype":"F","createdate":"2019-01-23 16:29:33"},{"outboundsystem":["TP"],"storeno":"G121","filetype":"F","createdate":"2019-01-23 16:29:33"}]
this basically means that both the entries in the array are the same i.e this.post[0].storeno is same as this.post[1].storeno. However, they should have two different values.
What do I do about this?
I've a REST api that returns the list of locales as dictionary:
{
"en-uk": "English UK",
"en-us": "English USA",
...
}
This dictionary is correctly ordered alphabetically by value.
When AngularJS receives it via HTTP, the dictionary gets automatically re-sorted by key, so when I bind to a select element the list of options is ordered by key, and the alphabetical order by key doesn't match the one by value, I get a wrong sorting.
The problem I suppose is due to the fact that such dictionary becomes basically one object with 800+ properties. How do I sort it by value?
First: You have to find all keys.
Second: Iterate all the keys.
Third: Then sort the array with values.
Please use the following:
let obj = {
"en-us": "English USA",
"en-uk": "English UK"
};
// Get an array of the keys:
let keys = Object.keys(obj);
// Then sort by using the keys to lookup the values in the original object:
keys.sort(function(a, b) { return obj[a] > obj[b] });
console.log(keys);
console.log(obj[keys[0]]);
You can modify the way you send the response from the server. Instead of sending the response as an object, send the stringified object.
The problem is indeed you cannot sort the values of the properties of an object. So I convert it to an array before binding it:
So,
languageResource.getCultures().then(function(cultures) {
vm.availableCultures = cultures;
});
becomes
languageResource.getCultures().then(function (culturesDictionary) {
var cultures = [];
angular.forEach(culturesDictionary, function (value, key) {
cultures.push({
lcid: key,
name: value
});
});
vm.availableCultures = cultures;
});
Seen this when the key is numerical. If the key's data type is string than it would keep its sorted state after an API call. If the key's data type is numerical, than, you would need set the key's value as a string and even add single quotes before and after the key's value, before the API sends it back.
I haven't tried the approach to stringfy the dictionary in the API. After the call you would parse the string back to an object with something like JSON.parse(string) might be your best bet.
I have a dictionary of type {name: value}
A = {
name: x,
name: y,
name: z
}
I want to fetch a collection (consisting of models having one of their attribute as 'name'), but to be optimal I want to fetch such that the value of the attribute 'name' exists in my dictionary.
Is there a way to do specific filtering like that?
If you're doing the filtering client-side, overriding the filter method is really NOT the way to go.
Now you no longer have it available, should you need it later. Also, modifying the collection itself from within the filter method is an undesirable sideeffect.
Instead you should be using the parse method, which will automatically be called when fetching the collection.
Now as I understand it, you want to limit the fetched set to models with names matching the keys in your dictionary.
If so, I would do the following:
parse: function(response, options) {
// Do we want to filter the response?
if (options.filterNames) {
// Filter
response = _.filter(response, function(obj) {
// Check if this model name is one of the allowed names
return _.contains(options.filterNames, obj.name);
});
}
// Backbone will use the return value to create the collection
return response;
}
And then call fetch using
someCollection.fetch({filterNames: _.keys(someDictionary)});
If you're certain, you will always be filtering the collection on fetch, you can omit passing the option and just use the dictionary within parse.
Alternatively you could create a fetchFiltered() method on the collection, which would then invoke the line above.
After investigations and trials, here are the two ways this can be resolved:
1. Client side filtering after fetching the collection from the server. This is a less optimal method, especially when the collection is huge. In situations when you really want 5 models out of a 1000 model collection, it can be an overkill. But if the server side has no logic of accepting and using the filtering client side filtering should look something like:
Overload the collection filter code something like:
var filter = {
filter: function() {
var results = _.filter(this.models, function(model) {
// Perform the check on this model, like compare it to your local dict
if (checkPassed) {
return true;
}
return false;
});
results = _.map(results, function(model) {
return model.toJSON();
});
// Reset the existing collection to filtered models
this.reset(results) ;
};
var ExtendedCollection = OriginalCollection.extend(filter);
Pass a filter option in the fetch ajax call to the server, and the server should understand the filter and return the collection based off that.
I'm trying to add a new item to whichever name that was passed in under whichever id. My first problem is that it seems like its not grabbing the values from any of my variables (name, item, id), instead just using them as object keys. My next issue is that when I tested by hard-coding sample table info onto here, it wasn't adding more items to that array, but simply replacing the entire array with whatever values I had here.
function addlist(name, item, id){ // Add to user's list
console.log(id);
db.collection('newcon').update({_id: id}, { "$set": { "$push": { name:item } } });
ret(id);
}
$set is not an array update operation.
The $set operator replaces the value of a field with the specified value.
You just want to use $push by itself, as in
.update({_id: id}, {$push: {name: item}})
You can't interpolate object property names in raw object declarations, so if you want to use a variable name you will have to create an object to do this:
var obj = {};
obj[name] = item;
You can then pass this to .update, {$push: obj}
I have the following string comming from server (as part of object):
...
SelectValues: "[{displayName: "Not selected", id: 0},{displayName: "Client", id: 1},{displayName: "Industry", id: 2},{displayName: "Country", id: 3}]"
...
I am using mapping pluging:
var ItemModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
}
As a result all items are created properly, except SelectValues. SelectValues should be observable array (each array item should have two properties id & displayName). Later I will use SelectValues for dropdown.
The problem is that it is returned as String and not as Array.
The question is whether I can somehow deal with it on client side (without changing format on server side)?
I probably can create SelectValuesComputed as ko.computed and somehow convert SelectValues to array (how?).
First of all, this is invalid JSON string you have in your property, see documentation (property names should be in quotes). But, having the condition that you cannot change the server code, you can use eval function to get your object and then use it in mapping like this:
var ItemModel = function (data) {
var self = this;
var mapping = {
"SelectValues": {
create: function(options){
return ko.mapping.fromJS(eval(options.data));
}
}
};
ko.mapping.fromJS(data, mapping, self);
}
See working demo. Although this might seem like the simpliest way to workaround the problem, I would strongly recommend you though to get a valid JSON string instead of using eval (or regexp) to get your object.