Access dynamically created objects in Javascript - javascript

I am attempting to dynamically create an object with name-value pairs using html input fields. This is what i have so far:
var taskComplete = {
newTask: function(arg) {
var fieldObj = {},
selector = arg,
inputFields = document.getElementsByClassName(selector);
for (var i=0;i<inputFields.length;i++) {
var attrValue = inputFields[i].getAttribute("name"),
value = inputFields[i].value,
newFieldObj = fieldObj[i] = {[attrValue]: value };
console.log(newFieldObj);
}
}
}
taskComplete.newTask('input');
The console log outputs:
Object {title: ""}
Object {description: ""}
Object {date: ""}
Question1:
How do i access these objects? they all share the same name eg. 'Object' so 'object.title' does not work.
Question2:
Is there a way to combine these objects into a single object?
eg.
var obj = {
title: "",
description: "",
date: "",
}
code example with html: codepen.io
Hope this make sense. Thank you for any and all assistance.

I will answer your questions in the reverse order, makes more sense, you will see.
Question2: Is there a way to combine these objects into a single object?
Yes, I am happy to inform you that you absolutely can. Where you do
newFieldObj = fieldObj[i] = {[attrValue]: value };
simply do
fieldObj[attrValue] = value;
What this does, is the following: On the fieldObj, which is a plain {} set a key named after the value of attrValue and pair that key with the value value
Question1: How do i access these objects? they all share the same name eg. 'Object' so 'object.title' does not work.
In order to be able to access these objects, your newTask method should be returning them. So, at the end of your newTask method, simply do return fieldObj; like so
var taskComplete = {
newTask: function(arg) {
var fieldObj = {},
selector = arg,
inputFields = document.getElementsByClassName(selector),
attrValue,
value;
for (var i=0;i<inputFields.length;i++) {
attrValue = inputFields[i].getAttribute("name");
value = inputFields[i].value;
fieldObj[attrValue] = value;
}
return fieldObj;
}
}
and then store the returned value to a new variable like so:
var aFancyName = taskComplete.newTask('input');
Here's the modified pen: http://codepen.io/anon/pen/XdjKQJ

Not super clear on what you are trying to do here.
Instead of creating a new object for each iteration of your loop, why not just assign those properties to the fieldObj you already have?
Then you can just return that object and do whatever you want with it in the calling code:
'use strict';
// ** TASK OBJECT ** //
var taskComplete = {
newTask: function(selector) {
var fieldObj = {},
inputFields = document.getElementsByClassName(selector);
for (var i = 0; i < inputFields.length; i++) {
var attrKey = inputFields[i].getAttribute("name"),
value = inputFields[i].value;
fieldObj[attrKey] = value;
}
return fieldObj;
}
}
var o = taskComplete.newTask('input');
console.dir(o);
http://codepen.io/anon/pen/reMLPB?editors=0010

Related

Javascript Unintentionally Changing Multiple Objects' Array Attribute

I am running into a weird problem where I am trying to change the value of an attribute in a specific object it's changing that attribute value in all objects.
Below is my code the creates these objects "nodes"
function processNode(nodeID, name, fields){
this.id = nodeID;
this.fields = fields;
this.name = name;
}
var nodeFuncs = {table:
function(nodeID){
function tableNode() {}
tableNode.prototype = Object.create(new terminalNode(nodeID, 'table'));
return new tableNode(nodeID, 'table');
}
, source:
function(nodeID){
function sourceNode() {}
sourceNode.prototype = Object.create(new processNode(nodeID, 'source'));
sourceNode.prototype.table = '';
sourceNode.prototype.selectors = '';
sourceNode.prototype.include = 1;
return new sourceNode(nodeID, 'source', []);
}
, sort:
function(nodeID){
function sortNode() {}
sortNode.prototype = Object.create(new processNode(nodeID, 'sort'));
sortNode.prototype.order = [];
return new sortNode(nodeID, 'sort', [])
}
, filter:
function(nodeID){
function filterNode() {}
filterNode.prototype = Object.create(new processNode(nodeID, 'filter'));
filterNode.prototype.names = [];
return new filterNode(nodeID, 'filter', [])
}
}
function createNode(nodeID, name){
return nodeFuncs[name](nodeID);
}
idToNodeObjectMap['abc123'] = createNode('abc123', 'source')
idToNodeObjectMap['abc124'] = createNode('abc124', 'sort')
idToNodeObjectMap['abc125'] = createNode('abc125', 'filter')
idToNodeObjectMap['abc126'] = createNode('abc126', 'filter')
Here is a sample jquery event that is triggering the re-valuing of an object's attribute:
$('body').on('click', "div button.ok", function(){
var nodeID = $(this).parent('div.nodeForm').attr('id')
var objectNode = idToNodeObjectMap[nodeID];
objectNode.fields.splice(1,1);
});
For example I will have 4 objects and reference one of them as var objectNode whose .fields value is ['tid', 'gid', 'tname']. Then when I call objectNode.fields.splice(1,1) the .fields value will be ['tid', 'tname'] FOR ALL 4 OBJECTS not just the one that is reference in the objectNode variable.
BUT, when I change the line...
objectNode.fields.splice(1,1);
to...
objectNode.fields = ['hi'];
then it only changes the .fields attribute of the object that I referenced as var objectNode.
Does anyone have any idea why this would happen? I thought it might be a referencing issue where all .fields were referencing and changing each others values but that doesn't seem to make sense to me because when I set the .fields attribute equal to ['hi'] it only changes one object's .fields attribute.
Any help would be appreciated.
I notice in your code that you have this line and I wonder if its part of the problem.
filterNode.prototype = Object.create(new processNode(nodeID, 'filter'));
Object.create() returns an object that has the prototype of processNode but not the prototype object itself. So you have a prototype equal to an object with another prototype inside of it.
filterNode {
__proto__: processNode {
__proto__: processNode.prototype
}
}
This might be attributing to your reference issues.

Adding another variable to an array in angularJS

So im editing some code and I would like to add another variable to an array. The code below works perfectly:
submit.addAttributeValue = function() {
var aValue = submit.status.newAttributeValue;
var aType = submit.status.selectedAttributeType;
console.log('adding value', aValue, aType)
if(aValue && aType ) {
submit.ProductMeta['attributes'][aType][aValue] = true;
};
};
I then add the variable aPrice to the function:
submit.addAttributeValue = function() {
var aValue = submit.status.newAttributeValue;
var aType = submit.status.selectedAttributeType;
var aPrice = submit.status.newAttributePrice;
console.log('adding value', aValue, aType, aPrice)
if(aValue && aType ) {
submit.ProductMeta['attributes'][aType][aValue][aPrice] = true;
};
};
I get the error:
Error: submit.ProductMeta.attributes[aType][aValue] is undefined
submit.addAttributeValue#http://dubdelivery.com/js/controllers-submit.js:369:13
ProductMeta is defined as: submit.ProductMeta = {};
Any advice on how I should approach this?
Thank You!
Your array is empty so you can't set a second level field before the first
If you have
var obj = {};
You have to set
obj.firstItem
before
obj.firstItem.secondItem
Here is an example
Look in the debugger or just console log "aType", "aValue", and "aPrice". I'm betting "aValue" is undefined.
If you're going to go about manipulating object properties this way, you have to make sure the variables that contain your property names actually have values.
(BTW, especially now with ES6 classes, you probably shouldn't be manipulating object property/values this way).

Real use case dynamic (computed) property

A dynamic property:
var obj = {
// Computed (dynamic) property names
[ 'prop_' + (() => 42)() ]: 42
};
This is of course very fancy. But where could someone use this without adding unnecessary complexity?
If you have a property name as a constant:
var obj = { [SOME_CONSTANT]: 42 };
One case where I wanted it was where property names for JSON were defined in generated files, based off Java classes.
// Generated
var SomeJsonBodyParams = {NAME: 'name', ID: 'id', ETA, 'estimatedTimeOfArrival'};
// Using it
sendAjax('some/url', {
[SomeJsonBodyParams.NAME] = userData.name,
...
});
We even had a method so we could kind of do it
function makeObj() {
var obj = {};
for (var i=0; i < arguments.length; i+=2) {
obj[i] = obj[i+i];
}
return obj;
}
sendAjax('some/url', makeObj(
SomeJsonBodyParams.NAME, userData.name,
...
));
You can use it in class and with Symbols:
class MyClass {
[Symbol.iterator]() {
// my iterator
}
}
Let's say you have:
var hi = 'hi';
var test = 'test';
var hello = 'hello';
Instead of:
var object = {};
object[hi] = 111;
object[test] = 222;
object[hello] = 333;
You could write it in a much shorter syntax:
var object = {
[hi]: 111,
[test]: 222,
[hello]: 333
}
E.g. it could be used when you want to use a, let's say, constant as a key in object.
const DATA_TYPE = {
PERSON: 'person',
COMPANY: 'company'
};
let cache = {
[DATA_TYPE.PERSON]: getPerson()
};
And later access:
cache[DATA_TYPE.PERSON]
Instead of DATA_TYPE.PERSON could be anything (including some real-time calculated values).

how to get the content of java script object in another object?

how to get the content of java script object in another object ?
let say my variable are like follows :
var credentials ={
"name":userName,
"passwd":password
}
var params={
"Credentials":credentials
}
am passing params as an parameter to same other function.In that function i have another object pkt ,as follows :
var pkt={
"name":xxx,
//XXXX
}
what to code at XXXX so that my final pkt structure should be like:
pkt={
"name":xxx,
"Credentials": {
"name":userName,
"passwd":password
}
}
we may have multiple objects inside params,the requirement is that the key value pair should come accordingly.
the equivalent java code is as follows:
Iterator iterKeys = params.keySet().iterator();
while (iterKeys.hasNext())
{
String key = (String)iterKeys.next();
JSONValue value = params.get(key);
pkt.put(key, value);
}
Thanks.
Javascript objects are just Hashmaps.
var credentials = {
"name": "userName",
"passwd": "password"
}
var params = {
"Credentials": credentials
}
var pkt = {
"name": "xxx",
}
for (var property in params) {
if (params.hasOwnProperty(property)) {
var value = property;
pkt[property] = params[property];
}
}
alert(JSON.stringify(pkt));
You can just assign as seen in [this fiddle]
(http://jsfiddle.net/TfWMy/)
You could use a library function like $.extend or _.extend:
pkt = $.extend(pkt, params);
Otherwise you can loop through params and add each key/value pair to pkt:
for (var key in params){
pkt[key] = params[key];
}
Use hasOwnProperty to avoid looping over ancestor members.
You can also use associative array structure.
i.e
var credentials = {
"name": "userName",
"passwd": "password"
}
var pkt = {
"name": "xxx",
}
pkt["Credentials"] = credentials
Not particularly sure about this, but this should work as expected.
Here's two quick functions that should do what you're looking for. The first adds the keys and values to a new object, the second function adds the keys and values to the first object.
var mergeObjectsToNew = function(o1, o2) {
var r = {};
for (var key in o1) {
r[key] = o1[key];
}
for (var key in o2) {
r[key] = o2[key];
}
return r;
}
var mergeObjects = function(o1, o2) {
for (var key in o2) {
o1[key] = o2[key];
}
return o1;
}
I think you are looking to extend your object with another.
Please follow the code and I hope this is the thing you are require.
var credentials ={
"name":"",
"passwd":""
}
var params={
"Credentials":credentials
}
var pkt={
name:"ABC"
};
function Extends(param1,param2){
var object = $.extend({}, param1, param2);
console.log(object);
}
Extends(params,pkt);
Please find Fiddle Below
Fiddle

Can you use custom objects as properties of an object in javascript?

Suppose I create a custom object/javascript "class" (airquotes) as follows:
// Constructor
function CustomObject(stringParam) {
var privateProperty = stringParam;
// Accessor
this.privilegedGetMethod = function() {
return privateProperty;
}
// Mutator
this.privilegedSetMethod = function(newStringParam) {
privateProperty = newStringParam;
}
}
Then I want to make a list of those custom objects where I can easily add or remove things from that list. I decide to use objects as a way to store the list of custom objects, so I can add custom objects to the list with
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = true;
myListOfCustomObjects[customObjectInstance2] = true;
myListOfCustomObjects[customObjectInstance3] = true;
and remove custom objects from the list with
delete myListOfCustomObjects[customObjectInstance1];
but if i try to iterate through the list with
for (i in myListOfCustomObjects) {
alert(i.privilegedGetMethod());
}
I would get an error in the FireBug console that says "i.privilegedGetMethod() is not a function". Is there a way to fix this problem or an idiom in javascript to do what I want? Sorry if this is a dumb question, but I'm new to javascript and have scoured the internet for solutions to my problem with no avail. Any help would be appreciated!
P.S. I realize that my example is super simplified, and I can just make the privateProperty public using this.property or something, but then i would still get undefined in the alert, and I would like to keep it encapsulated.
i won't be the original object as you were expecting:
for (i in myListOfCustomObjects) {
alert(typeof i); // "string"
}
This is because all keys in JavaScript are Strings. Any attempt to use another type as a key will first be serialized by toString().
If the result of toString() isn't somehow unique for each instance, they will all be the same key:
function MyClass() { }
var obj = {};
var k1 = new MyClass();
var k2 = new MyClass();
obj[k1] = {};
obj[k2] = {};
// only 1 "[object Object]" key was created, not 2 object keys
for (var key in obj) {
alert(key);
}
To make them unique, define a custom toString:
function CustomObject(stringParam) {
/* snip */
this.toString = function () {
return 'CustomObject ' + stringParam;
};
}
var obj = {};
var k1 = new CustomObject('key1');
var k2 = new CustomObject('key2');
obj[k1] = {};
obj[k2] = {};
// "CustomObject key1" then "CustomObject key2"
for (var key in obj) {
alert(key);
}
[Edit]
With a custom toString, you can set the object as the serialized key and the value to keep them organized and still continue to access them:
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = customObjectInstance1;
myListOfCustomObjects[customObjectInstance2] = customObjectInstance2;
myListOfCustomObjects[customObjectInstance3] = customObjectInstance3;
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
The for iteration variable is just the index, not the object itself. So use:
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
and, in my opinion, if you use an Object as an array index / hash, it just would be converted to the string "Object", which ends up in a list with a single entry, because all the keys are the same ("Object").
myListOfCustomObjects =[
new CustomObject('someString'),
new CustomObject('someOtherString'),
new CustomObject('yetAnotherString')
]
you will get access to any element by index of array.

Categories

Resources