How to copy data in a $scope going inside to a function? - angularjs

$scope.data = {name:"harold", age:"25", address:"california USA",};
function assignData() {
$scope.data = angular.copy($scope.data);
};
how can i copy a data in an object into an object inside a function using angular.copy? or any other idea of doing this beside ng-copy? just ignore the data being used lets just assume that the data in $scope.data is too many thats why im finding ways to lessen the codes. thank you soo much

You can use second parameter in copy method like: angular.copy(source, [destination]);
Or do let me know what is the exact problem?

inner functions has all access to the variables declared in outer function.
like
$scope.data = {name:"harold", age:"25", address:"california USA",};
create one more variable
$scope.data = {name:"harold", age:"25", address:"california USA",};
$scope.dup_data;
function assignData() {
$scope.dup_data = angular.copy($scope.data);
};
Note:
angular.copy performs only a shallow copy when dealing with objects.so $scope.data and $scope.dup_data pointing to the same object.

Related

Trying to compare objects to determine change and update scope based on that

Sorry I'm not sure how to ask this question but the code is pretty straight forward I think. I want to check if the data being returned from the DB has changed and if so update the scope. However when I do the compare it always comes back as different and does the update:
$scope.tickets = Ticket.tickets.query();
updateTickets = $interval(function(){
var deferred = $q.defer();
$scope.curTickets = $scope.tickets;
deferred.resolve(Ticket.tickets.query());
var promise = deferred.promise;
promise.then(function(newTickets){
$scope.newTickets = newTickets;
if($scope.curTickets != $scope.newTickets){
$scope.tickets = $scope.newTickets;
console.log('newtickets!');
} else {
console.log('no newtickets');
}
});
},90000);
As mentioned in https://stackoverflow.com/a/201471/3878940, there is no definite way of comparing the equality of 2 objects in JavaScript. So, you may need to look for an alternative approach to recursively compare the values of the response object by writing a custom method.

How to delete all entries from list?

I am trying to delete all entries from list using angular js. I have two directives I communicate between two directive suing shared service. I am able to add the entry in my list .
I want to delete my list when I click on delete button. I blank my array, but I blank my array on service so it is not reflected on my view. How to blank my list?
Here is my code
https://jsfiddle.net/8fjhLqnw/4/
I delete like that
vm.delete = function() {
vm.data = [];
}
It is not reflecting on my view
For deleting all the entries from a list in Angularjs, you can do something like this
$scope.students.splice( $scope.students.indexOf(student), 1);
Use vm.data.length = 0; to clear the array. If you assign a new array, it will not be bound to the view.
Try this:
vm.delete = function() {
vm.data.length = 0;
}
Because you use f.data = sharedData.data to put the data into the scope of the controller, the will share the same array instance, so modifications on sharedData.data will be seen on f.data, as they are the same.
By sharedData.data = [] you assign a new instance of an array to sharedData.data.
From that point, f.data and sharedData.data are separate instances, any modification done on sharedData.data will leave f.data unaffected.
Another way to workaround this:
.controller('f', function($scope, sharedData) {
this.data = sharedData; // and not this.data = sharedData.data
})
and reference the data as f.data.data. This way you can put in new array instances, because you access it directly through sharedData.

angular - fail to update array from service

I got a service that contain some contacts (name,phone). The controller has array that contain a reference to the array from the service so for every change on the array all gets updated.
Service:
app.service('ContactManagerService', function()
{
this.Contacts=[];
...
this.AddContact=function(Contact){...};
this.RemoveContact=function(Contact){...};
...
});
First question: Is this a good approach? Should every controller/directive need to have a direct reference to the original array from the service? I have read a lot about setting up some events from the service to the controllers when the array has been changed, but it sound stupid because the array on the controller will be change anyway (because its the same array) and the ng-repeat will be updated automatically.
Second problem: The service has a method that replace the array to new one:
this.ReplaceContacts=function(NewContacts)
{
this.Contacts=NewContacts;
});
The ng-repeat does not update because the controller still got the old reference to the old array. So a refresh need to be done.
I tried to replace the code to this one so the same array's reference wont change, but when the the code enter the foreach, this.Contacts array is undefined and the code stops. Why ?!
this.ReplaceContacts=function(NewContacts)
{
this.Contacts.splice(0, this.Contacts.length); //remove all contacts
NewContacts.forEach(function (contact, index)
{
this.Contacts.push(contact);//place the new ones
});
});
The controller code:
app.controller("myCtrl",
function ($scope,ContactManagerService)
{
$scope.Contacts = ContactManagerService.Contacts;
$scope.AddContact= function (Contact1) {
ContactManagerService.AddContact(Contact1);
}
$scope.RemoveContact = function (ContactID) {
ContactManagerService.RemoveContact(ContactID);
}
});
I hope everything is clear,
Thanks.
Because the callback function passed to forEach isn't bound to the service instance. So this, inside the callback, is not the service.
My advice: avoid this like the plague. It's an enormous source of bugs in JavaScript.
Use
var self = this;
at the top of the service, and use self instead of this everywhere.
Or bind the callback function to the service instance:
NewContacts.forEach(function (contact, index) {
...
}, this);
You can simply push elements to Contacts using Array.prototype.push()
The push() method adds one or more elements to the end of an array and returns the new length of the array.
this.ReplaceContacts=function(NewContacts){
this.Contacts.splice(0, this.Contacts.length); //remove all contacts
Array.prototype.push(this.Contacts, NewContacts);
});
As mentioned in previous anser, context of this in forEach loop is not what you think it is.
A simplification would be to use Array.prototype.concat():
var self = this;
self.ReplaceContacts = function (NewContacts) {
self.Contacts.splice(0, this.Contacts.length); //remove all contacts
self.Contacts.concat(NewContacts);
});

adding new property to an object exposed to scope in angularjs

I have an object that is exposed to $scope and has properties attached to it.
I access this object in my controller and call a service which does little something.
What I need to add to it is new property to the object(which is going to be an array attached to the object as a property) so that updated object is returned to the controller and I can access the elements of this array using data-expression tag{{ }}.
I would like to know in detail about making such manipulations the right way and possible ways of doing it.
Just add the array to the object.
$scope.myobj = {};
...
// sometime later
var numbers = [1,2,3];
$scope.myobj.numbers = numbers;
EDIT:
To answer your question about scope in a service. Scope is not accessible in a service. Typically you ask your service for something IE data. But your service can do anything, like add 2 numbers, or in your case create an array of something that you need to attach to your object.
module.service('MyService', function() {
this.add = function(number1, number2) {
return number1 + number2;
}
this.createMyArray = function() {
// pass in whatever you need to this service in order
// to create the array you need.
// example of just returning a hard coded array
return [1,2,3];
}
});
Then you can inject your service into your controller which has the scope you want to modify.
app.controller('MyController', function($scope, MyService) {
$scope.add = function(number1, number2) {
// Lets use our service to add these numbers and
// assign result to scope variable
$scope.answer = MyService.add(number1, number2);
}
$scope.myobj = {};
$scope.makeArray = function() {
// lets use our service again to create an array
// this time lets add it to a scope object that already exists.
$scope.myobj.numbers = MyService.createMyArray();
}
});
A lot of times services are used to grab/update things from a server, so you will see a lot of examples that make http get/post/put/delete calls. Then from your controller(s) you can use those services to grab data. But again you are not limited to that, your service can simple just hold some static data or helper functions too.

Factory without inject the dependency

This is my code that currently works:
angular.module('myApp')
.controller('myCtrl', function (DocumentTypeManagerPdf, DocumentTypeManagerVideo) {
$scope.showPreview = function(document){
var previewModule = eval('DocumentTypeManager' + document.clientModule);
previewModule.show(document);
};
});
but... two things I would avoid:
Eval is evil
I am forced to inject every DocumentTypeManagerXYZ that I'll implement
In there a better solution tu use a Factory dynamically?
I think you should go with a factory pattern.
One service DocumentTypeManagerFactory
With one method like
var myDocumentTypeManager = DocumentTypeManagerFactory.instanciateWithType(document.clientModule);
myDocumentTypeManager.show(document);
Your controller will only inject one service (and the DocumentTypeManagerFactory should inject all)
In your DocumentTypeManagerFactory you should make a switch or if/else to avoid eval.
I think you can use arguments in the function. inJS every function has a variable named arguments which is a array of given parameters.
But I am not sure how your DocumentTypeManagerXYZ objects are structured. So just type debugger; beginning of your controller function and check arguments data by console then you can take a correct action.
the below one is the first one comes to my mind;
var previewModule;
for(var i = 0, len=arguments.lengh; i <len; i++) {
if (arguments[i].constructure.name === 'DocumentTypeManager' + document.clientModule) {
previewModule = arguments[i];
break;
}
}
this will be your basic approach.
as this is an angular application you can user $injector.get("moduleName")
for example;
var previewModule = $injector.get("'DocumentTypeManager' + document.clientModule");
please see $injector

Resources