Now I got something like this, instead of creating new-info: {"name": "name", "description": "mydescription"} it deletes the previous new-info and just adds for example
new-info: "test" How can I make this to be one object of values?
function setName(value) {
this.name = value
localStorage.setItem('new-info', JSON.stringify(this.name))
},
function setDescription(value) {
this.description = value
localStorage.setItem('new-info', JSON.stringify(this.description))
},
The issue appears to be that you are not assigning the required object to localStorage, but rather the string property, meaning you are overwriting the key new-info with a string. Try saving the entire object instead, like this:
const info = {
name: '',
description: ''
};
function setName(value) {
info.name = value;
saveToStorage();
};
function setDescription(value) {
info.description = value;
saveToStorage();
};
function saveToStorage() {
localStorage.setItem('new-info', JSON.stringify(info));
}
Related
I have a handleCreate function that takes care of taking some user data and inserting it into a database.
Inside the aliasArr.forEach() loop I POST into my DB new user instances for each element in the aliasArr array. This particular code works as expected, if I check the DB, I will find the new members.
After saving the new members, I want to keep the members in the members array so I can pass it along to another function.
For this, I'm doing members.push(memberAttributes); but if I log the contents of members I get the right amount of elements but the alias property value is duplicated (all other properties should have the same value cause they are being added into the same role in a batch operation).
If I have two new users, say: xyz and abc, I get:
[
{alias: "abc", Role: "admin", "grantedBy": "someone"},
{alias: "abc", Role: "admin", "grantedBy": "someone"},
]
Instead of:
[
{alias: "xyz", Role: "admin", "grantedBy": "someone"},
{alias: "abc", Role: "admin", "grantedBy": "someone"},
]
Here's the code:
handleCreate = () => {
const { memberAttributes } = this.state;
const { role, createRoleMember } = this.props;
const roleArr = [];
roleArr.push(role);
const aliasArr = memberAttributes.alias.split(",");
let members = [];
//false hardcoded during debugging.
if (false /* await aliasIsAdmin(memberAttributes.alias, roleArr) */) {
this.setState({ userExists: true });
} else {
memberAttributes["Granted By"] = window.alias;
memberAttributes.Role = role;
memberAttributes.timestamp = Date.now().toString();
this.handleClose();
aliasArr.forEach((currAlias) => {
memberAttributes.alias = currAlias;
console.log("memberAttributes:", memberAttributes);
members.push(memberAttributes);
console.log("members", members);
const marshalledObj = AWS.DynamoDB.Converter.marshall(memberAttributes);
const params = {
TableName: "xxx",
Item: marshalledObj,
};
axios.post(
"https://xxx.execute-api.us-west-2.amazonaws.com/xxx/xxx",
params
);
});
}
createRoleMember(members); //passing members to this function to do more stuff.
};
I'm wondering if this issue is due to memberAttributes being part of the component's state.
The problem here is that you are pushing references to the same object into the array after changing a value within that object. So whenever you make the change to memberAttributes.alias, it's changing the alias to the most recent one. After that, all references to the same object (which in this case is every item in the members array) present the new value in alias.
const obj = { alias: 'abc', role: 'role1' }
const arr = []
arr.push(obj)
obj.alias = 'new alias'
arr.push(obj)
for (var mem of arr) {
console.log(mem)
}
To fix it, you need to create a new object each time and push it onto the array instead, like so:
aliasArr.forEach((currAlias) => {
// Creates a new object in memory with the same values, but overwrites alias
const newMemberAttributes = Object.assign(memberAttributes, { alias: currAlias });
console.log("memberAttributes:", newMemberAttributes);
members.push(newMemberAttributes);
console.log("members", members);
...
}
Similarly, you can use the spread operator to create a deep copy of the object and then reassign alias.
aliasArr.forEach((currAlias) => {
// Creates a new object in memory with the same values, but overwrites alias
const newMemberAttributes = { ...memberAttributes };
newMemberAttributes.alias = currAlias
console.log("memberAttributes:", newMemberAttributes);
members.push(newMemberAttributes);
console.log("members", members);
...
}
Is it possible to reference the name of the object variable declaration within the object itself?
Something like:
const foo = {
bar: `${MAGICTHIS}-bar`,
}
console.log(foo.bar); //foo-bar
EDIT:
I am writing a dynamic function for rewriting all my css classnames to BEM in an object. I do this to be able to manage them in one point through out my application. Without the function it is like this:
export const button = {
btn: 'button',
btnSm: 'button--small',
btn2: 'button--secondary',
export const alert = {
alert: 'alert',
alertDanger: 'alert--danger',
//etc
}
They are separated in different objects because I want to isolate usage.
I wanted to optimize this since I'll be doing this a lot. That's why I'm trying to write a 'bemmify' function. So I can do this:
export const button = {
btn: bemmify(),
btnSm: bemmify('small'),
btn2: bemmify('secondary'),
export const alert = {
alert: bemmify(),
alertDanger: bemmify('danger'),
//etc
}
And have the same result as the objects above.
Of course I could always pass the 'base' as a first param (bemmify('button', 'small')) but I started to wonder if it were possible to let my bemmify function be so smart that it could recognize the name of the object it is in.
Whenever you find yourself writing code where the variable names are significant, you should generally be using an object where the variable names are keys. So you should have an object like:
const bem_data = {
button: {
btn: 'button',
btnSm: 'button--small',
btn2: 'button--secondary',
},
alert: {
alert: 'alert',
alertDanger: 'alert--danger',
}
}
Then you can use a function to create each element:
function add_element(data, key, prefix, additional) {
const obj = {
[prefix]: key
};
Object.entries(additional).forEach(([
keySuffix,
valSuffix
]) => obj[prefix + keySuffix] = `${key}--${valSuffix}`);
data[key] = obj;
}
const bem_data = {};
add_element(bem_data, "button", "btn", {
Sm: "small",
"2": "secondary"
});
add_element(bem_data, "alert", "alert", {
Danger: "danger"
});
console.log(bem_data);
Then you export bem_data and use bem_data.button, bem_data.alert, etc.
I have an Ember Route class defined as below;
export default Ember.Route.extend({
model: function() {
var compObj = {};
compObj.gridPara = this.get('gridPara');
return compObj;
},
gridPara: function() {
var self = this;
var returnObj = {};
returnObj.url = '/myService';
// setting some other returnObj attributes
var summaryObj = {
total: {
label: "Total 1",
value: "100"
},
additional: [{
label: 'Label 2',
value: 'val2'
}, {
label: 'Label 3',
value: 'val3'
}]
};
returnObj.summary = summaryObj;
return returnObj;
},
actions: {
dataLoaded: function(resp) {
// Here I get the service response and want to set (or overwrite) the summaryObj values
this.get('gridParams').summary.total.value = resp.numRows;
}
}
});
My template looks like
{{my-grid params=this.gridPara dataLoaded="dataLoaded"}}
Now I want to set the "summary" on returnObj
I have verified that I get "resp" inside dataLoaded callback.
But I get the following error when trying to do
this.get('gridParams').summary.total.value = resp.numRows;
Uncaught Error: Assertion Failed: You must use Ember.set() to set the value property (of [object Object]) to 100.
Also how do I set/push for "additional" array inside summaryObj
As the error states, you must use set to the the value (Im assuming you have gridParams defined somewhere?):
this.set('gridParams.summary.total.value', resp.numRows);
In order to push a new object, try this:
var additional = this.get('gridParams.additional');
additional.push({label: ..., value: ....});
this.set('gridParams.additional', additional);
not 100% sure, but give it a try:
Watch out the property names. I suppose it's a wording error to declare 'gridPara' and trying to get 'gridParams'
You should retrieve the value like this
this.get('gridParams.summary.total.value')
What you are trying with the last sentence is a setting, but like it was plain JS. In Ember you should do it this.set('gridParams.summary.total.value',resp.numRows)
Just adding to #Remi answers ,the best practice would be to use
Ember.set('gridParams.summary.total.value', resp.numRows);
To answer the question in your comment
Say you want to update additional array at index i.Just do
var updateItem = additional[i];
Ember.set(updateItem.propertyname,newValue)
//Here propertyname would be the property you want to update and new Value is the new value which you want to set to that property
I have an application that is running with firebase. When I try to use the push() method, it basically overwrites the existing JSON. Here's an example:
First time around, the following JSON is generated:
JSON
"deviceIDs" : {
"-JzCx5C_13eoXPEgklMW" : {
"author" : "gracehop22",
"deviceID" : "99alpha",
"title" : "Announcing COBOL, a New Programming Language"
}
}
Next time around, if I call the same function, the above JSON is deleted and a new JSON is inserted such as this one:
JSON
"deviceIDs" : {
"-JzCxbuEj2V1kmvvgqnc" : {
"author" : "gracehop22",
"deviceID" : "99alpha",
"title" : "Announcing COBOL, a New Programming Language"
}
}
Here's my code snippet:
function CreateUserProfile(UID, name, email, deviceID) {
var ref = new Firebase($scope.firebaseurl + '/' + UID);
var profileArray = {UserProfile:{}};
profileArray.UserProfile.UID = UID;
profileArray.UserProfile.name = name;
profileArray.UserProfile.email = email;
profileArray.UserProfile.deviceID = deviceID;
var onComplete = function (error) {
if (error) {
console.log('Synchronization failed');
} else {
//1. On Success, Store Key User Profile Elements
localStorage.setItem("kasimaProfileInfo",JSON.stringify(profileArray));
$rootScope.username = name;
//2. Hide the feedback and change screens
$timeout(function () {
$scope.HideFeedback();
$scope.ChangeLoc('/featured');
}, 1500);
}
};
ref.set(profileArray, onComplete);
var postsRef = ref.child("deviceIDs");
var newPostRef = postsRef.push();
newPostRef.set({
deviceID: deviceID,
author: "gracehop22",
title: "Announcing COBOL, a New Programming Language"
});
}
You're overwriting the entire ref when you're setting profileArray:
...
ref.set(profileArray, onComplete);
var postsRef = ref.child("deviceIDs");
...
You'll probably want to use update() there:
...
ref.update(profileArray, onComplete);
var postsRef = ref.child("deviceIDs");
...
Update
The Firebase update() functions set the value of the properties in the JSON object you pass it. So your new profileArray.UserProfile will replace the existing data.
The solution is to not build a nested JSON structure locally, but instead update the data at the lower location where it needs updating:
ref.child('UserProfile').update(profileArray.UserProfile, onComplete);
This removes the entire need for the profileArray:
var userProfile = {
UID: UID,
name: name,
email: email,
decideID: deviceID
};
ref.child('UserProfile').update(userProfile, onComplete);
For a working example, see: http://jsbin.com/ciqoge/edit?js,console
For a next time: if you provide such a jsbin/jsfiddle straight away, it will be much easier to quickly help you.
I want to create a javascript object from a template. The problem is I don't know what the template is going to look like beforehand. As a simple example, if I had the template function
template = function (data) {
return {
title: data.title
}
}
then I could run template({ title: "Steve" }) and get back the object
{ title: "Steve" }
Because data.title is not evaluated until I call the template function. But I'm constructing an object based on user input where the field names are not known beforehand and could be deeply nested anywhere in the object.
If I define the object that is returned beforehand then the data.title field in the example would already be evaluated and wouldn't use the input data. For example, I want to be able to define the template object like
obj = { title: this.title }
then redefine the template as
template = function () {
return obj
}
and call template.call({title:"Steve"}). But currently I get back
{ title: undefined }
because this.title was already evaluated when I defined obj. Maybe I'm approaching this the wrong way, because I keep coming to the conclusion that I'd have to modify the function by stringifying it, modifying the string to include the unevaluated code this.title and creating a new function from the string. But that seems like a plain awful idea.
And traversing the object looking for special values to replace seems expensive and complicated. I also looked for some sort of javascript object templating library but didn't find anything.
EDIT: To make it more clear that the input data and the template structure won't necessarily match, I may want have a template that looks like
template = function (data) {
return {
name: "Alfred",
stats: {
age: 32,
position: {
level: 10,
title: data.title
}
}
}
}
and call template({title:"Manager"}) to get
{
"name": "Alfred",
"stats": {
"age": 32,
"position": {
"level": 10,
"title": "Manager"
}
}
}
So I've managed to solve this by (ab)using functions as metadata to mark the values that should be replaced in the template. This is made possible by two things:
I only need valid JSON values, so I can safely say that functions aren't literal user input
JSON.stringify has a replacer parameter which will traverse the object and can be used to pass the input data to the template
Using a template generator like this
var templateMaker = function (object) {
return function (context) {
var replacer = function (key, val) {
if (typeof val === 'function') {
return context[val()]
}
return val;
}
return JSON.parse(JSON.stringify(obj, replacer))
}
}
I create a template object, replacing field names with functions that return the field name
var obj = {
name: "Alfred",
stats: {
age: 32,
position: {
title: function () { return 'title' },
level: function () { return 'level' }
}
}
}
then I create the template function, define my input, and render it to an object
var template = templateMaker(obj);
var data = {
title: "Manager",
level: 10
}
var rendered = template(data);
and magically, the object output looks like
{
"name": "Alfred",
"stats": {
"age": 32,
"position": {
"title": "Manager",
"level": 10
}
}
}
Maybe template engines like Mustache would help you with this.
You can define your object template in string:
var template = '{ title: {{title}} }';
then render it with the data, and convert it to json:
var data = {title: 'I am title'};
var obj = JSON.parse(Mustache.render(template, data));
UPDATE:
I read your updated example, here is the corresponding example:
var template = JSON.stringify({
name: "Alfred",
stats: {
age: 32,
position: {
level: 10,
title: '{{title}}'
}
}
});
var data = {title: 'I am title'};
var obj = JSON.parse(Mustache.render(template, data));
obj.stats.position.title == "I am title";