AngularJs/Nodejs updating view and animating it - angularjs

I'm writing
angularjs/nodejs
I useed $http service to load my data from database and ngRepeat directive to display it into the view. What I can't do is when I add new item to database, update my view with just one item, and do it with animation.I know need to use ngAniamte and set class on ng enter but how do i push single item into data array without reloading the whole view?
Data Load and Insert
vm.loadData = function () {
$http.get('/data')
.success(function (data) {
vm.data = data;
})
.error(function (data) {
console.log('Error: ' + data);
});
}
http.post('/data', data).success(function (data) {
})

I assume vm.data is an array? You should not reassign the complete array but rather add new items to it, delete old items from it and/or update items in it. You can add new items with vm.data.push() and add/delete items with vm.data.splice(). To do this, you need to compare vm.data with data to determine which items need to be added/deleted/modified.

Related

Trying to replace each record having a button in AngularJS with only one button for records that are selected

So I'm working on an app that has a table listing records that have been added to a database. As it currently stands, line in the table has a record entry with one edit and one delete button for each record. So as you scroll, lots of lines, lots of delete and edit and delete buttons. I'd like to keep the table as is and get rid of the all the buttons, instead having only 2 total buttons outside of the table at the bottom of the page where you would highlight the table entry in some way and the buttons would correspond to the actions. This is all done in the controller, but I'm reworking someone else's stuff, so it's a bit tricky. Any suggestions? My code in the controller looks something like this:
$scope.edit = function(id) {
myApp.edit($scope.svc, id)
.then(function(data) {
$scope.record = data;
}, function() {
console.log('error in removing the record : ' + id);
});
};
$scope.add = function() {
console.log($scope.record);
myApp.add($scope.svc, $scope.record)
.then(function(data) {
refresh();
}, function() {
console.log('error in adding the record : ');
});
};
$scope.update = function() {
console.log($scope.record);
myApp.update($scope.svc, $scope.record)
.then(function(data) {
refresh();
}, function() {
console.log('error in adding the record : ');
});
};
}
You didn't really highlight what error / issue you were having but I'll show you how I'd implement this:
Create one global record variable in your controller.
Each time a record is clicked, set the global record variable to be the clicked record. Then on your two buttons you simply invoke the edit / delete functions which work off of the global record variable.
On your table row repeater:
<tr ... ng-repeat="record of records" ng-click="setActiveRecord(record)">
In your controller:
$scope.activeRecord = {}
$scope.setActiveRecord = (record) => { $scope.activeRecord = record }
$scope.add = () => { ... }
$scope.edit = (record) => { /* your edit logic using $scope.activeRecord */ }
$scope.delete = (record) => { /* your delete logic using $scope.activeRecord */ }
As some basic UX you'd want to show which record is currently active, so perhaps by using ng-class:
<tr ... ng-repeat="record of records" ng-class="{ 'your-css-classname' : record.id === activeRecord.id }">

AngualrJS $watchCollection triggers even when arrays are equal

I am trying to implement an auto sync between my angularJS model and my database.
I am running the following function every ten seconds to get data from from database in which I update my variable products_copy:
$interval(function(){$scope.getProductsSync();},10000);
$scope.getProductsSync = function() {
var q = $q.defer();
$http({
url: '/getData/getProducts.php',
method: "POST",
data: {"user_id":$scope.user_id}
})
.then(function(response) {
if(response.data.valid)
{
console.log('Products sync complete: '+new Date().toLocaleTimeString());
console.log(response.data.products);
$scope.products_copy = response.data.products;
q.resolve('Products sync complete');
}
else if(response.data.msg=="offline")
{
console.log('Products sync offline');
q.resolve('Products sync offline');
}
else
{
console.log('Products sync error');
console.log(response);
q.reject('Products sync error');
}
},
function(response) {
console.log('Products sync error');
console.log(response);
q.reject('Products sync error');
});
return q.promise;
}
Whenever there is a change in this data I want to update my actual product list in my model which is defined by the array products. Hence, I am using the service $watchCollection to detect a change in the data and update my model when there is a change. However this change is triggered in each call even though the data from the database is unchanged.
$scope.$watchCollection('products_copy', function (newValue, oldValue, scope) {
if(newValue!==oldValue)
{
console.log('Watch on products was called');
console.log('Old value: '+oldValue);
console.log('New value: '+newValue);
$scope.products = newValue;
}
});
I want the event to be triggered only when there is change in the array such as:
add item
remove item
edit any property of any item
EDIT 1:
I changed it to angular.equals but even that resulted in trigger in every call. However, when I examined each item in the console I realised angular was adding a property $$hashkey which was varying between the items. Any idea how to solve this?
It is how it should be, because on each response you assign a new reference to $scope.products_copy and no matter that there're no changes of the data inside it, when you do newValue!==oldValue you compare the refereces, they are always different
if you try
var a = [];
var b = [];
console.log(a===b); // false
// the both are empty and seems to be equal
you have to check the data inside old and new data. Try with angular.equals
You can try for angular.equal(object1, object2)
$scope.$watchCollection('products_copy', function (newValue, oldValue, scope) {
if(!angular.equals(newValue, oldValue))
{
console.log('Watch on products was called');
console.log('Old value: '+oldValue);
console.log('New value: '+newValue);
$scope.products = newValue;
}
});
The problem was that angular was inserting a $$hashKey attribute which resulted in a difference even in same objects. Removing this field did the trick for me.

Where should I view Console.log result in AngularJS?

I am having the following code:
var vocabularies = new MyDataService.myService();
vocabularies.success(function (data) {
console.log(data);
}).error(function (data) {
console.log(data);
});
Where can I view the value of data instead of debugging the above code?
If you want to view the data present in the console then you may use keyboard shortcut Ctrl + Shift + J to bring focus on the console.
If you want to see your data during execution you may use alert instead of console.log.
If you want to bind your data to the HTML you need to use
$scope.variable=data;
you can then get your value by using expression tag in HTML.
{{variable}}
You can assign your data to a $scope variable. And on template you can view it. Find below code:
var vocabularies = new MyDataService.myService();
vocabularies.success(function (data) {
console.log(data);
$scope.viewData = data;
}).error(function (data) {
console.log(data);
$scope.viewData = data;
});
And then on the template:
{{viewData | json}}
The above will print it in json format if its json else normal text

when i click on update button i got data to be updated but it gets cleared when i move to update page in angularjs

$scope.fetchDataForEditInvoice = function (row)
{
var index = $scope.gridOptions.data.indexOf(row.entity);
var InvoiceId = $scope.gridOptions.data[index].InvoiceId;
var status = angularService.FetchDataForEditInvoice(InvoiceId);
status.then(function (invoiceData) {
console.log(invoiceData);
window.location.href = "/Invoice/AddInvoice";
$scope.InvoiceDetails = invoiceData.data.InvoiceDetails;
},
function () {
alert('Error in fetching record.');
})
}
on click of update button i call following function and i got data but how i can assign it to controls on update page
save invoiceData.data.InvoiceDetails in a $rootScope variable. So it will available in all controllers.
$rootScope.InvoiceDetails=invoiceData.data.InvoiceDetails;
inject $rootScope to your controller before using it.
Use routers traversing next page.Refer Single Page Apps with AngularJS Routing]1

Cannot set option value in select programmatically using AngularJs

The select:
select(ng-model="elId", ng-change="load(elId)", ng-options="e._id as e.name for e in options")
option(value="") - select a mashup -
Controller:
The following works, the select gets populated. I am using broadcasts because it comes from a socket.. don't mind that.
//receive list
$scope.$on('list:refresh', function(ev, data) {
$scope.options = data
})
The following only works if I did not manually select any option before. data.id is a valid entry in the list.
//refresh list of mashups when a new one has been created
$scope.$on('list:select', function (ev, data) {
$scope.elId = data.id
})
If I manually select an option, and then the list:select fires, the $scope.elId is udated but the <select> does not highlight the option.
What is going on?
Solved:
The select:
select(ng-model="data.elId", ng-change="load()", ng-options="e._id as e.name for e in options")
option(value="") - select a mashup -
Controller:
//receive list
$scope.$on('list:refresh', function(ev, data) {
$scope.options = data
})
$scope.load() {
var elId = $scope.data.elId
....
}
//refresh list of mashups when a new one has been created
$scope.$on('list:select', function (ev, data) {
$scope.data.elId = data.id
})
I guess the problem was that I tried to change the selected value from a child controller.. now I am using a service Data that I load into the controllers $scope.data = Data.. meh?

Resources