Change knockout values before posting them to server - javascript

Let's say I have a VM like this (price1 to price100)...
var Item = {
price1: ko.observable(),
price2: ko.observable(),
price3: ko.observable(),
...
...
price100: ko.observable(),
name: ko.observable()
}
But before posting it to my server, I need to replace all dots with commmas in every single price but not the "name" variable.
I don't want to change the field itself. I use ko.toJS(Item) ... so it's this result I want to change without manually going through all prices.
Is that possible?

If you are going all the way to JSON, then you could do something like described here: http://www.knockmeout.net/2011/04/controlling-how-object-is-converted-to.html
You can add a toJSON function to Item.prototype something like:
Item.prototype.toJSON = function() {
//if calling ko.toJSON this will already be a "clean" object, but if calling JSON.stringify, then it would not, so get a clean version anyways
var clean = ko.toJS(this);
for (var prop in clean) {
if (clean.hasOwnProperty(prop) && prop.indexOf("price") > -1) {
clean[prop] = clean[prop].toString().replace(".", ",");
}
}
return clean;
};
Then, when you do ko.toJSON(myItem) it will do the replacement.
If you do not want to go all the way to JSON, then you would basically want to do the same thing directly. So, you could really call the toJSON function above and get back your clean object. var clean = myItem.toJSON();
Sample: http://jsfiddle.net/rniemeyer/zX7Ld/

Related

javascript - JSON file use a value only if key exists

I'm retrieving an OSM Json from an overpass call, to obtain a list of features that I have to save on a database. Since the data are very different from one another (for example, some of them do have a a tag called "addr:city", and some of them not), I would like to check if a key exists, and only in that case save the corresponding value. I've found only this question but it's not my case, since I do not know a priori which keys one element will have and which not, and since I'm working with a great load of data, I really can't check the elements one by one and of course I can't write an IF for each case.
Is there a way to solve this? I was thinking something about "if key has null value, ignore it", while looping over the elements, but I don't know if something like that exists
EDIT:
This is my query:
https://overpass-api.de/api/interpreter?data=[out:json][timeout:25];(node[~%22^(tourism|historic)$%22~%22.%22](44.12419,%2012.21259,%2044.15727,%2012.27696);way[~%22^(tourism|historic)$%22~%22.%22](44.12419,%2012.21259,%2044.15727,%2012.27696););out%20center;
and this is the code I'm using to save the data on firebase:
results.elements.forEach(e=>{
var ref = firebase.database().ref('/point_of_interest/');
var key = firebase.database().ref().child('point_of_interest').push().key;
var updates = {};
var data = {
città: e.tags["addr:city"],
tipologia: e.tags["amenity"],
indirizzo: e.tags["addr:street"],
nome: e.tags["name"],
lat: e.lat,
lon: e.lon
}
updates['/point_of_interest/'+key] = data;
firebase.database().ref().update(updates);
})
"results" is the response in json format
You could use something like that:
var attrs = ["addr:city", "amenity", "addr:street", "name"];
var labels = ["città", "tipologia", "indirizzo", "nome"]
var data = { };
attrs.forEach((a, i) => {
if (e.tags[a]) { data[labels[i]] = e.tags[a]; }
});
You could even make this more dynamic, if you can query the attribute names and labels from somewhere.

Access Array of Objects after filtering

so I have a JSON object returned from a webservice. Now I want to:
get a subset which matches a categoryTitle i pass as parameter (this seems to work)
from my filtered resultset I want to get another array of objects (helpsubjects), and for each of this subjects I want to extract the SubjectTitle.
Problem: It seems my Array of HelpSubjects does not exist, but I can't figure out why and hope you could help.
Perhaps this piece of commented code makes it more clear:
$.fn.helpTopicMenu = function (data) {
that = this;
var categoryContent = contents.filter(function (el) {
return el.CategoryTitle == data.categoryTitle;
});
debug('categorys Content: ', categoryContent); //see below
var container = $('#subjectList');
var subjectList = categoryContent.HelpSubjects;
debug('Subjects in Category: ', subjectList); // UNDEFINED?!
$.each(subjectList, function (i, item) {
container.append(
$('<li></li>').html(subjectList[i].SubjectTitle)
);
});
the line debug('categorys Content: ', categoryContent); returns the following object as shown in the picutre (sadly I can't add a picture directly to the post yet, so here's the link): http://i.stack.imgur.com/0kKWx.png
so as I understand it, there IS actually a HelpSubjects-Array, each entry containing a SubjectTitle (in the picture there actually is only one entry, but I need to have the Artikel einfügen as my html.
Would be great if you can help me.
The variable categoryContent set is an array of objects.
Try debugging categoryContent[0].HelpSubjects and see if you can access the property. If so, you can also loop this array if need be.

How to use Ember's getters/setters on properties with dots?

In my webapp, I have a model with properties whose names are dynamically generated based on data from the server. For example, I would normally reference this by doing something like this from my controller:
var str1 = 'property.name.with.dots'; // String from server
this.get('model.someProperty')[str1].integer = 2;
this.get('model.someProperty')[str1].integer += 1;
But Ember doesn't like this - it says I should use a set or get function. Which makes sense. So I want to do something like this in place of the last line above:
this.get('model.someProperty.' + str1).incrementProperty('integer');
This would work fine out of the box if str1 didn't have dots. It does, though, so what can I do to get Ember's getters to work? I tried
this.get('model.someProperty')[str1].incrementProperty('integer');
but it doesn't work - the subobjects don't get Ember's methods by default.
Definitely
Massage the data before handing it off to Ember, having dots in your name will just cause a plethora of chaining problems.
Clean the data, I chose _ (this isn't deep cleaning, exercise for your fun)
App.cleanData = function(result){
var response = {},
re = new RegExp('\\.', 'g'),
newKey;
for(var key in result){
newKey = key.replace(re, '_');
response[newKey] = result[key];
}
return response;
};
Use the cleaned data instead of the server data
App.FooRoute = Em.Route.extend({
model: function(){
return $.getJSON('/foo').then(function(result){
return App.cleanData(result);
}
}
});

underscore find method issue on array of objects

I have following array of objects
var ppl = [
{
name: "John",
content: "<p>description</p>"
},
{
name: "Mike",
content: "<p>Desc</p>"
},
{
name: "Steve",
content: "html"
},
{
name: "Michael",
content: "<p>description</p>"
}
];
What I am doing is to display above array. Then when user clicks on name return his content. Like following
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
var content = _.find(ppl, function (desc) { if (desc.name === text) return desc.content; });
console.log(content);
});
What above code does is it finds the content of the person clicked however it returns the entire object of that person e.g. when John is clicked the his entire object {
name: "John",
content: "<p>description</p>"
} is returned by the _.find() function. I just need the content. How can I return content only?
If I were you I would simply do a loop:
var length = ppl.length;
var findcat = function(){
for (var a = 0; a < length; a++) { if(ppl[a].name==text){return ppl[a].content} };
}
var content = findcat();
rather than using underscore.js .
Or if you really want to use underscore.js, change it to this:
var content = _.find(ppl, function (desc) { if (desc.name === text) return desc; });
content = content.content;
and it will work.
Updates (regarding HTML strings in json):
It is okay to store them in json as these HTML strings will simply be considered as normal strings data (just don't forget to escape characters like quotation and forward slash). When real HTML elements are being created from these strings (using jquery functions like .html(string), append(string) ), the browser will need to render these new contents and it may cause a slow performance comparing to leaving all the page-rendering at the start for the browser, but the difference will be pretty subtle. So in terms of performance, it is always okay to have them in json. But in terms of security, you should be careful when there were HTML markup in your data because you are making XSS easier to be accomplished. (Here is a wikipedia article that provides more details on XSS, also known as Cross-site scripting.)
I don't think you need an array here. A simpler and more efficient way would be to use names as properties.
var ppl = {"John": "<p>description</p>", "Mike": "<p>Desc</p>" };
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
console.log(ppl[text]);
});
This is the expected Behavior of find operator which returns whole found item ! , why dont use content.content
the _.find looks through each value in the list, returning the first one that passes a truth test, when you return desc.content, it is evalued to true, so the desc object is return. so you can't return inside the find. but you can just access the content as desc.content. here is jsfiddle code:
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
var desc = _.find(ppl, function (desc) {
return desc.name === text;
});
console.log(desc.content);
});

Better way to build JSON array and retrieve its elements

Here's how I'm initializing and building an array:
var newCountyInfo = new Object();
newCountyInfo.name = newCountyName;
newCountyInfo.state = newCountyState;
newCountyInfo.zips = newCountyZips;
newCountyInfo.branchID = newCountyBranchID;
So I have my four elements in the array. I'm then passing newCountyInfo to another function to pull out the elements for display in some HTML elements.
The only way I know how to get to the individual elements in the function that uses them is this:
JSON.parse(JSON.stringify(newCountyValidation)).name
JSON.parse(JSON.stringify(newCountyValidation)).state
... etc...
There's got to be a better/shorter/more elegant way of doing this!
What is it?
Why are you serializing at all? I don't understand what JSON has to do with this, unless you're using web workers, ajax, or something else which demands serialization. Start with object literal syntax:
var newCountyInfo = {
name: newCountyName,
state: newCountyState,
zips: newCountyZips,
branchID: newCountyBranchID
};
And just pass the whole object to the other function:
someOtherFunction(newCountyInfo);
Which can access the fields using plain old property accesses:
function someOtherFunction(foo) {
console.log(foo.name); // whatever was in newCountyname
}
No JSON whatsoever.
Something like this should work just fine:
var newCountyInfo = {
name: newCountyName,
state: newCountyState,
zips: newCountyZips,
branchID: newCountyBranchID
}
function test(newCountyValidation)
{
alert(newCountyValidation.name);
}
test(newCountyInfo);

Categories