How to use controller function in factory? - angularjs

myapp.controller("controller1",function(factory_name){
function abc(){
//code of function
})
myapp.factor(""factory_name",function(){
return {
'name': function(){
i want to use function abc here
}
}
})
I want to use controller function into the factory.As I cant use $scope I am not able to use. I have searched many pages but failed with all solution I have found.

I'm not sure how you want to output to look like but to get you started you can get the keys and values of the dict as separate lists. Use dict.keys() and dict.values().

Related

TypeError: push is not a function

Here is my code for factories.html
af.factory("PurchaseFactory",function(){
var productlist={products:[]};
return{
getpurchaseCart:function(){
return productlist;
},
addPurchaseCart:function(products){
productlist.products.push(products);
}
}
})
For Services.html
as.service("PurchaseService",function(PurchaseFactory){
this.getAllPurchase=function(){
return PurchaseFactory.getpurchaseCart();
}
this.addPurchase=function(products)
{
PurchaseFactory.addPurchaseCart(products);
}
})
For Controller.html
ac.controller("PurchaseController",function($scope,PurchaseService){
$scope.savepurchase=function(products){
if($scope.products._id==undefined){
$scope.products=angular.extend($scope.products,$scope.sizes)
PurchaseService.addPurchase($scope.products);
}
}
}
Here i have an another function in the same controller, as
$scope.saveorder=function(cartorder){
$scope.Mainpurchaselist=angular.extend($scope.cartorder,$scope.getpurchaseList)
CartService.addPurchaseCart($scope.Mainpurchaselist);
$scope.getpurchaseList.products={}
$scope.cartorder={}
$scope.products={}
$rootScope.isLogin=false;
CartService.deletecartyPurchase(idx);
Notification.success({message: 'your Cart Saving Successfully', delay: 1000});
}
In my HTML file, i have a button with function as savepurchase(products).
For first time its saving data but from second time its showing me error as TypeError:productlist.products.push is not a function. If I refresh the page its again saving the data, but continuously its not working.Let me know where the code goes wrong.
Here $scope.getpurchaselist.products={} is used to make a data null for every new purchase. If I remove the $scope.getpurchaselist.products={}, its working fine with no error but the problem is that the list is not getting null.
SO finally i have two ways
1. either to make it null by writing $scope.getpurchaselist.products={} but error as productlist.products.push is not a function let me know to overcome that error
2. Or to remove that line and let me know, how to make it null
I think, $scope.getpurchaseList.products={} is effecting you. As it passing an empty object instead of array as soon as the controller load. So, try removing it.
The condition if($scope.products._id==undefined) is breaking you. please check the logic you wrote. keep in mind $scope.products and products both are different variable in savepurchase function.
After extending $scope.products first time, condition return false.
change the $scope.products into just products. because u pass the products as paramater to the savepurchase() function. so no need to define as scope.products in ur controller

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);
});

Angular - Parameter for SQL

I have followed the basics from w3schools: http://www.w3schools.com/angular/angular_sql.asp
I now have controller with this line:
$http.get("getjson.php?q=2")
(let's say it's making a json based on select * from someplace where country=2)
How can I get this dynamic so that I can use the same angular module for all the x countries I want to list? I guess copying the module x times and hard code the country number isn't the best option...
You can crate service that implements your get request
angular.service('someService', function() {
this.getJson = function(qParam){
$http.getjson('getjson.php',{q:qParam});
}
})
you can use it in controller like this
angular.controller('mainController',function(someService){
someService.getjson(2);
})

Is it good practice to combine CREATE and EDIT controllers in AngularJS?

There are many duplicated code among CREATE and EDIT controllers.
These controllers could be combined into one for minimizing repetitive code.
The problem: I need to distinguish which method to use on form submitting - create() or edit() for example.
The solution: I could add $scope.mode for example and set $scope.mode='edit' if user clicked 'EDIT' button or set $scope.mode='add' if user clicked 'ADD' button.
I could use services for minimizing repetitive code, but there still will be duplicated code. For example in both controllers I have cancel() method which clears the form and hide it. I could store clearForm() and hideForm() in the service, but this code will be duplicated in both controllers:
$scope.cancel = function() {
Service.clearForm();
Service.hideForm();
};
Questions:
Is it good practice to combine CREATE and EDIT controllers in AngularJS?
Is there any good practices to minimize repetitive code?
Yes. Use 1 controller.
Here is the reason why use 1 controller
The job of the controller is to support the View. Your create view and the edit view is exactly same - just that one has data pre-populated (edit) and another does not (create).
Moreover the "purpose" of this View is to have the user change or enter new values in the form. Your only difference should be something like reset(). But even there you could start with an empty model object e.g. $scope.entity = {} in case of CREATE and you will start with $scope.entity = $http.get().
Repetition Problem with 2 Controllers
With 2 different controllers and services you are going to incur at least the following duplication:
$scope.cancel = function() {
Service.cancel();
};
$scope.validate = function() {
ValidtionSvc.validate();
}
.
.
.//other stuff similar
but the problem is why even this duplication like you stated.
(UDATED here onwards since above was the answer to the 1st question)
How to use 1 controller with repetition ?
Is there any good practices to minimize repetitive code?
Question redefined: Is there a good practice of eliminating repetitive code in CREATE and EDIT forms ?
No formal 'best practice' exist to my knowledge to avoid repetitive code in this specific situation. However I am advising against mode=edit/create. The reason being for controllers in this situation there should be almost no difference since their job is to purely to fetch/update the model as the user interacts.
Here are the difference you will encounter in this situation and how you can avoid if/then/else with mode=create/edit:
1) Populating the form with existing values vs. empty form for Create.
To fetch a existing entities you need some key/query data. If such key data is present you could do
var masterEntity = {};
if(keyData) {
masterEntity = MyEntityResourceFactory.getEntity(keyData);
}
$scope.entity = masterEntity;//for Create this would be {}
2) reset() form
should be simply
$scope.reset = function() {
$scope.entity = masterEntity;
}
3) Update/Create
$http.post()//should not be different in today's world since we are treating PUT as POST
4) Validation - this is a perfect reuse - there should be no differences.
5) Initial / Default Values
You can use masterEntity = Defaults instead of {}.
Is it good practice to combine CREATE and EDIT controllers in
AngularJS?
In my experience, yes it is a good idea for 99.9% of the time. I typically inject a formType variable into my controller via the $routeProvider resolve feature. So I would have something like the following:
$routeProvider
.when('/item/create', {
templateUrl: '/app/item/itemForm.html',
controller: 'itemFormController',
resolve: {
item: ['$route', 'itemRepository', function ($route, itemRepository) {
return itemRepository.getNew();
}],
formType: function () { return Enums.FormType.CREATE; }
},
})
.when('/item/edit/:itemId', {
templateUrl: '/app/item/itemForm.html',
controller: 'itemFormController',
resolve: {
item: ['$route', 'itemRepository', function ($route, itemRepository) {
return itemRepository.get($route.current.params.itemId);
}],
formType: function () { return Enums.FormType.EDIT; },
},
});
That way you get your entity and type of form action injected into the controller. I also share the same templates, so saving a form I can either rely on my repository/service to determine what REST endpoint to call, or I can do a simple check inside the controller depending on what formType was injected.
Is there any good practices to minimize repetitive code?
Some of the things I'm using to keep things DRY:
If you keep a common convention on your server API you can go a very long way with a base factory/repository/class (whatever you want to call it) for data access. For instance:
GET -> /{resource}?listQueryString // Return resource list
GET -> /{resource}/{id} // Return single resource
GET -> /{resource}/{id}/{resource}view // Return display representation of resource
PUT -> /{resource}/{id} // Update existing resource
POST -> /{resource}/ // Create new resource
etc.
We then use a AngularJs factory that returns a base repository class, lets call it abstractRepository. Then for each resource I create a concrete repository for that specific resource that prototypically inherits from abstractRepository, so I inherit all the shared/base features from abstractRepository and define any resource specific features to the concrete repository. This way the vast majority of data access code can be defined in the abstractRepository. Here's an example using Restangular:
abstractRepository
app.factory('abstractRepository', [function () {
function abstractRepository(restangular, route) {
this.restangular = restangular;
this.route = route;
}
abstractRepository.prototype = {
getList: function (params) {
return this.restangular.all(this.route).getList(params);
},
get: function (id) {
return this.restangular.one(this.route, id).get();
},
getView: function (id) {
return this.restangular.one(this.route, id).one(this.route + 'view').get();
},
update: function (updatedResource) {
return updatedResource.put();
},
create: function (newResource) {
return this.restangular.all(this.route).post(newResource);
}
// etc.
};
abstractRepository.extend = function (repository) {
repository.prototype = Object.create(abstractRepository.prototype);
repository.prototype.constructor = repository;
};
return abstractRepository;
}]);
Concrete repository, let's use customer as an example:
app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) {
function customerRepository() {
abstractRepository.call(this, restangular, 'customers');
}
abstractRepository.extend(customerRepository);
return new customerRepository();
}]);
What you'll find if you use this base repository pattern is that most of your CRUD controllers will also share a lot of common code, so I typically create a base CRUD controller that my controllers inherit from. Some people dont like the idea of a base controller, but in our case it has served as well.
The answer to your first question probably depends on the specific circumstances.
If the two controllers share a substantial amount of operations, and the behavior of just one or two functions needs to be altered - why not! Maybe not the most elegant solution but hey, whatever works.
If the behavior of many or all controller operations is going to depend on '$scope.mode'...I'd say be careful. That seems like a dangerous path.
Angular services have always served me well when it comes to minimizing code replication between controllers. If there is a "good practice to minimizing repetitive code," I would say it would be services. They are global to your app and can be injected into multiple controllers without issue.
I hope that helps!

looping + rendering in backbone

render:function(output){
_.each(output, function(i){
p=i.name;
});
$(this.el).append(p);
}
here i am getting output in the form of json....i have 100 names...and i want to append it one after the another...in this case i get one name....
if i put like this...
render:function(output){
_.each(output, function(i){
p=i.name;
$(this.el).append(p);
});
}
inside the each loop nothing come...
do i need to make 100 variable like p here or is there any other way...
You need to provide the context, i.e. this. "this" is the reference to the current object you are working in. However, when you are calling a different function from within your current object, you are loosing the reference to your current object. Basically, this then refers to the the function. But you can easily fix this.
Either by adding this as an argument to the function call:
render:function(output){
_.each(output, function(i){
p=i.name;
$(this.el).append(p);
},this);
}
Or by providing this via a helper variable
render:function(output){
var self=this;
_.each(output, function(i){
p=i.name;
$(self.el).append(p);
});
}
I would go for option 1

Resources