I am creating a new Javascript object and passing the values into the constructor I would like the object to have. One value is a moment object (holding a date) I can see that the date is correct (2017-05-09) but the newly constructed object always has the value 2017-05-04. If I do a console.log on the attribute: object.start_date, then I am able to see the correct date, but if I do console.log on object, it shows the moment object with the wrong date 2017-05-04. I've tried updating in the constructor, manually doing an update on the object after creation, or by updating the value within the created object with a new instance function, but nothing changes the date. Here's some code/output.
Main question: Why is the moment object not being updating with the correct value I am giving it?
Thank you.
Function to create new route:
duplicateRouteSuccess(data) {
let route = new Route(data['routeData']);
route.changeStartDate(data['routeData']['starts_at']);
console.log(route);
console.log(route.starts_at);
this.routeCalendar.scheduleRoute(route, route.repeats);
this.close();
}
and the constructor:
constructor (data) {
this.id = data['id'];
this.name = data['name'];
this.starts_at = moment(data['starts_at']);
this.repeats = data['repeats'];
this.repeat_rate = data['repeat_rate'];
}
UPDATE
doing JSON.stringify to my objects did show that they both have the same date, of 2017-05-08. But then my question is "when I access the attribute object.start_date to set the object onto a calendar, why does object.start_date say 2017-05-04"? Here is the stringify output image:
UPDATE 2
The route.changeStartDate was just an instance function I created to attempt to update the "starts_at" field a second time since it did not appear to be updated in the constructor of the Route class. Here's the code for that:
changeStartDate(start_date){
this.starts_at = moment(start_date)
}
Related
I have a complex variable as an object including 2 times the same object.
if I change a value of the first object part, this will assume to change the value of the second part. is there an explanation? why are the tow keys still connected?!
here is a simple example of my code:
arr1={'a':[],'b':{'b1':'','b2':''}};
arr2={'p1':{...arr1},'p2':{...arr1}};
arr2['p1']['a']=[1,2,3];
console.log(arr2['p2']['a']); // works => []
arr2['p1']['b']['b1']='blabla';
console.log(arr2['p2']['b']['b1']); // doesn't work => 'blabla'
I don't want to write 'B={'b1':{'a':''},'b2':{'a':''}}' because A is a very big object in a separated .js file
A={'a':''};
B={'b1':A,'b2':A};
B['b1']['a']='blabla';
The main reason is that you try to change the object element via its index a instead of changing the object (reference). Step by step,
you ask to find B['bi'], which is A object
and then you ask to set A['a'] to blabla
B['b1'] and B['b2'] point to A
you get "both" changed since it's same instance of A
But if you do B['b1'] = { 'a': 'blabla' }, then you will not get the same result. Because now you are adding a new instance without any connection to A.
- use spread operator will save you from a problem like this
The fundamental idea of the spread operator is to create a new plain object using the own properties of an existing object. So {...obj} creates a new object with the same properties and values as obj
you can do that easily like
A={'a':''};
B={'b1':{...A},'b2':{...A}};
B['b1']['a']='blabla';
console.log(B['b2']); // => '' not 'blabla'
I solved the problem with:
arr2={'p1':JSON.parse(JSON.stringify(arr1)),'p2':JSON.parse(JSON.stringify(arr1))};
In my Vue.js app, I have an array value that should only be updated when a user completes a specific "refresh" action. However, as soon as I assign a new value to that array value, the array value becomes reactive and changes instantly as the data in the assigned value changes. The array value should remain un-reactive.
For example, I have a method, refresh(), which when triggered is meant to update displayedData, which should not be reactive, with currentData, which should be reactive. displayedData should only update when refresh is called.
methods: {
refresh: function() {
this.displayedData = this.currentData;
}
}
To make a value not reactive without making it static, you can make a "deep copy" of it using stucturedClone(), which is becoming widely supported as of 2022:
this.displayedData = structuredClone(this.currentData);
Another widely used method is to use JSON to encode and then decode it:
this.displayedData = JSON.parse(JSON.stringify(this.currentData));
Both of these methods assign the current state of one value to another value, and no changes to the first value will change the second value until this code is triggered again.
The reason this is necessary isn't because of Vue.js specifically, but because of JavaScript in general. In JavaScript, arrays and objects are "passed by reference" rather than "passed by value".
An approach (WITHOUT disabling reactivity) is to use a different array for your temporary data and move stuff over in to the good array when the user presses refresh.
You could copy the values in the first array into the temp array like this.temp = this.permanent.slice() in the created or mounted life-cycle function.
Slice would make a shallow copy of the array. If you need to also clone the items in the array, then maybe use some deep copy library or the JSON.parse(JSON.stringify(...)) method.
If you DON'T add the currentData to the data() method then it will not be reactive.
export default {
currentData: [],
data() {
return {
}
},
methods: {
refresh: function() {
this.displayedData = this.currentData;
}
}
}
You can then still reference currentData in the section using {{ $options.currentData }}
You can use destructuring assigment:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment?retiredLocale=it
this.displayedData = {...this.currentData}
You will have a new object made with the "copied" data from the first
I have to add a property for an object returned from my db before pushing it to an array. Changing properties work, but adding new ones doesn't. Can anyone can explain the logic behind this behavior?
ids.forEach(async (id, index) => {
//get object without highlight property
let real_a = await database.getA(id)
real_a.highlight = "shoud add highlight property to real_a object"
realItems.push(real_a)
// the correct string is printed
console.log(real_a.highlight)
//object still doesn't have that property
console.log(real_a)
}
It was the intended behavior.Sorry for bothering.
I was using a mongodb query for the database.getA(id) function and it turns out you have to specify a parameter in the mongodb query to get an actual changeable JSON object.
Here is the complete answer:
Why can't you modify the data returned by a Mongoose Query (ex: findById)
I'm having trouble using the setter functions on my Sequelize js model properties.
What I want to do is when one property is given a value use that value to populate another property in the table at the same time.
In my model this is the code I have for the property in question...
date_time_paid: {
type:DataTypes.DATE,
set(val) {
const date = new Date(val);
this.setDataValue('date_time_paid', val); // set the the current property
this.setDataValue('month_paid', `${date.getFullYear()}-${(date.getMonth() + 1)}`); //also set another property on the same row
},
},
What I expect to happen is for the date_time_paid column to store the raw value and the month_paid column to store a string derived from it. But when I run my seeder to populate the table with test data the value for the month_paid column remains null.
Is this the correct use of a setter function?
If it is what have I done wrong that means it's not working?
I think you need a just a getter. Forget about date_time_paid and make getter for month_paid:
get month_paid(){
const date = new Date(this.date_time_paid);
return `${date.getFullYear()}-${(date.getMonth() + 1)}`;
}
document.getElementById("submit").addEventListener("click", getElements)
function getElements() {
var a = document.getElementById("sample").value;
var x = new obj(a);
function store() {
localStorage.setItem('todays-values', Object.values(x));
}
store();
}
In a separate js file I then call
localStorage.getItem('todays-values');
I get the values, but if I put new inputs into my html file and click the submit button, the previous values get overwritten and replaced by the new ones. How do I store all the values that are submitted and prevent the old ones from getting replaced?
I'm very new to Javascript so I would prefer to solve this problem without the use of any additional libraries if possible.
First: it seems that you are mixing JavaScript a class with a function (here is an example: What techniques can be used to define a class in JavaScript, and what are their trade-offs?)
For example this is the class equivalent in JavaScript:
function ClassName() {
var privateVar;
this.publicVar;
function privateFunction() {}
this.publicFunction = function() {};
}
You shouldn't wrap a function in a function unless it has a meaning (beacuse it is confusing for other people otherwise), but in the example given you don't need that. Also I can't see the reason why you are creating a new object x - if you create the object right before you save it you could just save the value because the object will only contain the value from sample, so you could write something like this:
document.getElementById("submit").addEventListener("click", getElements);
function storeElements() {
var sampleValue = document.getElementById("sample").value;
localStorage.setItem('todays-values', sampleValue);
}
Back to your question:
As Kalamarico mentioned: if you write new values into todays-values you will overwrite your old values, you could simply load all old values from the localStorage append the new ones and write them back to the localStorage.
You should also note that the localStorage only takes strings, so you should stringify objects (see localStorage.setItem).
function appendValueToStorage(key, value) {
var values = JSON.parse(localStorage.getItem(key));
if (values === null) {
values = [];
}
values.push(value);
localStorage.setItem(key, JSON.stringify(values));
console.log(localStorage.getItem(key));
}
appendValueToStorage('todays-values', document.getElementById("sample").value);
The function will let you append some value for a key, you could even wrap this function again to be able to use it in your click function:
function onSubmitClick() {
appendValueToStorage('todays-values', document.getElementById("sample").value);
}
document.getElementById("submit").addEventListener("click", onSubmitClick);
With the console.log command you can see the current content of the localStorage (you could also check with the developer tools - I find the ones for chrome work the best, under the Application -> Local Storage tab you can check the localStorage of your page).
You need read more about localStorage, this is a new feature introduced with HTML5, you can take a look here and see all features.
localStorage stores your data like a JSON object, if you don't know what is JSON, you need to find info. In javascript think in objects in this way:
var myData = {
myName: 'Kalamarico',
myAge: undefined
};
This is a Javascript object, and JSON is very similar and it is a representation of objects.
localStorage API stores your data as this way, when you do:
localStorage.setItem('todays-values', Object.values(x))
localStorage saves a new entry, one key 'todays-values' and its value is an object, so, your localStorage seems:
{
"todays-values": { ... }
}
Every time you set a "todays-values" you will overwrite the key, as you are seeing, so, if you can keep old values, you need to do this manage, first you can get items in localstorage (if there are), and after you can "merge" your old value and the new value. Or you can set a new key, for example: "todays-values1" depends on your need.
If you need to store exactly one key-value pair per day, then you could add the date in the key string.
Else how about numbering the keys ("yourKey_0", "yourKey_1", ...) and also storing the current (biggest) index ("currentIndex")in local storage:
function store(value) {
newIndex = localStorage.getItem("currentIndex") + 1;
localStorage.setItem("yourKey_" + newIndex, value);
localStorage.setItem("currentIndex", newIndex);
}
If you run into problems storing integer values, convert to strings.