How can I define a function in angular service, and then use the function definition in a function in another service.
I implement as below but it doesn't work. I don't want to return a ParentService instance, just a defintion of its constructor to be used as parent class of PersonService.
Thanks for your help.
var personModule = angular.module('personModule',['coreModule']).service('personService', function($q, jAjax){
function PersonService($q, jAjax) {
var self = this;
ParentService.call(self, $q, jAjax);
this.name = "person";
};
inherit(ParentService, PersonService);
PersonService.prototype.loadPersonList = function() {
var self = this;
var deferred = self.$q.defer();
ParentService.prototype.loadList.call(self, "meta", function(data){
self.items = data;
deferred.resolve(data);
});
return deferred.promise;
};
return new PersonService($q);
});
var coreModule = angular.module('coreModule',[]).service('commonService', function(jAjax){
var ParentService = function(jAjax) {
};
ParentService.prototype.loadList = function(docType, fn) {
var self = this;
var url = self.name + "/get";
self.jAjax.get(url).success(function(data) {
if (fn !== undefined) {
fn.call(this, data);
}
});
};
return ParentService;
});
Thanks for your time. I found the solution for this. In parentService, I return an object that contains the function definition
return {ParentService:ParentService};
, then in other module I get it as an property
inherit(commonService.ParentService, PersonService);
The fixed code is below
var personModule = angular.module('personModule',['coreModule']).service('personService', function($q, jAjax, commonService){
function PersonService($q, jAjax, commonService) {
var self = this;
ParentService.call(self, $q, jAjax);
this.name = "person";
};
inherit(commonService.ParentService, PersonService);
PersonService.prototype.loadPersonList = function() {
var self = this;
var deferred = self.$q.defer();
commonService.ParentService.prototype.loadList.call(self, "meta", function(data){
self.items = data;
deferred.resolve(data);
});
return deferred.promise;
};
return new PersonService($q, jAjax, commonService);
});
//Calling module
var coreModule = angular.module('coreModule',[]).service('commonService',function(jAjax){
var ParentService = function(jAjax) {
};
ParentService.prototype.loadList = function(docType, fn) {
var self = this;
var url = self.name + "/get";
self.jAjax.get(url).success(function(data) {
if (fn !== undefined) {
fn.call(this, data);
}
});
};
return {ParentService:ParentService};
});
Related
This question already has answers here:
Share data between AngularJS controllers
(11 answers)
Closed 5 years ago.
I have to controllers the first controller is "cockpitController"and the other one "idCardSupplierWarnController" .In the first controller i set my objects and i checked if the set work and it work i can see all my objects but when i want to get my objects in the other controller then all my objects are null .
PS: I checked this solution it's working for the case that the controller is in the same Window of the navigator but in my case it's in new window using $window.open(url).
Le service idCardSupplierWarnService :
var app = angular.module('idCardSupplierWarn');
app.service('idCardSupplierWarnService', function () {
this.idRefNum = "";
this.idSupNum = "";
this.codeSuppNum = "";
this.setParam = function (paramSet) {
console.log(paramSet);
this.idRefNum = paramSet.designRefPart;
this.idSupNum = paramSet.idSuppNumber;
this.codeSuppNum = paramSet.codeSupp;
};
this.getParamSupNum = function () {
return this.idSupNum;
};
this.getParamCodeSupNum = function () {
return this.codeSuppNum;
};
this.getParamIdRefNum = function () {
return this.idRefNum;
};
});
Le controller cockpitController :
(function () {
angular
.module("cockpit", ['mm.foundation', 'security', 'message', "isteven-multi-select"])
.controller('cockpitController', ['$scope', '$translate', 'serviceCockpit','idCardSupplierWarnService', '$window', function ($scope, $translate, serviceCockpit,idCardSupplierWarnService,$window) {
var urlSuppliersWarning = 'rest/suppliers/warnings';
var urlSuppliersWarningByRefForDetails = 'rest/suppliers/warnings/supplier/ref/search';
var self = this;
serviceCockpit.loadData([urlSuppliersWarning]).then(function (results) {
self.suppliersWarning = results[0].data;
});
this.change = function () {
if (this.openWindow) {
this.openWindow = false;
}
else {
this.openWindow = true;
}
};
$scope.openNewWindowRef = function (url, params) {
console.log(params);
idCardSupplierWarnService.setParam(params);
console.log(idCardSupplierWarnService.getParams());
$window.open(url, '_blank', 'left=0, top=0, width=1100,height=600,scrollbars=yes, resizable=1');
};
$scope.openNewWindowSupp = function (url, params) {
idCardSupplierWarnService.setParam(params);
console.log(idCardSupplierWarnService);
$window.open(url, '_blank', 'left=0, top=0, width=1100,height=600,scrollbars=yes, resizable=1');
};
this.process = function (items) {
if (items.origin == 'reference' || items.origin == 'suppliers' || items.origin == 'supplierAccounts' || items.origin == 'supplierAddressCodes' || items.origin == 'reset') {
serviceCockpit.loadData([urlSuppliersWarningByRefForDetails], items).then(function (results) {
self.suppliersWarningDetails = results[0].data;
});
}
serviceCockpit.loadData([urlSuppliersWarning], items).then(function (results) {
self.suppliersWarning = results[0].data;
});
}
}]);
})();
Le controller **idCardSupplierWarnController :**
(function () {
angular
.module("idCardSupplierWarn", ['mm.foundation', 'security', 'message', "isteven-multi-select"])
.controller('idCardSupplierWarnController', ['$translate', '$scope', 'serviceCockpit','idCardSupplierWarnService', function ($translate, $scope, serviceCockpit,idCardSupplierWarnService) {
var urlSupplierWarningByRefDetail = 'rest/suppliers/warnings/supplier/details';
var self = this;
var params = {} ;
params.idRefNum = idCardSupplierWarnService.getParamIdRefNum();
params.idSupNum = idCardSupplierWarnService.getParamSupNum();
params.codeSuppNum = idCardSupplierWarnService.getParamCodeSupNum();
console.log(params.codeSuppNum);
serviceCockpit.loadData([urlSupplierWarningByRefDetail], params).then(function (results) {
self.suppliersWarningsList = results[0].data;
});
}]);
})();
"This" in the functions of your service refers to the individual functions in your service, not the service itself.
Modify your service to look like this:
app.service('idCardSupplierWarnService', function () {
var service = this
service.idRefNum = "";
service.idSupNum = "";
service.codeSuppNum = "";
service.setParam = function (paramSet) {
console.log(paramSet);
service.idRefNum = paramSet.designRefPart;
service.idSupNum = paramSet.idSuppNumber;
service.codeSuppNum = paramSet.codeSupp;
};
service.getParamSupNum = function () {
return service.idSupNum;
};
service.getParamCodeSupNum = function () {
return service.codeSuppNum;
};
service.getParamIdRefNum = function () {
service this.idRefNum;
};
return service
});
You need to inject idCardSupplierWarn module into cockpit module, to access the service.
angular.module("cockpit", ['mm.foundation', 'security', 'message', `isteven-multi-select`, `idCardSupplierWarn`])
I am trying to work with an object array which I am sharing among two controllers one of which is dealing with modal window.
Here is the js code.
angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache', 'ui.bootstrap'])
.service('Faq', function ($http) {
this.faqList = [];
this.faqList = $http.get('/Json/faq.json');
this.getFaqs = function ()
{
return this.faqList;
}
this.addfaq = function (obj) {
this.faqList.push(obj);
};
})
.controller('AppCtrl', function ($scope,$modal,Faq) {
$scope.faqData = [];
Faq.getFaqs().then(function (msg) {
$scope.faqData = msg.data;
});
}
$scope.show = function () {
$modal.open({
templateUrl: "faqAddUpdate.html",
controller: "faqctrl"
});
};
})
.controller('faqctrl', function ($scope, $modalInstance, Faq) {
$scope.question = '';
$scope.id = '';
$scope.answer = '';
$scope.editFaq = function (id) {
$scope.divFaq = true;
$scope.faqs = [];
Faq.getData().then(function (msg) {
$scope.faqs = msg.data;
var l = $scope.faqs.length;
for (var i = 0; i < l; i++) {
if ($scope.faqs[i].id == id) {
$scope.question = $scope.faqs[i].question;
$scope.id = $scope.faqs[i].id;
$scope.answer = $scope.faqs[i].answer;
}
}
});
};
$scope.AddUpdateFAQ = function () {
var faq = {
id: $scope.id,
question: $scope.question,
answer: $scope.answer
};
Faq.addfaq(faq);
console.log(faq);
$modalInstance.close();
};
$scope.Cancel = function () {
$modalInstance.dismiss();
};
});
but when I am submitting the data through the modal it says this.faqList.push is not a function.
It is because your faqList variable is not an array.
You overide the first definition:
this.faqList = [];
With this:
this.faqList = $http.get('/Json/faq.json');
But $http.get returns a promise (see doc), not an array.
You should do something like this:
this.faqList = [];
$http.get('/Json/faq.json').then(function(result) {
// process your results here
this.faqList = result.data;
});
Not tried, but this is within the function scope, so create a _this var first might help:
this.faqList = [];
this.faqList = $http.get('/Json/faq.json');
var _this = this;
this.getFaqs = function ()
{
return _this.faqList;
}
this.addfaq = function (obj) {
_this.faqList.push(obj);
};
I would like to create a jQuery type chaining on an element created using javascript's document.createElement(). The following code is generating an error "Cannot call method 'appendChild' of undefined" whenever I try to run my "append" method on a parent object that was defined by my function. Any help or suggestions are appreciated.
this.el = (function () {
function _el() {
var self = this,
ele;
this.add = function (tag) {
ele = document.createElement(tag);
return this;
},
this.byId = function (id) {
ele = document.getElementById(id);
return this;
},
this.byClass = function (cl) {
ele = document.getElementsByClassName(cl);
return this;
},
this.id = function (name) {
ele.id = name;
return this;
},
this.cl = function (name) {
ele.className = name;
return this;
},
this.css = function (style) {
_this.setCSS(ele, style);
return this;
},
this.html = function (str) {
ele.innerHTML = str;
return this;
},
this.append = function (parent) {
if (parent.nodeType === 1) {
parent.appendChild(ele);
}
console.log(ele);
console.log(ele.nodeType);
return this;
};
return this;
}
return new _el();
}());
This is how I use the function in my code. The first use works while the second one does not. It has something to do with the type of object being returned by my function but I am not sure how to correct.
var dialog = hlp.el.add("div").cl("alphaDialog").append(document.body);
var top = hlp.el.add("div").append(dialog);
this.append function returns this object which holds _ele js object. We have to return our HTML element ele. In this.append we return ele;
this.el = (function () {
function _el() {
var self = this,
ele;
this.add = function (tag) {
ele = document.createElement(tag);
return this;
},
this.byId = function (id) {
ele = document.getElementById(id);
return this;
},
this.byClass = function (cl) {
ele = document.getElementsByClassName(cl);
return this;
},
this.id = function (name) {
ele.id = name;
return this;
},
this.cl = function (name) {
ele.className = name;
return this;
},
this.css = function (style) {
_this.setCSS(ele, style);
return this;
},
this.html = function (str) {
ele.innerHTML = str;
return this;
},
this.append = function (parent) {
if (parent.nodeType === 1) {
parent.appendChild(ele);
}
console.log(ele);
console.log(ele.nodeType);
//return this; // this holds javascript object, not element
return ele; // return our ele variable which holds the element
// this.append() is the end of the chain
};
return this;
}
return new _el();
}());
I have a view model called ProductsViewModel
This contains an observableArray of ProductViewModel
A ProductViewModel also contains an observableArray - of ProductPriceViewModel
One feature I have is that I can duplicate a ProductViewModel and insert it into the ProductsViewModel array.
When I clone using:
ko.mapping.fromJS(ko.toJS(itemToCopy));
It doesn't appear to copy correctly - the prices observable array, isn't populated with ProductPriceViewModels - just Object
Here's the view models
var ProductsViewModel = function() {
var self = this;
self.products = ko.observableArray([new ProductViewModel()]);
self.addNewProduct = function() {
self.products.push(new ProductViewModel());
};
self.duplicateProduct = function() {
var itemToCopy = ko.utils.arrayFirst(self.products(), function(item) {
return item.visible();
});
//if i look at itemToCopy.prices() it is an array of ProductViewModel
var newItem = ko.mapping.fromJS(ko.toJS(itemToCopy));
//if i look at newItem.prices() it is an array of Object
self.products.push(newItem);
};
};
var ProductViewModel = function() {
var self = this;
self.name = ko.observable();
self.visible = ko.observable(true);
self.prices = ko.observableArray([new ProductPriceViewModel()]);
self.addPrice = function() {
self.prices.push(new ProductPriceViewModel());
};
};
var ProductPriceViewModel = function() {
var self = this;
self.name = ko.observable();
self.price = ko.observable();
};
I solved this by passing in a mapping configuration like this:
var mapping = {
'prices': {
create: function (options) {
return new ServicePriceViewModel(options.data);
}
}
};
on
var newItem = ko.mapping.fromJS(ko.toJS(productToCopy), mapping);
and changing my ProductPriceViewModel to accept data as a parameter:
var ProductPriceViewModel = function (data) {
var self = this;
self.name = ko.observable();
self.description = ko.observable();
self.price = ko.observable();
self.priceIsFrom = ko.observable();
if (data)
ko.mapping.fromJS(data, {}, this);
};
I am trying to get this function to get the correct scope for its "this" operator, but no luck. Inside the AssetName = function(options){ code block, I want the "this" to point to the class AssetName. What is it that I am missing? The scope of this right from the beginning is window.
Assetname: function(options){
var Base = WM.Utility.GenericFilter()
options = options;
if (typeof Object.create !== "function") {
// For older browsers that don't support object.create
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
var AssetName = {};
AssetName = function(options){
return function(){
var self = this;
debugger;
// Call the super constructor.
Base.call(this, options);
this.$mod.on('change', '#asset-name-quick-search', self,
this.search);
this.$mod.on('click', '.close', self, this.remove);
this.initTypeAhead();
this.$selectionList = this.$mod.find("#asset-name-selection-list");
this.assetListItems = [];
return this;
}(options, AssetName);
}
// The AssetName class extends the base GenericFilter class.
AssetName.prototype = Object.create(Base.prototype);
AssetName.prototype.initTypeAhead = function(){
var options = {};
options.source = _.pluck(this.collection, 'asset_name');
options.items = 8;
this.$mod.find('#asset-name-quick-search').typeahead(options);
};
AssetName(options);
return AssetName;
},
AssetName = function(options){
return function(){
var self = this;
debugger;
// Call the super constructor.
Base.call(this, options);
this.$mod.on('change', '#asset-name-quick-search', self, this.search);
this.$mod.on('click', '.close', self, this.remove);
this.initTypeAhead();
this.$selectionList = this.$mod.find("#asset-name-selection-list");
this.assetListItems = [];
return this;
}(options, AssetName);
}
change to
AssetName = function(options){
var aa = function(){
var self = this;
debugger;
// Call the super constructor.
Base.call(this, options);
this.$mod.on('change', '#asset-name-quick-search', self, this.search);
this.$mod.on('click', '.close', self, this.remove);
this.initTypeAhead();
this.$selectionList = this.$mod.find("#asset-name-selection-list");
this.assetListItems = [];
return this;
};
aa.call(AssetName,options);
}
In your code, the function aa is called as aa(options); so this is window.
[update]
I fix the bug with the following code:
AssetName = function (options) {
AssetName = function (options) {
var aa = function () {
alert(this);
return this;
};
aa.call(this, options);
}
AssetName.prototype.initTypeAhead = function () {
alert(1);
}
return new AssetName(options);;
};
var test = AssetName();
test.initTypeAhead();
But I suggest how about writing the code like bellow:
AssetName = function (options) {
AssetName = function (options) {
alert(this);
}
AssetName.prototype.initTypeAhead = function () {
alert(1);
}
return new AssetName();
};
var test = AssetName();
test.initTypeAhead();
You cam just move your var self = this out side of the anonymous returned function. Then you can use just use self.