Concise way to declare and load object - javascript

I have an object that I am creating and a function on that object to load data into the various properties. While the method works as desired, I feel like it might be redundant. Can this be accomplished in a more concise or better way?
var user = {
productLine: {
userActiveValue: []
},
id: {
PACT: null,
EDIPI: null,
AKO: null,
},
name: {
first: null,
last: null,
},
DMIS: null,
region: null,
email: null,
load: true,
loadUser: function (userInfoAPIResponse) {
this.id.PACT = userInfoAPIResponse.UID;
this.id.EDIPI = userInfoAPIResponse.EDIPN;
this.id.AKO = userInfoAPIResponse.akoUserID;
this.name.first = userInfoAPIResponse.fName;
this.name.last = userInfoAPIResponse.lName;
this.DMIS = userInfoAPIResponse.dmisID;
this.region = userInfoAPIResponse.RHCName;
this.email = userInfoAPIResponse.userEmail;
console.log(this);
}
};

function User(userInfoAPIResponse) {
this.id = {
PACT: userInfoAPIResponse.UID,
EDIPI: userInfoAPIResponse.EDIPN,
AKO: userInfoAPIResponse.akoUserID
};
this.productLine = {
userActiveValue: []
};
this.name = {
first: userInfoAPIResponse.fName,
last: userInfoAPIResponse.lName
};
this.DMIS = userInfoAPIResponse.dmisID;
this.region = userInfoAPIResponse.RHCName;
this.email = userInfoAPIResponse.userEmail;
}
var user = new User(...);

Aside from using e.g. user.name = {first: response.fName, last: response.lName} and so on, no. You need to map the variables from one object to another yourself, or just use the response as your user variable.
Alternatively you could just declare user as global (or outer) scope and both declare and set the sub-objects in your callback function. This would mean you potentially had to check for them and their parents being undefined before using them elsewhere, as opposed to a simple not null check.

Related

How to properly reset Vue Composition Api's reactive values

I'm wondering how should I reset a reactive in vuejs setup? (i know if change it to the ref and using view.value will solve this problem, but there should be an answer to this for using reactive)
setup(props, context){
// states
const DataTable = reactive((null as unknown) as DataTable);
const PolicyForm = reactive((null as unknown) as PolicyForm);
let view = reactive(resetViewState());
let config = reactive(
(resetPreRegisterConfig() as unknown) as PreRegisterConfig
);
// methods:
const fetchProfilelist = (
pagination: Pagination{ page:1, size:15},
sort_label: string = ""
) => {
DataTable.fetchTablelist(api_fetchProfilelist, pagination, sort_label);
};
const pageRefresh = () => {
view = resetViewState(); // 👈
config = resetPreRegisterConfig();
fetchProfilelist();
};
return {
DataTable,
PolicyForm,
view,
config,
fetchProfilelist,
pageRefresh
}
You can use Object.assign:
setup() {
const initialState = {
name: "",
lastName: "",
email: ""
};
const form = reactive({ ...initialState });
function resetForm() {
Object.assign(form, initialState);
}
function setForm() {
Object.assign(form, {
name: "John",
lastName: "Doe",
email: "john#doe.com"
});
}
return { form, setForm, resetForm };
}
See it live on codesandbox
credits: taken from here
Object.assign didn't work for me. (Maybe because I used a shim for the Composition API in Nuxtjs 2?) For anybody that run into the same problem: I had to use a compact loop.
setup() {
const initialState = {
name: "",
lastName: "",
email: ""
};
const form = reactive({ ...initialState });
function resetForm() {
for (const [key, value] of Object.entries(initialState)) {
form[key] = value
}
}
function setForm(values = {name: "John", lastName: "Doe", email: "john#doe.com"}) {
// only loop with the supported keys of initial state
for (const key of Object.keys(initialState)) {
form[key] = values[key]
}
}
return { form, setForm, resetForm };
}
Citing from the official Vueland Discord server:
"For what I know, reactive is the old way we use to do reactivity from the Classic API, so to reset the values should be something like:"
const myData = reactive({
foo: true,
bar: ''
})
function resetValues () {
myData.foo = true
myData.bar = ''
}
Therefore, if you don't change properties you should be able to use Object.assign(). (Correct me if I'm wrong)
How about use ref instead of reactive?
const myData = ref({ xxx: 11 })
// ... After many operations on myData
// resetData
myData.value = { xxx: 11 }
The disadvantage is that you need to add .value when using it in script.
But this is the same as reactive in vue template.
If you have deep objects you can use this trick to reset the values converting them to JSON
setup(){
const form = ref({
order: '',
user:{},
});
const defaultForm = JSON.parse(JSON.stringify(form));
form.value.user = {firstname:"Joe", lastname:"Doe"};
const onSubmit = () => {
// Reset values to default
form.value = JSON.parse(JSON.stringify(defaultForm));
}
}
If you do not want to use ref and want to reset value of a reactive variable then you have to take one key variable for reference in the reactive variable, because reinitializing reactive variable directly will cause to loose reactivity in the process.
So to reset the value use extra key variable in reactive variable, see code as below
setup() {
const initialState = {
name: "",
email: ""
};
const form = reactive({ data: ...initialState });
function resetForm() {
form.data = { ...initialState };
}
function setForm() {
form.data = {
name: "Bahubali",
email: "bahubali#mahismati.com"
});
}
return { form, setForm, resetForm };
}
So basically you are taking data as key of your reactive variable and when you want to reset or set your values you just need to change the form.data and it will be reactive and refreshes the elements which uses form.data.

Trying to make a data module

I'm trying to make a data module in JavaScript, but can't access the data from outside, while everything works fine when I try to log it from inside
'use strict;'
function manager() {
let data = {};
function define(name, surname, age) {
let length = Object.keys(data).length;
data[`user${length + 1}`] = {
name: name,
surname: surname,
age: age
};
}
function get(num) {
return data[`user${num}`];
}
return {
define: define,
get: get
};
};
manager().define('John', 'Smith', 17);
console.log(manager().get(1));
//undefined
Every time you call manager you define a new variable named data and assign it the value {}.
So manager().define('John', 'Smith', 17); creates an object, assigns some data to it, then the object drops out of scope and is garbage collected.
Then console.log(manager().get(1)); creates a new object, and it has no data in it.
Define the variable and assign the object to it outside the function.
Kindly use module pattern and the execution will like this
var manager = (function() {
'use strict';
let data = {};
function define(name, surname, age) {
let length = Object.keys(data).length;
data[`user${length + 1}`] = {
name: name,
surname: surname,
age: age
};
}
function get(num) {
return data[`user${num}`];
}
return {
define: define,
get: get
};
}());
manager.define('John', 'Smith', 17)
console.log(manager.get(1))
var manager = (function() {
'use strict';
let data = {};
function define(name, surname, age) {
let length = Object.keys(data).length;
data[`user${length + 1}`] = {
name: name,
surname: surname,
age: age
};
}
function get(num) {
return data[`user${num}`];
}
return {
define: define,
get: get
};
}());
manager.define('John', 'Smith', 17)
console.log(manager.get(1))

AngularJS service parent separate reference

I'm using an AngularJS service to store data from multiple pages, to be submitted together. See the code below.
In my Chrome console if I observe checkoutData.shipping, I get back the correct object with data. If I observe checkoutData.data I get an empty object, where it's shipping property is blank.
These should be pointing at the same object, right? Why would it work with .shipping and not using .data? The reason it's set up this way is that the shipping page only cares about .shipping, while the final page needs everything in .data.
(function() {
angular.module('app').factory('checkoutData', [function() {
var data = {
carrierId: null,
serviceTypeId: null,
shippingCost: {},
billingOptionId: null,
shipping: {},
billing: {},
cart: null
};
var inputForms = {};
var options = {
shippingOptions: null,
billingOptions: null,
selectedShippingOption: null
};
var staticContent = {
billing: {},
cart: {},
shipping: {}
};
return {
data: data,
shipping: data.shipping,
inputForms: inputForms,
cart: data.cart,
billingOptionId: data.billingOptionId,
billingOptions: options.billingOptions,
carrierId: data.carrierId,
serviceTypeId: data.serviceTypeId,
shippingOptions: options.shippingOptions,
staticContentBilling: staticContent.billing,
staticContentCart: staticContent.cart,
staticContentShipping: staticContent.shipping,
selectedShippingOption: options.selectedShippingOption,
setValid: function(formName, valid) {
inputForms[formName].valid = valid;
},
initializeForm: function(formName) {
inputForms[formName] = {};
},
formInitialized: function (formName) {
return inputForms[formName] != null;
}
}
}]);
})();
One suggestion to make things easier is separate your data model(s) from your methods. And there's no need to try to keep multiple references to the same object within the same factory. There's nothing wrong with doing for example ng-model="checkoutModule.data.shipping.firstName". Is it wordier? Yes. Is it wrong? No.
So maybe something like
angular.module('app').factory('checkoutData', [function() {
return {
dataModel: {
carrierId: null,
serviceTypeId: null,
shippingCost: {},
shipping: {}, // This should be databound to an object from "shippingOptions", removing the need for "selectedShippingOption"
billing: {}, // This should be databound to an object from "billingOptions", removing the need for "billingOptionId"
cart: null
},
options: {
shippingOptions: null,
billingOptions: null
},
inputForms: {}
};
}]);
for your data and
angular.module('app').factory('checkoutModule', ['checkoutData', function(checkoutData) {
return {
data: checkoutData.dataModel,
options: checkoutData.options,
inputForms: checkoutData.inputForms,
setValid: function(formName, valid) {
checkoutData.inputForms[formName].valid = valid;
},
initializeForm: function(formName) {
checkoutData.inputForms[formName] = {};
},
formInitialized: function (formName) {
return checkoutData.inputForms[formName] != null;
}
}
}]);
for the factory that ties it all together.
From what I can see there is no way of setting the value of data.shipping other than using something like:
checkoutData.shipping = {"country" : "Sweden"};
This will result in checkoutData.shipping pointing to a new object and checkoutData.shipping will return that object:
{"country" : "Sweden"};
but
checkoutData.data will return the original empty shipping object since we haven't updated that value.
If you instead create a function for setting the shipping value in the checkoutData service:
setShipping : function(s){
data.shipping = s
},
and use that for setting the shipping data, you will get the values you want from checkout.data and checkout.shipping.
Have a look at this for demonstration: jsfiddle

Cannot Populate Javascript Object Properties with Values Using Function

I have the following Javascript object defined:
var APIUserItem = function () {
var
id = '',
account_id = '',
client_id = '',
user_name = '',
salutation = '',
first_name = '',
middle_name = '',
last_name = '',
organization_name = '',
alternate_email = '',
time_zone_id = '',
utcoffset = '',
date_created = new Date(),
last_updated_date = new Date(),
is_active = null,
is_approved = null,
classes = [],
groups = [],
permissions = [],
properties = {},
version_stamp_hash_string = '',
getFromData = function (data) {
id = data.ID;
account_id = data.AccountID;
client_id = data.ClientID;
user_name = data.UserName;
salutation = data.Salutation;
first_name = data.FirstName;
middle_name = data.MiddleName;
last_name = data.LastName;
organization_name = data.OrganizationName;
alternate_email = data.AlternateEmail;
time_zone_id = data.TimeZoneID;
utcoffset = data.UTCOffset;
date_created = data.DateCreated;
last_updated_date = data.LastUpdatedDate;
is_active = data.IsActive;
is_approved = data.IsApproved;
properties = data.Properties;
version_stamp_hash_string = data.VersionStampHashString;
// list of pointers to classes
$.each(data.Classes, function (index, value) {
class_pointer = new APIPointerItem();
class_pointer.ID = value.ID;
class_pointer.PublicID = value.PublicID;
class_pointer.Name = value.Name;
class_pointer.RelativeURI = value.RelativeURI;
classes.push(class_pointer);
});
// list of pointers to Groups
$.each(data.Groups, function (index, value) {
group_pointer = new APIPointerItem();
group_pointer.ID = value.ID;
group_pointer.PublicID = value.PublicID;
group_pointer.Name = value.Name;
group_pointer.RelativeURI = value.RelativeURI;
groups.push(group_pointer);
});
// list of permissions
$.each(data.Permissions, function (index, value) {
permission_pointer = new APIPermissionList();
permission_pointer.ID = value.ID;
permission_pointer.Description = value.Description;
permission_pointer.Category = value.Category;
permission_pointer.Level = value.Level;
permission_pointer.ResourceType = value.ResourceType,
permission_pointer.Action = value.Action;
permissions.push(permission_pointer);
});
};
return {
ID: id,
AccountID: account_id,
ClientID: client_id,
UserName: user_name,
Salutation: salutation,
FirstName: first_name,
MiddleName: middle_name,
LastName: last_name,
OrganizationName: organization_name,
AlternateEmail: alternate_email,
TimeZoneID: time_zone_id,
UTCOffset: utcoffset,
DateCreated: date_created,
LastUpdatedDate: last_updated_date,
IsActive: is_active,
IsApproved: is_approved,
Classes: classes,
Groups: groups,
Permissions: permissions,
Properties: properties,
VersionStampHashString: version_stamp_hash_string,
GetFromData: getFromData
};
};
When I new up an APIUserItem by calling:
var user = new APIUserItem();
user.GetFromData(data);
then try to access the values in the new item like so:
document.write(user.ID);
all of the property values come back empty, except for the collections, which contain the expected data. For example, I can loop through the Groups array from outside the object and access the properties of each group to display values.
The data object I passed to the GetFromData function call contains all the data - it just seems like the assignments to the local variables are not working? I know I must have made some obvious mistake in my code. Can anyone help me find my problem?
Your assignments to the local variables are probably working, but they're just that: assignments to local variables. Your code does nothing to update the properties of the object. The fact that you create the object via that return statement that initializes properties from the local variables does not create a magic link between the local variables and the properties.
Your "getFromData" function should look something like this:
function getFromData( data ) {
this.ID = data.ID;
this.AccountID = data.AccountID;
// and so on
}
The collection properties ("classes", "groups", "permissions") worked because they're objects, and you update their contents. That part's OK. Really, you don't need those local variables at all; you can just initialize the object properties directly.

Add JSON objects to JSON object

I have a JSON object employees which I would like to populate with the data in my localstorage. I first saved my JSON object to local storage using stringify() .
sessionStorage.setItem('Employee3', JSON.stringify({id: 3, firstName: 'Dwight', lastName: 'Schrute', title: 'Assistant Regional Manager', managerId: 2, managerName: 'Michael Scott', city: 'Scranton, PA', officePhone: '570-444-4444', cellPhone: '570-333-3333', email: 'dwight#dundermifflin.com', reportCount: 0}));
Now I want to populate my employees object:
employees: {},
populate: function() {
var i = i;
Object.keys(sessionStorage).forEach(function(key){
if (/^Employee/.test(key)) {
this.employees[i] = $.parseJSON(sessionStorage.getItem(key));
i++;
}
});
},
The function $.parseJSON(sessionStorage.getItem(key)) returns the JSON object correctly. Assigning it to the employees object fails:
Uncaught TypeError: Cannot set property 'undefined' of undefined
Array.forEach doesn't preserve this, so you'll have to preserve it yourself. Either of these will work (see mdn):
Object.keys(sessionStorage).forEach(function(key){
if (/^Employee/.test(key)) {
this.employees[i] = $.parseJSON(sessionStorage.getItem(key));
i++;
}
}, this);
var self = this;
Object.keys(sessionStorage).forEach(function(key){
if (/^Employee/.test(key)) {
self.employees[i] = $.parseJSON(sessionStorage.getItem(key));
i++;
}
});
Also, consider using the browser's JSON.parse() instead of jQuery's. Any browser that supports Array.forEach will support JSON.parse().
Yet another way:
Object.keys(sessionStorage).forEach((function(key){
if (/^Employee/.test(key)) {
this.employees[i] = $.parseJSON(sessionStorage.getItem(key));
i++;
}
}).bind(this));
Calling .bind(this) on a function will return a new function bound to the value for this (in the current scope).
the advantage to this is that you don't need to remember which methods support the second "value for this" parameter. It always works. For example, this also works for when adding event listeners to DOM nodes.
tjameson's first suggestion is probably to be preferred in this specific case.
You have a problem with the scope of this. When you are inside the foreach-callback this is not referring to the correct instance.
You need to save a reference to this before and then access the object through that reference (self in the following example):
function something(){
var self = this;
** snip **
employees: {},
populate: function() {
var i = i;
Object.keys(sessionStorage).forEach(function(key){
if (/^Employee/.test(key)) {
self.employees[i] = $.parseJSON(sessionStorage.getItem(key));
i++;
}
});
},
** snip **
}
You have a problem with the value of this inside the forEach callback. Also, And you don't need jQuery to parse JSON.
You can do this instead:
employees: {},
populate: function() {
var that = this;
var i = i;
Object.keys(sessionStorage).forEach(function(key){
if (/^Employee/.test(key)) {
that.employees[i] = JSON.parse(sessionStorage.getItem(key));
i++;
}
});
},
There is no reason to parse JSON, two simple functions will do the job (hope that was the idea):
var employees = {};
function setEmployee( data ) {
var id = data.id;
sessionStorage.setItem('Employee' + id, JSON.stringify( data ));
};
function getEmployee( id ) {
employees[id] = sessionStorage.getItem('Employee' + id);
};
var oneEmployee = {
id: 3,
firstName: 'Dwight',
lastName: 'Schrute',
title: 'Assistant Regional Manager',
managerId: 2,
managerName: 'Michael Scott',
city: 'Scranton, PA',
officePhone: '570-444-4444',
cellPhone: '570-333-3333',
email: 'dwight#dundermifflin.com',
reportCount: 0
};
setEmployee( oneEmployee );
getEmployee( 3 );

Categories

Resources