How to clear JSON object using JavaScript or jQuery - javascript

I have a JSON object as follows. After sending ajax call I want to clear this. How I can do?
var cfamFwdDtls = {
cndtwizid: [],
clientIdsInstnIds: [],
positioncd: '',
positionCnt: '',
rcrtrInstnId: '',
positionLocation: {
cntryIdFrCndt: '',
stateIdFrCndt: '',
zipIdFrCndt: '',
cityIdFrCndt: ''
},
searchPstnSkill: []
};

If you want to reset the entire object, just reset the variable back to {};
cfamFwdDtls = {};
// or
cfamFwdDtls = new Object;
// will prevent garbage collection
delete cfamFwdDtls;
However, if you want a more fine-grained way of "resetting" the object, you are going to need to define what specifically your requirements for a reset are. Regardless, you can always iterate through the object and make the necessary objects.
for (var key in cfamFwdDtls) {
if (typeof cfamFwdDtls[key] == "string") {
cfamFwdDtls[key] = '';
} else if (Array.isArray(cfamFwdDtls[key])) {
cfamFwdDtls[key] = [];
} else {
delete cfamFwdDtls[key];
}
}
The above definition could be a possible way to define your particular situation since I only see strings and arrays in your object. If the key is neither of those, it would just delete the key. This could be tailored as you find necessary.

for (var entry in cfamFwdDtls) delete cfamFwdDtls[entry];
If you simply reassign to {}, you'll get in trouble if there are multiple references to your object. Also may face garbage collection issues.

there is alternative for this if you want to remove object.Something like this
delete cfamFwdDtls;
you can use delete keyword for deleting a object.
more details read
example

The Problems
When I ran into this I wanted to solve two issues.
Have one location for a complex structure definition.
Reassurance the entire definition is reset.
Solutions
The basic idea is have a function return the empty structure. If it is not in a function you could change the structure itself not the instance of the structure.
Examples
Class
I personally use this but I also include the API functions in the class and make it an HTTP service.
class complexStructure {
constructor () {
this.payload = resetPayload();
}
resetPayload () {
this.payload = {
cndtwizid: [],
clientIdsInstnIds: [],
//...
};
}
}
Function
function resetStructure () {
return {
cndtwizid: [],
clientIdsInstnIds: [],
//...
};
}
let resetStructure = resetStructure()

function getJson(){
return {
cndtwizid: [],
clientIdsInstnIds: [],
positioncd: '',
positionCnt: '',
rcrtrInstnId: '',
positionLocation: {
cntryIdFrCndt: '',
stateIdFrCndt: '',
zipIdFrCndt: '',
cityIdFrCndt: ''
},
searchPstnSkill: []
};
}
var data = getJson();
data.positioncd = 'xyz';
data.rcrtrInstnId = 'abc';
$.ajax(...){
}
success(response){
data = getJson(); //re-initialize structure
}

Related

referencing properties that are yet to be defined

I have an array of objects. The objects reference properties that need to be examined. However, the properties are optional and might not get passed. This results in an error.
Here is a greatly simplified version of the code:
var build = {
execute: function (type, data) {
switch (type) {
case "fullName":
return build.fullName(data);
}
},
fullName: function(data){
return data[0] + data[1]
}
};
// assume this is the actual inbound data after parsing
var sample_event = {
customer: {
firstName: "bob",
lastName: "smith",
email: "a#example.com"
}
};
function cleanStuff( event) {
// potential inbound data
var prospects = [
{parent: "customer", type: build.fullName, newField: 'fullName',data: [event.customer.firstName, event.customer.middleName, event.customer.lastName]},
{parent: "customer", type: build.fullName, newField:'fullName', data: [event.idontexist.firstName, event.seller.middleName, event.seller.lastName]}
];
function calc(type, newField, calculationData) {
var calculated = calculated || {};
return calculated[newField] = build.execute(type, calculationData);
}
var filteredList = prospects.filter(function (x) {
if (event[x.parent] !== undefined) {
return x
}
});
filteredList.forEach(function (item) {
var type = item.type,
fieldName = item.fieldName,
data = item.data;
calc(type, fieldName, data, event);
});
}
cleanStuff(sample_event);
How does one go about referencing properties that don't exist? I DO NOT want to create empty properties, or set them to null. I want to simply avoid scrubbing them if they were not sent in to the app.
I could create the elements as Strings and parse them back to property paths at time of use but I think thats a bad approach.
I was also considering setting up a Proxy using ES6 but Chrome has yet update with the latest spec.
I'm using the 'prospects' array as a lookup table of sorts to say, "hey if this value is sent, do X to it".
I found using the newly introduced Proxy (ES6) works well here and allows me to set traps to handle these scenarios. Very cool addition to JS, allows for a great level of abstraction.
function Event(event) {
var proxy = new Proxy(event, {
get: function (target, property) {
if (property in target) {
return target[property];
} else {
return " ";
}
}
});
return proxy;
}
var event = new Event(sample_event);
Use Babel (via Webpack or Browserify perhaps) to compile ES6 code, and problem solved?
Maybe you can use async functions with Promises that promise the data will eventually be available?

Editing object with javascript/underscore, adding new items if don't exist already

So I am pulling in an object that I want to "edit", with a bit of help I have a function that finds the item i'm looking for and replaced the value. What I did no account for when building this was if the items don't exist yet.
So right now the function looks like this :
myFunction = function(moduleName, stateName, startVar){
//currentState brought in from factory controlling it
var currentState = StateFactory.current();
_.each(currentState, function(item) {
if (item.module === moduleName) {
_.each(item.customUrl, function(innerItem) {
if (_.has(innerItem, stateName)) {
innerItem[stateName] = startVar;
}
});
}
});
}
So - this does a great job of replacing the startVar value, assuming it already exists. I need to add some levels of checks to make sure the items exist (and if they don't add them in).
So, for reference, this is what the currentState looks like
[{
"module": "module1",
"customUrl": [
{ "mod1": "2" },
{ "mod2": "1" }
]
}, {
"module": "module2",
"customUrl": [
{ "mod3": "false" },
{ "mod4": "5" }
]
}
];
And so if i passed
myFunction("module1","mod1",3);
This works great, however if I pass
myFunction("module5","mod8","false");
Or maybe something in between like
myFunction("module1","mod30","false");
This function will not handle that scenario. I could use some helpe wrapping my head around how to tackle this problem. Also, am using underscore (if it is required to help). Thank you for taking the time to read!
As mentioned by Phari - something to the effect of this
currentState[moduleName].customUrl[stateName] = startVar;
I was thinking I could just create the object and just _.extend, but because it is an array of objects that wont quite work.
Here's what I mean :
var tempOb = {"module" : moduleName, "customUrl" : [{stateName : startVar}]};
_.extend(currentState, tempOb);
Doesn't quite work right with an array of objects.
It seems that all you need to do is remove the if statement:
if (_.has(innerItem, stateName)) {
innerItem[stateName] = startVar;
}
should become simply:
innerItem[stateName] = startVar;
Then if the property is not present, it will be added. If it is already present, it will be overwritten.
EDIT: to handle absence at top level:
myFunction = function(moduleName, stateName, startVar){
//currentState brought in from factory controlling it
var currentState = StateFactory.current();
var found = false;
_.each(currentState, function(item) {
if (item.module === moduleName) {
found = true;
_.each(item.customUrl, function(innerItem) {
if (_.has(innerItem, stateName)) {
innerItem[stateName] = startVar;
}
});
}
});
if ( ! found ) {
var newItem = {
module: moduleName,
customUrl: []
};
var newInnerItem = {};
newInnerItem[stateName] = startVar;
newItem.customUrl.push(newInnerItem);
currentState.push(newItem);
}
}

MVC4 ModelState property name to JSON or Array

I am using a complex object graph serialized to JSON with MVC4/jQuery/Sammy/Rivets for SPA functionality.
I have a object graph that looks a bit like this when serialized to JSON (obviously mocked-up):
model =
{
Name: "Me",
Age: 22,
Hobbies:
[
{ Name: "Biking", IsActive: true },
{ Name: "Programming", IsActive: true }
]
}
Everything works quite well until I need Unobtrusive validation, since my Hobbies are in a SlickGrid and I am managing all the data myself. To handle this I am returning my ModelState with my JSON next to my model.
return JSON(new { model = model, modelState = this.ModelState });
From there I intend to iterate through the modelState and assign errors to the right place with some custom function, but there is one problem.
ModelState looks like this:
"Name",
"Age",
"Hobbies[0].Name",
"Hobbies[0].IsActive",
"Hobbies[1].Name",
"Hobbies[1].IsActive"
I need to separate the [0]'s into an object and [1]'s into their own objects so I can smoothly get the values. This gets confusing for me when I begin to account for a third level of complex object array.
Solution:
var ModelStateConverter = function ($, module) {
module = module || {};
// Convert The ModelState form style object to a standard JS object structure.
module.toObject = function (modelState) {
var ModelState = {};
$.each(modelState, function (key, value) {
AssignValuesToObjectStore(key, ModelState, value);
});
return ModelState;
}
// item is the full identifier ex. "Hobbies[0].Name"
// store is the object we are going to throw arrays, objects, and values into.
// value is the error message we want to get in the right place.
// index is an internal processing parameter for arrays only, setting it's value has no effect.
function AssignValuesToObjectStore(item, store, value, index) {
var periodMatch = item.match(/[\.]/);
if (periodMatch === null) {
if (Array.isArray(store)) {
if (store[index] === undefined) {
store[index] = {};
}
store[index][item] = value;
}
else {
store[item] = value;
}
}
else {
// This wasn't a simple property or end of chain.
var currentProperty = item.slice(0, periodMatch.index); // Get our property name up to the first period.
var container = {}; // We assume we are dealing with an object unless proven to be an array.
var arrayIndex; // This is irrelevant unless we have an array.
if (currentProperty.slice(-1, currentProperty.length) === "]") {
// We are dealing with an array! Hoo Ray?!
arrayIndex = parseInt(currentProperty.slice(currentProperty.indexOf("[") + 1, currentProperty.indexOf("]")));
currentProperty = currentProperty.slice(0, currentProperty.indexOf("[")); // remove the indexer ex. [0] so we are left with the real name
container = []; // We know we need an array instead;
}
if (store[currentProperty] === undefined) {
store[currentProperty] = container; // If this property isn't already created, then do so now.
}
//Recurseive nature here.
AssignValuesToObjectStore(item.slice(periodMatch.index + 1, item.length), store[currentProperty], value, arrayIndex);
}
}
return module;
}($, ModelStateConverter);
You can call this from:
ModelStateConverter.toObject(data.modelState);
Where data.modelState is assumed to be the ModelState from the server.
You could try a library like JSON.NET, or the class JavaScriptSerializer, to serialize the ModelState.

Serializing a Child Object Within a Parent Object in JavaScript

This question is a follow-up to my last question: JavaScript Serialization and Methods. While related, I believe this is different which is why I started this thread. Regardless...
I have a complex tree of objects that I need to pass around between pages. Because of this, I'm attempting to serialize and deserialize my objects. One of my objects in particular has several collections of child objects. Each of those child object types has a function on it, that I'm trying to call. Unfortunately, I am not having any luck. I setup a test project in an attempt to isolate the problem and get to the bottom of it. Currently, I have my JavaScript Objects defined in a seperate file called objects.js. That file looks like this:
objects.js
function MyChild() { this.init(); }
MyChild.prototype = {
data: {
id: 0,
fullName: "",
},
init: function () {
},
save: function (key) {
},
load: function (key) {
},
test: function () {
alert("Testing Child functions");
}
}
function MyParent() { this.init(); }
MyParent.prototype = {
data: {
id: "",
children: null
},
init: function () {
this.data.children = [];
},
save: function (key) {
window.localStorage.setItem(key, JSON.stringify(this.data));
},
load: function (key) {
var temp = window.localStorage.getItem(key);
if (temp != null) {
this.data = JSON.parse(temp);
$.each(this.data.children, function (i, r) {
});
}
},
test: function () {
alert("Testing Parent functions");
}
}
I am creating, serializing, deserializing, and attempting to interact with these objects in an .html file. That .html file is shown here:
test.html
<div>
<input id="button1" type="button" value="Create Object Tree" onclick="button1Click();" /><br />
<input id="button2" type="button" value="Retrieve and Execute" onclick="button2Click();" /><br />
</div>
<script type="text/javascript">
function button1Click() {
var child = new MyChild();
child.data.id = 1;
var p = new MyParent();
p.data.id = "A";
p.data.children.push(child);
p.save("A");
}
function button2Click() {
var storedParent = new MyParent();
storedParent.load("A");
storedParent.test(); // This works
alert(storedParent.data.children.length); // This displays "1" like I would expect
alert(storedParent.data.children[0].data.id); // This does NOT work.
storedParent.data.children[0].test(); // This does NOT work.
}
</script>
I'm not sure what I'm doing wrong. Can someone please help me understand this? Can somone please help me fix my example. I have a hunch that I'm not serializing MyChild objects properly. But I don't understand how I should be serializing / deserializing them in relation to MyParent.
Thank you!
You need to store your data within each object, not within its prototype.
Data stored in in the prototype of an object is shared between all instances and won't be serialised by JSON.stringify, so your object data never ends up in the local storage.
To fix, add data to this within the this.init() function:
MyChild.prototype = {
init: function() {
this.data = {
id: 0,
fullName: ""
};
},
...
}
MyParent.prototype = {
init: function() {
this.data = {
id: "",
children: []
}
},
...
}
Working sample at http://jsfiddle.net/alnitak/fdwVB/
Note that attaching the functions in MyChild to the retrieved data is tricky. The code below appears to work:
load: function(key) {
var temp = window.localStorage.getItem(key);
if (temp != null) {
this.data = JSON.parse(temp);
var children = this.data.children;
for (var i = 0; i < children.length; ++i) {
children[i] = $.extend(new MyChild(), children[i]);
}
}
},
But note that it works by constructing a new "default" child for each retrieved entry, and then overwriting that child's data with the serialised values.
This could be problematic if the constructor has "side effects".
A better approach might be to allow the MyChild() constructor to take an optional complete object of initial values to use instead of the default values.

Combining JavaScript Objects into One

I have a function called "Colorbox" (jQuery plugin) that takes a number of parameters like so:
$(this).colorbox({
width : "500px",
height : "500px"
});
I have several different types of "this", though, each with their own properties. Like so:
var Type = {
video: {
width : "500px",
height : "500px"
},
gallery: {
width : "1065px",
height : "600px"
}
}
Beyond that, I have other behaviors, logic, and a 'default' group of settings (which get overwritten by more specific ones). What I'm trying to do is push all the appropriate settings, from multiple objects, into a single Object so I can just call:
$(this).colorbox(Settings);
How would I transfer an unknown group of properties and their values (for example "width" and "height") from something like Type.video into Settings? The goal is to be able to call Settings.height and get back the value I pushed in.
Take a look at the JQuery extend method. It can merge two objects together and all their properties.
From JQuery's example page:
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);
Now settings contains the merged settings and options objects.
JavaScript have a simple native function to merge object. which is Object.assign() introduced in ES6.
// creating two JavaScript objects
var x = { a: true };var y = { b: false}; // merging two objects with JavaScript native function
var obj = Object.assign(x,y);
//result
Console.log(obj); // output is { a: true, b: false }
for more information about javascript merging object please check at merge JavaScript objects with examples.
A non-jQuery solution is:
YOUROBJ.vars = {
vars1: {
vars1_1: 'an object which will overwrite',
vars1_2: 'an object which will be added'
}
};
YOUROBJ.vars2 = (!YOUROBJ.vars) ? {} : YOUROBJ.vars;
YOUROBJ.vars = {
vars1: {
vars1_1: 'an object which will be overwritten',
vars1_3: 'an object which will remain'
}
};
YOUROBJ.extend = function(obj, defaults) {
for (var i in defaults) {
if (!obj[i]) {
obj[i] = defaults[i];
} else {
YOUROBJ.extend(obj[i], defaults[i]);
}
}
};
YOUROBJ.extend(YOUROBJ.vars, YOUROBJ.vars2);
delete YOUROBJ.vars2;
This is useful if you wish to add a variable to a general functions object before it has been loaded and created.
This also enables the second YOUROBJ.vars to act as the default setting,.
If you're using jQuery you should checkout the $.extend function.
You could try something like this:
$.fn.somePlugin = function(options){
settings = $.extend(true, {default_values: "foo"}, options);
}
I have also created a "merge" function in Javascript to use for my general purposes:
if (typeof Object.merge !== 'function') {
Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
for(var i in o2) { o1[i] = o2[i]; }
return o1;
};
}
Usage:
var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});
It's quicker and dirtier (shallow copy), but it does what I need it to do.
I don't understand your question very well but i think you should use the $.extend function:
Settings=$.extend(Settings, Type.video);
in this way Settings will get Type.video properties
Simply first level merging (appending keys from second object to first one):
var mergeObjects = function (originalObject, objectToAppend) {
for (var item in objectToAppend) {
if (objectToAppend.hasOwnProperty(item)) {
originalObject[item] = objectToAppend[item];
}
}
};
originalObject must be non-null!

Categories