I am trying to to update the attribute of an onbject in angularjs array of object.
I have the folowing array of object:
$scope.formes= [
{id: 0, geo: 0,cx:0, cy:0, b:0, h:0, r:0, d:0, a:0, ax:0, ay:0, val: 0}
];
The values of each attribute are set to 0 by default until the user type in a new value in a field. Some values are updated after the user add a new objet or hit a button. This app is used to calculate the center of basic geometric shapes and there moments. Just fyi.
This is the function that is running when the user add an object.
$scope.ajoutForme = function(){
$scope.formes.a = parseInt($scope.formes.b) * parseInt($scope.formes.h); /// not working
$scope.formes.push({
id: $scope.nbrForme++ //just adding and new id
});
}
Before I add the objet I want to update some values with calculations. For exemple in this case I what to set the value of a with b*h.
I have try
$scope.formes[nbrForme].h = parseInt($scope.formes[nbrForme].b) * parseInt($scope.formes[nbrForme].h); //This is working but only the first time I press the button??
nbrForme is = to the id of the element I am working on and gets incremented when I add a new object.
Complete Controler
var moment = angular.module('moment',[]);
var nbrForme = 0;
moment.controller('momentCtrl', ['$scope', function($scope) {
$scope.nbrForme = nbrForme;
$scope.formes= [
{id: 0, geo: 0,cx:0, cy:0, b:0, h:0, r:0, d:0, a:0, ax:0, ay:0, val: 0}
];
$scope.ajoutForme = function(){
$scope.formes[nbrForme].a = parseInt($scope.formes[nbrForme].b) * parseInt($scope.formes[nbrForme].h); /// only work once
$scope.formes.push({
id: $scope.nbrForme++
});
}
}
}]);
Your object definition is wrong:
$scope.object = [
{id:0, attr1:2, attr2:4, attr3:0},
{id:1, attr1:2, attr2:4, attr3:0},
{id:2, attr1:2, attr2:4, attr3:0}
];
Note a added , to separate the elements of the array.
Edit:
You wrote that this line doesn't work $scope.formes.a = parseInt($scope.formes.b) * parseInt($scope.formes.h);
This is because $scope.formes is an array, so you must reference to a specific object inside the array that has the a/b/h property. The question is which one?
If it's the first index in the array you'll do
$scope.formes[0].a = parseInt($scope.formes[0].b) * parseInt($scope.formes[0].h);
The last element:
var lastIndex = $scope.formes.length - 1;
if (lastIndex >= 0) {
$scope.formes[lastIndex].a = parseInt($scope.formes[lastIndex].b) * parseInt($scope.formes[lastIndex].h);
}
If $scope.nbrForme is the ID of the element you're currently working on, then you need to decrease its value by 1, because you start with the value of 1, and the first index of an array is 0:
$scope.formes[$scope.nbrForme - 1].a = parseInt($scope.formes[$scope.nbrForme - 1].b) * parseInt($scope.formes[$scope.nbrForme - 1].h);
Related
I am trying to unshift a object to existing array list. But when i do that, i am getting one of the value is empty. what is the correct way to push a new object to existing array in angularjs?
here is my code :
var staticPhase = {
"DisciplineId": "0",
"DisciplineName": "All",
"PhaseId": "0",
"PhaseName": "All" // but this is being converted as ''
}
if($scope.firstLoad) {
var newList = angular.copy( $scope.project.ProjectSummaryFilter ); //taking a copy of existing array
var filterById = $filter('filter')(newList, { ProjectId : $scope.projectId })[0];
staticPhase.ProjectId = filterById.ProjectId;
staticPhase.ProjectName = filterById.ProjectName;
staticPhase.SubProjectId = filterById.SubProjectId;
staticPhase.SubProjectName = filterById.SubProjectName;
}
var phaseList = $scope.project.ProjectSummaryFilter;
phaseList.unshift(staticPhase) //adding static phase to array;
The standard JavaScript push() method should work:
var phaseList = $scope.project.ProjectSummaryFilter;
phaseList.push(staticPhase);
Before I start, I will link my codepen so you can have a look before reading this :)
I have made a very simple app to demonstrate my issue.
basically when I have multiple services sharing an array, it appears that angularjs treats the array as a primitive object which is odd.
I have to link code, so this is my controller and 2 services at the start:
angular.module('bindingApp', [])
.controller('MainController', ['MainService', 'SelectionsService', function (service, selections) {
// Map the controller to a variable
var self = this;
// Attach the model to our scope
self.models = service.models;
// Create a function that handles the changes the service in some way
self.updateSelectedItems = function () {
// Get our first item
var models = selections.selected;
// Loop through our selected items
for(var i = 0; i < models.length; i++) {
// Get our current model
var model = models[i];
// Change the properties
model.status = 'Cancelled';
model.colour = 'gray';
}
};
// Reset everything
self.reset = function () {
selections.reset();
service.reset();
console.log('models in the controller', self.models);
}
// Map our function to our service function
self.selectItem = selections.select;
// Initialize our service
service.init();
}])
.service('MainService', function () {
// Create our service
var service = {
// Create the default model (empty array)
models: [],
// Populates our model
init: function () {
// Loop from 1 to 10
for(var i = 0; i < 10; i++){
// Create some object
var model = {
status: 'Live',
colour: 'green',
selected: false
};
// Push our model to our array
service.models.push(model);
}
console.log('models in the service', service.models);
},
// Resets everything
reset: function () {
// Reset our array
service.models = [];
// Initialize
service.init();
}
};
// Return our service
return service;
})
.service('SelectionsService', function () {
// Create our service
var service = {
// Create a reference to our selected objects
selected: [],
// Our select function
select: function (e, item) {
// Create a reference to our selected items
var selected = service.selected;
// Update the selected status
item.selected = true;
// Push our item to our selected items
selected.push(item);
// Stop propagation
e.stopPropagation();
e.preventDefault();
},
// Resets our selected items
reset: function () {
service.selected = [];
}
};
// Return our service
return service;
});
I have created 2 more Codepens to try to fix the issue. The first one maps the items to an object encapsulating an array in the MainController. The second one does the same, but also the MainService has an object encapsulating the array.
Does anyone know what I can do to get this simple pen working?
OK. This doesn't have much to do with Angular. Just plain JavaScript.
Here's what happens:
The service initializes its models array. service.models is a variable that contains a reference to that array. You thus have
service.models ----> [firstArray]
Then the controller does self.models = service.models;. So it creates another reference pointing to the same array, referenced by service.models:
service.models ----> [firstArray]
^
controller.models ----|
Then you click the reset button, which calls service.reset(), which does service.models = [];. So it creates a new array and assigns it to its models variable. You thus end up with
service.models ----> []
controller.models --> [firstArray]
Note that you never make controller.models point to the new array in the service. So it still points to the first array, and the view still displays the elements of that first array.
So, either you make sure to reinitialize the controller's models variable after calling reset():
controller.models = service.models;
Or you make sure to simply remove everything from the original, first array in reset():
service.models.splice(0, service.models.length)
It looks like that you must not reset the models array by referencing a new empty array but removing all items from it.
Instead
// Reset our array
service.models = [];
use
// Reset our array
service.models.length = 0;
I'm trying to figure out how to watch an array and update an object, like this.
var vm = this; //controller
vm.order = {
totalValue: 25,
products: [{id:0, val: 10, qtd: 1}, {id:1, val: 15, qtd: 1}]
};
If I push a new product into this order object, how do I update the totalValue just watching the collection ? (totalValue = All Val * All Qtd)
It is necessary because the "qtd" field is bind to an input field, so I can change the value of all "products" at any time.
UPDATE
$scope.$watchCollection(
function() { return self.order.products; },
function(products) {
self.order.totalValue = products.reduce(function (p, n) {
console.log(n.qtd);
console.log(n.val);
return p + n.qtd * n.val;
}, 0);
});
The code worked, but only when I push a new "product" into order.
I have to watch every order.products.product.qtd and change the order.totalValue every time the user change the qtd of a product
Try this way:
$scope.$watch('order.products', function (products) {
scope.order.totalValue = products.reduce(function (p, n) {
return p + n.qtd * n.val;
}, 0);
}, true);
This will deep watch array to detect qtd and val changes inside array items.
I have an extjs store associated with grid class. when I select a class, it gives ClassID of the record.
var ClassData = record.get('ClassID');
console.log(ClassData);
Based on this ClassID I am loading store of next grid:
var Grid = this.getSemGrid();
var Store = Grid.getStore(); // your grid's store
//load store with records having selected class ID
var g = Store.load( {params : {ClassID: ClassData }});
Till here everything is fine.
Once the store is loaded, I am getting all loaded records (Error Area)
var selected = g.getRange(); // getRange = select all records
Then pushing all the values of one field of all records in an array
var Excerpt = []; // start with empty array
Ext.each(selected, function(item) {
// add the fields that you want to include
var Obj = {
third_field: item.get('ExamName')
};
Excerpt.push(Obj); // push this to the array
}, this);
console.log(Excerpt);
Excerpt gives array of previously selected record not the current record.
I have also tried
Store.loadData([],false);
to clear all the loaded data of store before loading it again.
Got this working
var g = Store.load({
params : {ClassID: ClassData },
callback : function(records, operation, success){
var Excerpt = []; // start with empty array
Ext.each(records, function(item) {
// add the fields that you want to include
var Obj = {
third_field: item.get('ExamName')
};
Excerpt.push(Obj); // push this to the array
}, this);
}
});
I am having an issue with losing data within an array when i try to assign it to a new array.
My object im using is as follows:
$scope.shops = [
{
name: "Kroger",
items: [ { itemName: "Chips"} ]
}
];
This is the code for the functions im using, it may be a callback issue? or something? Im losing the items info for the shop.
$scope.addItem = function(newItem, newShop){
var x = findShop(newShop);
x.items.push(newItem);
$scope.shops.push(x);
};
findShop = function(shopTag){
var old = angular.copy($scope.shops);
var tar = {
name: shopTag,
items: []
};
$scope.shops = [];
angular.forEach(old, function(shop, key){
if(shop.name === shopTag) {
tar.items = angular.copy(shop.items);
}
else {
$scope.shops.push(shop);
}
});
return tar;
};
the goal is to have the findShop function return a shop with the correct name, with empty items if there wasnt a shop previously, or with items full of the items if the shop was already created. then the addItem will push the item into the shop.items array and push the shop into the $scope
Any help is greatly appreciated!!!
You are right , it is this line which is causing the problem ,
tar.items = shop.items;
Try using it like this ,
tar.items = angular.copy(shop.items);
var old = $scope.shops; // old and $scope.shops point to the same place
..........
$scope.shops = []; // you assigned a new array that overrides the data
............
angular.forEach(old, function(shop, key){ // for each on an empty array????
If you dont want to point to the same reference use:
var copiedObject = angular.copy(objToCopy);
I guess the array is getting empty even before for loop.
Var old is reference to shops array, which you are making empty before foreach.. effectively making old empty...