I have an object in my JS sliced from an array:
self.deploysToDevId = ko.computed(function() {
var deployToDev = ko.utils.arrayFilter(self.builds(), function(build) {
return build.buildType() == 'Deploy to Development';
}, self);
var deployToDevID = deployToDev.slice(0,1).id
return deployToDevID;
});
This object is originally from an array called builds and is a build object. However, I am trying to get a property, the "id" of the build which is a property of build, and I want to be able to store this and return this as an object, however when I do the data-bind prints the text [Object object]
self.getIdOfMostRecentDeploy = ko.computed(function() {
var idOfMostRecentDeploy = (self.deploysToDevId().id);
return idOfMostRecentDeploy;
});
This should store the id of the object as "idOfMostRecentDeploy" but it is not doing so.
self.deploysToDevId = ko.computed(function() {
var deployToDev = ko.utils.arrayFilter(self.builds(), function(build) {
return build.buildType() == 'Deploy to Development';
},
self);
var deployToDevID = deployToDev[0];
return deployToDevID;
});
This is another way I have tried, this time trying to take the first object in the array and assign its id to a variable. although, I still just get [Object object]
when you do this:
self.deploysToDevId = ko.computed(function() {
var deployToDev = ko.utils.arrayFilter(self.builds(), function(build) {
return build.buildType() == 'Deploy to Development';
}, self);
var deployToDevID = deployToDev.slice(0,1).id
return deployToDevID;
});
you are creating a computed that will contain just the id of the deployToDev object, which I presume is an observable (that is, a javascript function you need to eval to get the value)
Then, when you try to access it using:
(self.deploysToDevId().id)
this is returning basically nothing, because the "id" you are looking for is in the computed itself, self.deploysToDevId(), not in any inner id property
EDIT:
I have created this fiddle that may help you:
https://jsfiddle.net/r88zkn11/
in you case the only difference is that the object instead if having id and buildType as string objects, they are functions, so if you have to use them you have to evaluate them (use buildType() instead of buildType)
When you do this:
var deployToDevID = deployToDev.slice(0,1).id;
You are saying: give me an array one element long, and take the id property of that array. The array doesn't have an id property. Instead, you should be indexing the first element:
var deployToDevID = deployToDev[0].id;
Then, as JulioCT notes, the computed will return the id. It doesn't have an id member, it's just the id.
In your last example, you take the first element but don't take its id property, so naming it deployToDevID is misleading. Take the id of it as I suggest above, and then use deployToDevID anywhere you want to use that id.
Related
I have a list of html elements with data attributes, which I would like to assemble into a jQuery object and manipulate the values.
What is the best way to dynamically add these in an each loop so that I can easily access the data as so: data.name and data.name.prop?
I want all the naming conventions to be dynamic and based on the data.
I based my code on the top answer from here: How to create dynamically named JavaScript object properties?
So far I have:
$('.licences-list .data div').each(function(index) {
var data = {}
cats[$(this).find('p').data('cat')] = $(this).find('p').data('catname')
cats.push(data)
})
But when I try to iterate over the data array, like so:
$.each(cats, function(key, value){
$('<div class="card"><p>'+value+'</p></div>').appendTo('#commercial-licenses');
});
I just get [object Object] output... and I'm not sure why!
var data = {}
cats[$(this).find('p').data('cat')] = $(this).find('p').data('catname')
Each time you loop through, you're actually just adding an empty object (data) to your array (cats). You're then assigning a named property to that array (cats) which $.each has no idea about (it ignores them because it's iterating over an actual array).
My guess is you want an object map which is something like: var cats = { "f1": "feline 1", "f2": "feline " };
In that case what you want is:
var cats = {};
$('.licences-list .data div').each(function(index) {
cats[$(this).find('p').data('cat')] = $(this).find('p').data('catname')
})
If you want an array that contain more values than just strings (or whatever data you have added to the element), you create new objects each time and append them to the cats array:
var cats = [];
$('.licences-list .data div').each(function(index) {
cats.push({
'id': $(this).find('p').data('cat'),
'name': $(this).find('p').data('catname')
});
})
This will then give you an array that you can use $.each over, and access the values using: value.id, value.name
Don't over complicate it.
$('.div').attr('data-attribute', 'data-value');
using your example:
$('.licences-list .data div').attr('attribute-name', 'attribute-value');
I've used the nest() in d3js to group a bunch of insects by Pain Index, but am having trouble accessing a property. There's a similar question on SO, but I keep getting undefined instead of the property name and value. This is the data I'm dealing with:
Array[6]
0: Object
1: Object
2: Object
3: Object
4: Object
5: Object //expanded below
key: "4"
values: Array[3]
0: Object
Insect: "Tarantula Hawk" // I'm trying to access this object inside an object
PainIndex: "4"
I thought something like this would work since d.values gives you an array organized by PainIndex, but this prints undefined in my console:
var eachPain = d3.values(data_group).map(function(d){console.log(d.values); return d.values.Insect})
I'm curious to know how to access either the Insect or PainIndex properties. Any help is very apprecitaed
values is an array. Looks like you want the first instance. Try this:
var eachPain = d3.values(data_group).map(function(d){ return d.values[0].Insect });
EDIT:
var eachPain = d3.values(data_group).map(function(d) {
return d.values.map(function(v) { return v.Insect; }).join(', ');
});
Just to add some more information, besides the one in the accepted answer:
If you want to get a specific insect, and if you know it's position in the array (as you seem to do), this is what you need:
var someInsect = data_group[i].values[j].insect;
//outer object ----^ ^---- inner object
In this variable, the index i refers to the outer object, with all insects with a given level pain. Then, inside it, the index j refers to the inner object, with a specific insect.
For instance, check this following demo (I'm using a <pre> to load the data), where I get the data and nest it the way you did. In this demo, to get the tarantula hawk, I'm using:
var someInsect = data_group[0].values[1].insect;
var data = d3.csvParse(d3.select("#data").text());
var data_group = d3.nest()
.key(d => d.painIndex)
.entries(data);
var someInsect = data_group[0].values[1].insect;
console.log(someInsect);
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="data">insect,painIndex
fire ant,4
honey wasp,1
warrios wasp,3
paper wasp,1
velvet ant,2
tarantula hawk,4
bullet ant,4</pre>
Of course, that variable will change according to the insect you want.
Another possibility is getting the pain level of any insect you want by name. In your nested array, that can be done with:
var filtered = [].concat.apply([], data_group.map(function(d) {
return d.values
})).filter(function(d) {
return d.insect === myInsect
})[0].painIndex;
Where myInsect holds the name of the insect you'll use in the filter.
Check this other demo, where we get the pain value of the tarantula hawk:
var data = d3.csvParse(d3.select("#data").text());
var data_group = d3.nest()
.key(d => d.painIndex)
.entries(data);
var myInsect = "tarantula hawk"
var filtered = [].concat.apply([], data_group.map(function(d) {
return d.values
})).filter(function(d) {
return d.insect === myInsect
})[0].painIndex;
console.log(filtered);
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="data">insect,painIndex
fire ant,4
honey wasp,1
warrios wasp,3
paper wasp,1
velvet ant,2
tarantula hawk,4
bullet ant,4</pre>
Of course, all of this (getting the key values, get the value depending on other value etc...) would be way easier if you used your original array, instead of the nested one.
I have object that all of its fields are observable (knockout.observable).
I have other regular object too, that its fields have the same names like the first-object-fields.
I want to insert into each field of the first object, the value of the match-field at the second object.
For example:
var first = {
a:ko.observable(),
b:ko.observable()
};
var second= {
a:'my'
b:'fields';
};
I want the first object to look like:
first = {
a:ko.observable('my'),
b:ko.observable('fields')
};
Yes, of course, I can do it by 'each' loop.
But, my question is:
Is there any build-in function that does it?
You can use the ko.mapping plugin:
var results = ko.mapping.fromJS(second, first);
See Documentation
I am a novice trying to deserialize my result from an onSuccess function as :
"onResultHttpService": function (result, properties) {
var json_str = Sys.Serialization.JavaScriptSerializer.deserialize(result);
var data = [];
var categoryField = properties.PodAttributes.categoryField;
var valueField = properties.PodAttributes.valueField;
for (var i in json_str) {
var serie = new Array(json_str[i] + '.' + categoryField, json_str[i] + '.' + valueField);
data.push(serie);
}
The JSON in result looks like this:
[
{
"Text": "INDIRECT GOODS AND SERVICES",
"Spend": 577946097.51
},
{
"Text": "LOGISTICS",
"Spend": 242563225.05
}
]
As you can see i am appending the string in for loop..The reason i am doing is because the property names keep on changing therefore i cannot just write it as
var serie = new Array(json_str[i].propName, json_str[i].propValue);
I need to pass the data (array type) to bind a highchart columnchart. But the when i check the var serie it shows as
serie[0] = [object Object].Text
serie[1] = [object Object].Spend
Why do i not get the actual content getting populated inside the array?
You're getting that because json_str[i] is an object, and that's what happens when you coerce an object into a string (unless the object implements toString in a useful way, which this one clearly doesn't). You haven't shown the JSON you're deserializing...
Now that you've posted the JSON, we can see that it's an array containing two objects, each of which has a Text and Spend property. So in your loop, json_str[i].Text will refer to the Text property. If you want to retrieve that property using the name in categoryField, you can do that via json_str[i][categoryField].
I don't know what you want to end up with in serie, but if you want it to be a two-slot array where the first contains the value of the category field and the second contains the value of the spend field, then
var serie = [json_str[i][categoryField], json_str[i][valueField]];
(There's almost never a reason to use new Array, just use array literals — [...] — instead.)
In my Knockout viewmodel, I've got some properties where I'm trying to make a hash observable. So instead of my pre-Knockout code of
self.MyHash = {};
I am now using:
self.MyHash = ko.observable({});
In other parts of my code, I am manipulating the hash with statements like these:
// add an entry
self.MyHash()["test"] = "My Value";
// remove an entry
delete self.MyHash()["test"];
The code works, in that the entries are added and removed properly. However, the changes to the hashtable don't seem to be detected by areas of the code that are observing it. For example, this computed observable never runs when I am changing the hashtable:
self.Querystring = ko.computed(function ()
{
var f = [];
$.each(self.MyHash(), function (k, v)
{
f.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
});
return (f.length > 0) ? f.join("&") : "";
});
I am going to guess that this is because Knockout observables are required to be simple variables (or observableArrays), and that it's not detecting the underlying changes to my hashtable.
If so, are there other options? Why isn't there an observableHash type in Knockout?
For what it's worth, my workaround is to have an observableArray of keys, and a regular JavaScript hashtable to lookup the values. Then I changed my computed method to observe the array of keys rather than the other hashtable variable I had before. I just want to make sure I'm not missing "The Right Way" to do it in Knockout.
self.MyHashKeys = ko.observableArray();
self.MyHash = {};
self.Querystring = ko.computed(function ()
{
var f = [];
$.each(self.MyHashKeys(), function (index, value)
{
f.push(encodeURIComponent(value) + '=' + encodeURIComponent(self.MyHash[value]));
});
return (f.length > 0) ? f.join("&") : "";
});
See the second example on the observable array page. Just make an array of key/value pairs:
// This observable array initially contains three objects
var anotherObservableArray = ko.observableArray([
{ name: "Bungle", type: "Bear" },
{ name: "George", type: "Hippo" },
{ name: "Zippy", type: "Unknown" }
]);
In your examples you are only iterating (except for deletion), so there is no real need to use an actual dictionary. It would be easy enough to just search for the key. I think the use of map is kind of a premature optimization to some extent. Its also not entirely in line with the ability of query strings to support the same key multiple times.
Edit: if you want to observe the key or value changing in this example, you would also have to make those properties observable:
var anotherObservableArray = ko.observableArray([
{ name: ko.observable("Bungle"), type: ko.observable("Bear") }
]);