Why Javascript object didn't change? - javascript

Can someone explain me this strange js behavior ?
All of this is in AngularJS.
I have helper function in my main app.js to simply return element from an array by its id:
var MyLib = MyLib || {};
MyLib.helpers = {
find: function(needle, stack) {
for (var i = 0; i < stack.length; i++) {
if(stack[i]._id === needle)
return stack[i];
}
return false;
}
}
Then I have factory and function to handle database change:
// categories are grabbed from db
var categories = [some array of objects];
// change is object returned from database that has all info about object as well as new object itself
function handleChange(change) {
var _category = MyLib.helpers.find(change.id, categories);
// if deleted, that part is ok
if(change.deleted) {
var idx = categories.indexOf(_category);
if(idx !== -1) {
categories.splice(idx, 1);
}
} else {
// if updated that part is weird
if(_category) {
_category = change.doc;
}
// if newly added that part is ok
else {
categories.push( angular.copy(change.doc) );
}
}
}
Why when I try to update element grabbed from categories array doesn't update in categories array ?
// categories ARE NOT updated after this
_category = change.doc;
and only when I refer to categories by index like this:
// categories ARE updated after this although _category is returned from this array by index (find function)
var idx = categories.indexOf(_category);
categories[idx] = change.doc;
I don't understand this...

You are overwriting the variable with a new value and any reference to prior value is gone.
Instead of overwriting the original object value with a new object you could update the existing object using angular.extend()
angular.extend(_category, change.doc);

I didn't analyze everything, but you should always have dot notation.
_category pass by value, and will not change when 'MyLib.hel ...' is changed
var _category = MyLib.helpers.find(change.id, categories);
something.category pass by reference, and will be changed when 'MyLib.hel ...' is changed
var something.category = MyLib.helpers.find(change.id, categories);

Related

How to prevent object to add duplicate value and stop excuting function

Hey guys i am adding data to the array as object but i wanted to if there is any duplicate item code so its stop excuting the function and return and if the the condition is true so its take the constructor value and add itno the data structure
This what i try to prevent it from adding the value but its not work as i want
function getNo(b){
for (const [key, value] of Object.entries(data)) {
let val = value.itemCode;
if(b === val){
alert('Its equalt to item code');
break;}else{ return b;};
}}
----What i want is-----
1) Check if value is duplicate or not from the itemCode constructor
2)If its a duplicate value so its should show and alert and stop excuting the function
3)And add this function into the addItem function to check its duplicate or not
4)I store value in the data array
var item = function(name,itemCode,stock){
this.name = name;
this.itemCode = itemCode;
this.stock = stock;
}
var data = [];
function addItem(name,itemCode,stock){
var Newitem = new item(name,itemCode,stock);
data.push(Newitem);
}
addItem('BlueTee',100,50);
addItem('Yellow tee',101,100);
addItem('BrownTee',102,120);
There are multiple ways to handle this. Your choice should depend on other use cases.
The easiest way is to define data as a javascript object instead of an array. This would require keys for each object. This would look like this:
var data = {};
function addItem(name, itemCode, stock){
var newItem = new item(name, itemCode, stock);
if(data[itemCode] === undefined)
data[itemCode] = newItem;
}
If you are going to later access data as an array, then you can instead iterate over the array for each insertion. This would look like this:
function addItem(name, itemCode, stock){
var newItem = new item(name, itemCode, stock);
if(!data.some(function(x => x.itemCode === itemCode)){
data.push(newItem);
}
}
This would be slower than a normal insertion especially for large datasets. If you are going to use a very large dataset and need to be able to access as an array, then I would use a hybrid between the two. The javascript object would be used for direct access to the object. A class-like implementation would be preferred for that, but without using oo, the code would look something like this:
var data = [];
var keys = {};
function addItem(name, itemCode, stock){
var newItem = new item(name, itemCode, stock);
if(keys[itemCode] === undefined){
data.push(newItem);
keys[itemCode] = data.length - 1;
}
}
This implementation also gets complicated if you are going to modify the array more than just adding elements
You can map the data array to itemCodes and see if it includes the itemCode of the new item, and if so return an empty object for your constructor. Then in your addItem function you can choose not to add the object to the array if the object is empty.
var item = function(name,itemCode,stock){
if (data.map(i => i.itemCode).includes(itemCode)) {
alert("This item has a duplicate itemCode");
return this;
}
this.name = name;
this.itemCode = itemCode;
this.stock = stock;
}
var data = [];
function addItem(name,itemCode,stock){
var Newitem = new item(name,itemCode,stock);
if (Newitem.name) data.push(Newitem); // check if an object was created with properties
}
addItem('BlueTee',100,50);
addItem('Yellow tee',101,100);
addItem('BrownTee',102,120);
addItem('RedTee',100,70); // this won't be added because of duplicate itemCode
console.log(data); // only contains BlueTee, Yellow tee, and BrownTee objects

Store new value in an array of objects

I want to change the value of an object of an array but seems like values are not saving.I read about immutable objects but there must be somehow a way to do that.I would be glad for any help, thank you.
app.get('/api/reservations',function(req,res) {
Rezervari.getReservations(function(err,reserv){
if(err){
throw err;
}
let datas = reserv
for( var i=0;i < reserv.length ;i++){
let changetime = dateformat(datas[i].data).format("MM-DD-YYYY")
datas[i].data = changetime;
datas[i].data = dateformat(datas[i].data).format("MM-DD-YYYY")
console.log(datas[i].data) // 2018-09-17T21:00:00.000Z
console.log(changetime) // 09-18-2018
}
res.json(datas);
});
});
Edit: The object is reserv or datas(same array).I want to change field dataof reserv from ISO format to MM-DD-YYYY format.Value is changed in var changeTime but in the array value of data is not changed.
This could happen if the objects in the array were proxies. Here's an example of how you could implement something similar:
const handler = {
get: function(obj, prop) {
if (prop === 'data') {
return this._data.toISOString();
}
},
set: function(obj, prop, value) {
if (prop === 'data') {
this._data = new Date(value);
}
}
};
let obj = new Proxy({}, handler);
obj.data = '2018-09-17';
console.log(obj.data); // returns '2018-09-17T00:00:00.000Z'
If this is your case, and you want to avoid the proxy behavior, you could map the original array to a new one:
res.json(datas.map(item => {
return {
data: dateformat(item.data).format("MM-DD-YYYY")
/* extract any other properties you're interested in from the original objects */
};
}));
You could try cloning the Javascript objects, populating a new array and returning it. Here is an example:
let datas = [];
for (let i = 0; i < reserv.length ; i++){
const clone = Object.assign({}, reserv[i]);
clone.data = dateformat(reserv[i].data).format("MM-DD-YYYY");
datas.push(clone);
}
res.json(datas);

Pushing object into array erases instead of adding

I have a function like this :
$scope.saveSearch = function () {
var alreadyExist = false;
for (var i = 0; i < $scope.savedSearch.length; i++) {
if (JSON.stringify($scope.searched) === JSON.stringify($scope.savedSearch[i])) {
alreadyExist = true;
break;
}
}
if (!alreadyExist) {
$scope.savedSearch.push($scope.searched);
localStorage.setItem("savedSearch", JSON.stringify($scope.savedSearch));
}
};
Before that : $scope.savedSearch = [];
$scope.searched = {
IS: "",
area: "",
block: "",
type: "",
level: ""
};
The values in $scope.searched object are initialized and then modified by the user.
My problem is :
$scope.savedSearch always contains only the last pushed object. Instead of adding the object to the array, it just replaces the current object.
I don't understand why.
You'll want to change your push line to:
$scope.savedSearch.push(angular.copy($scope.searched));
I believe your problem is that objects are passed by reference. Since the object you have in the savedSearch is always pointing to the exact object you're searching, alreadyExist will always be true.
My guess is that the object reference is being stored in your array, not the actual object itself. Because of this, any subsequent calls to push the object to your array will not work because the object reference already exists in the array. It's merely updated.
Try this instead. Use angular.copy() to create a deep copy of the object and push the copy to your array. See if that works.
if (!alreadyExist) {
$scope.savedSearch.push(angular.copy($scope.searched));
localStorage.setItem("savedSearch", JSON.stringify($scope.savedSearch));
}
You are pushing the Object outside of the for so only 1 element get pushed in try move it inside the for and every object which doesnt already exist will be pushed in
$scope.saveSearch = function () {
var alreadyExist = false;
for (var i = 0; i < $scope.savedSearch.length; i++) {
if (JSON.stringify($scope.searched) === JSON.stringify($scope.savedSearch[i])) {
alreadyExist = true;
break;
}
if (!alreadyExist) {
$scope.savedSearch.push($scope.searched);
localStorage.setItem("savedSearch", JSON.stringify($scope.savedSearch));
}
}
};
easier way would be to just
$scope.saveSearch = function () {
var alreadyExist = false;
for (var i = 0; i < $scope.savedSearch.length; i++) {
if (JSON.stringify($scope.searched) != JSON.stringify($scope.savedSearch[i])) {
$scope.savedSearch.push($scope.searched);
localStorage.setItem("savedSearch", JSON.stringify($scope.savedSearch));
}else{
break
}
}
};

JavaScript-- Array Variable getting Updated Automatically

I was writing code for shopping cart function. When ever I add a product to cart, for each product, at first time and additional attribute called quantity gets added.
This is my code:
myStoreCartService.factory('Cart',function() {
var userCart = [];
var cartSummary = [];
var cartConsolidatedData = [];
var currentTotalMaster;
function formCart() {
cartConsolidatedData = [];
var dup = false;
var temp;
for(x in userCart) {
dup = false;
for(z in cartConsolidatedData) {
if(cartConsolidatedData[z].productname == userCart[x].productname) {
cartConsolidatedData[z].quantity = cartConsolidatedData[z].quantity + 1;
dup = true;
break;
}
}
if(!dup) {
// temp = userCart[x];
// temp.quantity = 1;
cartConsolidatedData.push(userCart[x]);
for(y in cartConsolidatedData) {
if(cartConsolidatedData[y].productname == userCart[x].productname) {
cartConsolidatedData[y].quantity = 1;
break;
}
}
}
}
};
return {
addItemToCart: function(cartData) {
console.log(cartData);
userCart.push(cartData);
formCart();
},
retrieveCart: function() {
return userCart;
}
});
Here even the fist item in userCart variable get quantity attribute, however just cartConsolidatedData variable's values should have got the this attribute.
I am stuck bad time here.
I'm not sure I understand your code but I suppose cartData is an object and you push that object to userCart like this
userCart.push(cartData);
then you push the same object to cartConsolidatedData with this command
cartConsolidatedData.push(userCart[x]);
So when you do this:
cartConsolidatedData[y].quantity=1;
You are adding a property to the cartData object and not as you state to the cartConsolidatedData array. Because cartConsolidatedData[y] is a cartData object and since it's a reference it means any change you do to it will also be reflected in the userCart array that points to the same cartData.

store value in JSON on button click

I am new in JSON, i am trying to save data using JSON. I have a list of element with some button when we click the button i want the corresponding value of button are save in JSON. I am also want to compare the title with already exists in JSON.
Demo Here
You can simply use a for loop to check if the element with that title is already there:
function alreadyAdded(itemTitle) {
for (var i = 0; i < objArray.length; i++) {
if (objArray[i].title === itemTitle) {
return true;
}
}
return false;
};
Also, you are not using a json object, just a JavaScript array.
Demo
try this
http://jsfiddle.net/Z3v4g/
var counter = 0;
var jsonObj = []; //declare object
$('.imgbtn').click(function () {
var title = $(this).parent().parent().find('span').html();
var image = $(this).parent().parent().find('img').prop('src');
for( var i=0; i<jsonObj.length; i++){
if( jsonObj[i].title == title ) return false;
};
counter++;
$('#lblCart').html(counter);
jsonObj.push({
id: counter,
title: title,
image: image,
description: 'Example'
});
});
I am assuming you want to store values in an array, and during a button click you want to check if the item already exists in the array. If this is true, then you can use the following code -
var counter = 0;
var jsonObj = []; //declare object
$('.imgbtn').click(function () {
var title = $(this).parent().parent().find('span').html();
var image = $(this).parent().parent().find('img').prop('src');
var match = $.grep(jsonObj, function (e) {
return e.title == title;
});
if (match.length > 0) {
// This title already exists in the object.
// Do whatever you want. I am simply returning.
return;
}
counter++;
$('#lblCart').html(counter);
jsonObj.push({
id: counter,
title: title,
image: image,
description: 'Example'
});
});
Notice that I have declared the array outside the callback function. This ensures that all the invocation of the callback operate on the same array object. Declaring it inside the callback was only making it available for a single callback invocation.
Also note that you are simply using an array to store plain JavaScript Objects.
Demo.
First:
var jsonObj = []; //declare object
This is not a JSON. This is an Array. JSON is just the notation of Javascript Object. To declare a object you should do:
var jsonObj = {};
or:
var jsonObj = new Object();
After this, you can approach what you asked doing this:
var counter = 0;
var jsonObj = new Object();
$('.imgbtn').click(function () {
var title = $(this).parent().parent().find('span').html();
var image = $(this).parent().parent().find('img').prop('src');
if (!(title in jsonObj)) { // if item is not in the object, (title in jsonObj) returns true of false
jsonObj[title] = { // When you have hundreds of items, this approach is way faster then using FOR loop, and if you need to alter the item or get one value, you can just call it by name: jsonObj['ABC'].image will return the path of the image
id: counter,
image: image,
description: 'Example'
}
counter++;
$('#lblCart').html(counter);
} else {
// Do what you want if the item is already in the list
alert('Item already in the list');
console.log(jsonObj[title]);
}
});
DON'T use FOR loops to do what you wan't, it will just slow down your application if the counter gets high.

Categories

Resources