How to append properties in an object in Vuejs - javascript

I have Data in vuejs like following:
params: {
comment: Object,
state: "",
deleteAppointment: false,
appointmentId: null,
}
I am filling data from two functions. First function is just assigning following lines:
this.params.state = "BLACKLIST";
this.params.deleteAppointment = true;
this.params.appointmentId = this.appointmentId;
But, in the second function when I am assigning following:
const comment = {};
fd.forEach(function(value, key){
comment[key] = value;
});
const data = {};
Object.keys(this.lead).map((key) => {
if (this.lead[key] != this.orginal[key]) {
data[key] = this.lead[key];
}
});
this.params = data; // May be the problem is here, data is overwriting existing properties of params
this.params.comment = comment;
When assigning data in params, previous properties are vanishing!
May be I need object copy or something! I couldn't understand what I have to do actually right now.

You should inherit the previous object using Spread Operator, try this
this.params = {...this.params, ...data};

Related

Is there a way to force a javascript element to redefine itself based on how it was originally defined?

I was playing around with objects and constructors and stuff like that, and I was wondering if there was a way to bind a value to a variable based on how it was originally defined. I have the following code:
typescript
let cr = "create",
ap = "apply",
$this = {
set: (prop, value) => {
this[prop] = value;
}
};
function creator() {
this.$ = (array: Object[]) => {
array.forEach((kp: Object) => {
let key = Object.keys(kp)[0];
let val = kp[Object.keys(kp)];
$this[key] = val;
creator.create(key, { value: val });
});
};
this.apply = (...objects: Object[]) => {
objects.forEach((obj: Object) => {
creator.call(obj);
});
};
}
function create(obj) {
function createValues(arr) {
let instance: Object = new obj();
let vals: any[] = [];
arr.forEach(name => {
vals.push(instance[name]);
});
return vals;
}
let names: string[] = Object.getOwnPropertyNames(new obj());
let values: string[] = createValues(names);
return combineArrays(names, values);
}
function combineArrays(arr1, arr2): { $?: any } { // the question mark removes an IDE error
let newObj: Object = {};
arr1.forEach(prop => {
newObj[prop] = arr2[arr1.indexOf(prop)];
});
return newObj;
}
Object.prototype.create = function(prop, options) {
return Object.defineProperty(this, prop, options);
};
create(creator).$([
{ hi: "hi" },
{ bye: $this["hi"] } // this is the important stuff
]);
I was wondering if there is a way, inside the set function of the $this variable, to detect how it is being set and therefore determine if that value has changed and so it's value should to, if that makes any sense? Let's say you had this:
let $this = {
set: function(prop, value) {
this[prop] = value;
}
}
let name = 'Ezra';
$this['name'] = name;
// then :
name = 'Bob';
// change $this.name too, so then:
console.log($this.name);
// >> 'Bob'
I believe this is called Data-Binding but I am unsure how to do it without creating endless numbers of proxies.
What you're describing is not really "data-binding" but pass-by-reference. In your example you expect an update to name to be reflected in $this['name']. That would only be possible if you were passing a reference (or a pointer) to the variable.
However, in this case the variable is a string, and strings in JavaScript are immutable:
no string methods change the string they operate on, they all return new strings. The reason is that strings are immutable – they cannot change, we can only ever make new strings.
So, going step-by-step through your example:
This creates a new string named 'Ezra', and assigns a variable called name to reference that string.
let name = 'Ezra';
This creates (or sets) a property in $this called 'name' that references the string in name (which is 'Ezra').
$this['name'] = name;
This creates a new string called 'Bob' and stores it in the variable called name. The variable already exists. This does not mutate the value that was previously held in there. Instead, name is being updated to point to a new reference.
// then :
name = 'Bob';
However, if you were to pass an object, you'll notice that you can actually mutate it. This is because objects are passed-by-reference and you can mutate the value at that reference.
For example:
// Create a new value that stores an object, with a property 'firstName'
let name = { firstName: 'Ezra' };
// Assign myObject to $this['name']. Now $this['name'] and name both point to the same reference.
$this['name'] = name;
// Change the value in the object pointed-to by name
name.firstName = 'Bob'
console.log($this['name'].firstName); // <- This will output 'Bob'

Access dynamically created objects in Javascript

I am attempting to dynamically create an object with name-value pairs using html input fields. This is what i have so far:
var taskComplete = {
newTask: function(arg) {
var fieldObj = {},
selector = arg,
inputFields = document.getElementsByClassName(selector);
for (var i=0;i<inputFields.length;i++) {
var attrValue = inputFields[i].getAttribute("name"),
value = inputFields[i].value,
newFieldObj = fieldObj[i] = {[attrValue]: value };
console.log(newFieldObj);
}
}
}
taskComplete.newTask('input');
The console log outputs:
Object {title: ""}
Object {description: ""}
Object {date: ""}
Question1:
How do i access these objects? they all share the same name eg. 'Object' so 'object.title' does not work.
Question2:
Is there a way to combine these objects into a single object?
eg.
var obj = {
title: "",
description: "",
date: "",
}
code example with html: codepen.io
Hope this make sense. Thank you for any and all assistance.
I will answer your questions in the reverse order, makes more sense, you will see.
Question2: Is there a way to combine these objects into a single object?
Yes, I am happy to inform you that you absolutely can. Where you do
newFieldObj = fieldObj[i] = {[attrValue]: value };
simply do
fieldObj[attrValue] = value;
What this does, is the following: On the fieldObj, which is a plain {} set a key named after the value of attrValue and pair that key with the value value
Question1: How do i access these objects? they all share the same name eg. 'Object' so 'object.title' does not work.
In order to be able to access these objects, your newTask method should be returning them. So, at the end of your newTask method, simply do return fieldObj; like so
var taskComplete = {
newTask: function(arg) {
var fieldObj = {},
selector = arg,
inputFields = document.getElementsByClassName(selector),
attrValue,
value;
for (var i=0;i<inputFields.length;i++) {
attrValue = inputFields[i].getAttribute("name");
value = inputFields[i].value;
fieldObj[attrValue] = value;
}
return fieldObj;
}
}
and then store the returned value to a new variable like so:
var aFancyName = taskComplete.newTask('input');
Here's the modified pen: http://codepen.io/anon/pen/XdjKQJ
Not super clear on what you are trying to do here.
Instead of creating a new object for each iteration of your loop, why not just assign those properties to the fieldObj you already have?
Then you can just return that object and do whatever you want with it in the calling code:
'use strict';
// ** TASK OBJECT ** //
var taskComplete = {
newTask: function(selector) {
var fieldObj = {},
inputFields = document.getElementsByClassName(selector);
for (var i = 0; i < inputFields.length; i++) {
var attrKey = inputFields[i].getAttribute("name"),
value = inputFields[i].value;
fieldObj[attrKey] = value;
}
return fieldObj;
}
}
var o = taskComplete.newTask('input');
console.dir(o);
http://codepen.io/anon/pen/reMLPB?editors=0010

Assign value in javascript

I have two objects : $scope.objectA and $scope.objectB.
I assign value from $scope.objectA to $scope.objectB like this:
$scope.objectB.value1 = $scope.objectA.value1;
then I make value1 of $scope.objectB to null;
$scope.objectB.value1 = null;
My question is why when I assign $scope.objectB.value1 to null, $scope.objectA.value1 is null too. How can I keep value of $scope.objectA.value1 while changing value of $scope.objectB.value1?
Make copy of object B and assign it to the object A. Use angular.copy function. It will creates a deep copy of source.
For more information Visit Angular copy doc
$scope.objectA.value1 = angular.copy($scope.objectB.value1);
Because this is how it works. You make these two variables "bound" together.
If you want to keep value of objectA, then use
$scope.objectB.value1 = angular.copy($scope.objectA.value1);
I think this can happen only if ObjectA and ObjectB refer to the same object on the heap, i.e. it ObjectA and ObjectB are the same objects
$scope['object1'] = {};
$scope['object1']['val'] = {};
$scope['object2'] = {};
$timeout(() => {
this.$scope['object2']['val'] = this.$scope['object1']['val'];
$timeout(() => {
this.$scope['object2']['val'] = null;
console.log(this.$scope['object1']['val']); // Object {}
})
});
-
$scope['object1'] = {};
$scope['object1']['val'] = {};
$scope['object2'] = {};
$timeout(() => {
this.$scope['object2']['val'] = this.$scope['object1']['val'];
$timeout(() => {
this.$scope['object2']['val'] = null;
console.log(this.$scope['object1']['val']); // null
})
});
The reason is when you assign object to a variable, the assignment will be by reference, so the old and new will be a reference to the original object
So when you edit an object, you're actually editing the original object.
The solution
Angular: use object = angular.copy(myObject1)
jQuery: object = $.extend({}, myObject1);

Merge objects dynamically - Object Property Name Issue

I'm trying to merge objects together, or add new objects to existing objects.
I've already got it working as for merge using jQuery, but it's the name of the property that wont work dynamically.
The parameter filters is an object, such as {test:123}.
When invoking filter({test:123});, I want the filter function to dynamically add objects to a global object. (and of course can't use push() since its not an array)
this.filter = function(filters) {
for (var key in filters) {
$.extend( settings.filter, {key:filters[key]} );
}
};
The problem is that "key" turns into "key" as the name of the property. When it should be "test" as the property name; I can not get the property name to be created dynamically.
The goal would be to allow the user to fire the function like this:
filter({test:123,test2:1321,test55:4})
and dynamically add objects to the global settings object without the user meddling with the object itself.
Your code does not work because key is not being interpreted as a variable when being directly set in the object.
$.extend( settings.filter, {key:filters[key]} );
Considering:
var keyName = "Test";
var badObj = { keyName: "Hello World" };
You would get undefined when calling newObj.Test because it is actually newObj.keyName.
In order to use a variable to create a property name, you need to use different syntax.
var keyName = "Test";
var newObj = {};
newObj[keyName] = "Hello World";
You could then reference and use newObj.Test to get "Hello World"
To fix the method you provided, you can adjust it to:
this.filter = function(filters) {
for (var key in filters) {
if (filters.hasOwnProperty(key)) {
var newObj = {};
newObj[key] = filters[key];
$.extend(settings.filter, newObj);
}
}
};
Keep in mind you can simplify this and just use the extend method. This would be better, unless you are looking to do your own filtering as the method name suggests.
this.filter = function(filters) {
$.extend(settings.filter, filters);
};
Demos
You should create temp obj before extend :
this.filter = function(filters) {
for (var key in filters) {
var obj = {};
obj[key] = filters[key];
$.extend( settings.filter, obj );
}
};

optional initialisation properties for new Javascript object

Is this the correct way to make a javascript class with default properties (even though some here are null), yet also having the option to add a creation argument that can contain specific values for some properties listed in object format/json?
Also should i put any of this into Person's prototype to save memory if I am creating many Person objects?
this is working for me but I wonder if it is a good way to do this ?
// PERSON Class -----------------------------------------------
QM.Person=function(data)
{
/* Closure for this */
var my = this;
this.PersonID=null;
this.Name_Last="";
this.Name_First="";
this.Date_Birth=null;
this.Biography="";
this.loadData=function(obj) {
for (var i in obj) {
if (my.hasOwnProperty(i)) {
my[i] = obj[i];
}
}
}
this.loadData(data);
}
example of creating using this class:
jondoe = new Person();
bob = new Person({Name_First:"Bob",Name_Last:"Bar"});
jondoe.Name_First /* "" */
bob.Name_First /* "Bob" */
To avoid repeating yourself you could build a list of keys you expect and also the default values to insert if they aren't specified:
MyType = function(data){
var keys = this.keys,
data = data || {},
key
for (key in keys) {
if (keys.hasOwnProperty(key)) {
if (data.hasOwnProperty(key)) {
this[key] = data[key];
} else {
this[key] = keys[key];
}
}
}
};
MyType.prototype.keys = {
personId: null,
firstName: 'A default first name',
lastName: ''
};
var o1 = new MyType();
var o2 = new MyType({
personId: 1,
firstName: 'Override'
});
console.log(o1, o2);
I wouldn't do it that way. I would do
QM.Person=function(data)
{
data = data || {};
this.PersonID= data.PersonId || null;
this.Name_Last= data.Name_Last || "";
...
}
You will note I am assuming you care about the explicit type, i.e. when you assign null, you want null, and not undefined. Same thing for "".
I think this is just simpler than creating a function and executing it to clean up your data
Finally, all methods your want to add to the function should be on the prototype. Properties should NOT be on the prototype, unless you want all instances to share the same properties. Since you don't have any methods other than your data-cleaner, nothing you have shown should go on the prototype.

Categories

Resources