I am currently working on a project in which I have to maintain an object that contains an array of smaller objects (collections) in js. Adding and editing seem to be working fine but I have hit a snag when trying to remove from the the object.
removeCollection(collectionId, index){
let copyCollectionItems = {...this.state.collectionItems};
copyCollectionItems[collectionId].splice(index, 1);
this.setState({ collectionItems: copyCollectionItems});
}
In the above code the object's state before the call looks something like:
{
collectionId-1: Array(4)[{...}, {...}, {...}, {...}],
collectionId-2: Array(2)[{...}, {...}],
collectionId-3: Array(1)[{...}]
}
Assuming the collectionId coming in is "collectionId-1", I expect the object to look like this after the call:
{
collectionId-1: Array(3)[{...}, {...}, {...}],
collectionId-2: Array(2)[{...}, {...}],
collectionId-3: Array(1)[{...}]
}
Instead I see that there are no changes to the object after the function call (collectionId-1 still has 4 objects in the array).
Is there something wrong with the way I am copying my object? Maybe the reference data is overwriting the new data? I have no idea why the object isn't changing.
I should also add that if the index coming in is 0, then the removal is successful. Any other index will not change the object.
Related
So I've got a vue component I'm using as an editing interface...
The database has a jsonified array inside of it (don't ask... I don't like it either), which has to be in a particular format... In order to allow admins to edit this string array without breaking the format, I'm making a vue editing component which will break the parts up into various textboxes etc...
I would like to have two separate variables - one for what the string array IS, and one for what they are changing... the first variable would be updated when they saved their changes...
The issue I have is that for some reason, when I update one of the variables... not only does the other variable change... but the prop changes as well...
I was under the impression that components could not change their props..?
In particular, the array looks something like this:
[
'1',
'2'
['1','2','3','4']
]
And when I do a .splice() on the sub-array, both variables and the prop updates...
Some sample code...
Laravel blade view:
<editor :somearray={{ $someJsonifiedArray }}></editor>
Component props/data setup:
props: {
somearray: {
default: [],
type: Array
}
}
data(){
return {
editedArray: this.somearray, // This is what will be saved
wipArray: this.somearray // This is what changes as they edit
}
}
Some of the methods:
resetChanges(){
this.wipArray = this.editedArray;
}
I'm probably missing something obvious... or misunderstanding how things work...
Javascript Array/Object is passed by reference, not by value!
if you do this
return {
editedArray: this.somearray, // This is what will be saved
wipArray: this.somearray // This is what changes as they edit
}
whenever you edit editedArray or wipArray, you are actually editing somearray, because they all refer back to the same array/Object .
So you gotta clone the array/Object instead of passing it directly. The simplest way to clone object is by using spread operator (or in some cases, deep cloning will be required). The simplest way to clone array is by using slice.
return {
editedArray: {...this.somearray}, // This is what will be saved
wipArray: {...this.somearray} // This is what changes as they edit
}
I am using Ajax to populate data properties for several objects. As such, the properties I want to bind to do not exist at the time of binding.
eg:
<template>
<my-list v-bind:dataid="myobject ? myobject.data_id : 0"></my-list>
</template>
<script>
export default {
data () {
return {
myobject: {}
}
}
</script>
In the Vue docs https://012.vuejs.org/guide/best-practices.html it mentions to initialize data instead of using a empty object.
However I am using multiple Ajax created objects with tens of parameters and sub parameters. To initialize every sub-parameter on all objects like this:
myobject: { subp1: [], subp2: [] ...}
where myobject may be an object containing array of objects, or an array of objects containing sub-arrays of objects for example.
would take quite a bit of work. Is there a better alternative when binding to 'not-yet existing' objects?
First of all, an empty array is still "truthy", so your check here
v-bind:dataid="myobject ? myobject.data_id : 0"
always returns true. You should check for myobject.length instead. Your code should work now.
Also, you really don't need to define dummy objects for an array. Vue detects whenever you mutate an array.
https://v2.vuejs.org/v2/guide/list.html#Array-Change-Detection
I have a two-part issue.
1) I need to access a list of unique values nested within a complicated object. I am able to output the object via a console.log as such:
console.log(dataStore);
This outputs the following (in part):
`Object
getResponses: function getResponses(ids)
arguments: null
caller: null
length: 1
name: "getResponses"
prototype: Object
__proto__: function ()
<function scope>
Closure
responseCache: Object
12345: gr.Response
12346: gr.Response
etc...
getImg: function (imageId)
etc... `
I need a call that gathers the list of numeric values under responseCache: 12345, 12346, 12347, etc. The total amount of these values may very. Could be 10, could be 100 in the list.
2) I need to create a conditional statement that compares the value for a variable that is not a part of the object above. For example:
variableX = variableXvalue;
if ("variableXvalue" is one of the unique values in "responseCache") {
//then do this
}
Not sure if it matters for the purposes of the question here, but the variableX is in a loop that iterates through attributes on a page. It loops through all matching tags/attributes on a page, and needs to compare those attribute values with the full list of responseCache values each time it loops.
Thank you for considering this question.
Let's look at an example of how this sort of code could be written.
var obj = (function() {
var responseCache = {
12345: 12,
12348: 34,
12355: 56
};
return {
getResponses: function getResponses(ids) {
return responseCache[id];
}
};
})();
console.log(obj);
If you run that code in your console, you'll get able to drill down and see essentially the same output as what you're seeing. Now, how can you directly access responseCache? You can't. It's effectively private and only directly accessible from within that closure. Outside code cannot access that variable directly. You can only indirectly access it if any functions on obj use it.
I'm trying to build a key/value relationship for an ajax based web app. I've decided to use a pure array-based approach as iterating arrays is faster than objs (or so I'm told).
The base of the idea looks like this:
var keyVals = [
[ "key1", ["value1"] ],
[ "key2", ["value2"] ],
];
However when I iterate the array to delete/set or change a key, the event doesn't run as expected:
For example:
console.log(keyVals);
function delKeyPair(key) {
for (var i = 0; i < keyVals.length; i++) {
if (keyVals[i][0] && keyVals[i][0] === key) {
Array.prototype.splice.call(keyVals, i, 1);
return true
}
}
return false
};
delKeyPair("key1");
console.log(keyVals);
When I first console.log() the array - it shows that "key1 has already been deleted, before the function is called.
here is a fiddle, not quite sure what's going on. Any help is much appreciated.
http://jsfiddle.net/3pfj8927/
key1 has not already been deleted before calling function:
try console.log(keyVals.length);
DEMO
Output:
Length before deleting: 2
Length after deleting: 1
The console runs asynchronously. It also keeps a reference to your object.
Your code is running just fine.
When you look at the object in the console, it shows you the current way it looks, not how it was at the time of the log.
If you replace console.log(keyVals); with console.log(keyVals.slice());, you should see the proper objects, because we copy them as-is.
The key1 has not been deleted. Note you're working on a reference of the given array. If you inspect the Array it will be loaded by the reference. Because you're changing the reference in the delKeyPair function it seems that there never was a key1.
If you copy the array on delete you'll see everything works like expected.
I have two objects. One is the master data, another is a similar object but contains certain properties that I am using and is a subset of the master data. Please find below the two objects:
$scope.masterData = {
"StoresForOrgs": {
"PPP0001188": ["007071","007073","007079"],
"PPP0001189": ["007075","0070756","0070789"],
"PPP0001190": ["007075","0070756","0070789", "00707893", "00707899"]
}
}
$scope.masterDataForDisplay = {
"StoresForOrgsDisplay": {
}
}
If in my code I do
$scope.masterDataForDisplay = $scope.masterData;
this is linking both the objects and if I change the masterDataForDisplay it is changing the masterData as well. Now I understand that comparing these two would create the same reference and this could be avoided by using then
try this
$scope.masterDataForDisplay = JSON.parse(JSON.stringify($scope.masterData));
but even when the code is not executed this is happening. Are the objects being initialized before?
use this:
$scope.masterDataForDisplay = angular.copy($scope.masterData);
instead of
$scope.masterDataForDisplay = $scope.masterData;
copy() : Creates a deep copy of source, which should be an object or an array. So they dont share the same reference