I have some code using angularJS.
In my application initialization logic, I keep geting an error, but I can't figure out why.
I think this may be a problem with the promise.
Here is my controller:
// TeacherCtrl.js
(function () {
"use strict";
angular
.module("app.controllers")
.controller("TeacherController", TeacherController)
.config(["$routeProvider", config]);
TeacherController.$inject = ["DataService"];
function TeacherController(DataService) {
var vm = this;
vm.data = {};
begin(7, 163000001);
function begin(appId, schoolId) {
DataService.GetData(appId, schoolId).then(function (data) {
console.log(data);
});
}
}
function config($routeProvider) {
$routeProvider
.when("/teacher", {
"templateUrl": "components/teacher/teacher.html"
, "controller": "TeacherController"
, "controllerAs": "vm"
});
}
})();
And here is my service:
// app.services.js
(function () {
"use strict";
angular
.module("app.services")
.factory("DataService", ApplicationData);
DataService.$inject = ["KeysResource"];
function DataService(KeysResource) {
return {
"GetData": GetData
};
function GetData(appId, schoolId) {
return KeysResource.load({
"appId": appId,
"schoolId": schoolId
});
}
}
})();
and this is the error I am getting:
TypeError: undefined is not a function
at iniciar (http://my.url/TeacherCtrl.js:18:72)
at new TeacherController (http://my.url/TeacherCtrl.js:15:9)
at .. // angular js code here
What it's looks like is that the ".then" function for the promise is not immediately available. Shouldn't it be???
EDIT
Here is the KeysResource I've mentioned
"use strict";
(function () {
var restClient = angular.module("restClient", ["ngResource"]);
var serviceURL;
restClient
.factory("KeysResource", ["$resource", function ($resource)
{
serviceURL = "http://my.url/service/";
return $resource(serviceURL, null, {
"load": {
"method": "get",
"url": serviceURL + "load"
}
});
}]);
})();
I've found this question with a similar problem.
The solution is related to $resource, which does not return a promise directly. If I want to use the promise of $resource, I will need to use $promise too, like that:
//TeacherCtrl.js
function begin(appId, schoolId) {
DataService.GetData(appId, schoolId).$promise.then(function (data) {
console.log(data);
});
}
Related
This is my service:
(function () {
'use strict';
angular
.module('app')
.service('ClientsService', Service);
function Service($http) {
function getClients() {
$http.get('app/client/clients.json')
.then(function(res){
return res.data;
});
}
return {
getClients: getClients,
};
}
})();
If I a console log inside then I can obtain the clients from the json file.
Then I want to use the service in my component:
(function () {
'use strict';
var module = angular.module('app');
module.component("client", {
templateUrl: "app/client/client.html",
controllerAs: "model",
controller: function (ClientsService) {
var model = this;
model.clients = ClientsService.getClients();
console.log(model.clients)
}
});
})();
But the log says me: undefined.
How can I fix it?
You'll need minor refactoring for this to work.
(function () {
'use strict';
angular
.module('app')
.service('ClientsService', Service);
function Service($http) {
function getClients() {
//Notice the return here? we're returning a promise.
return $http.get('app/client/clients.json')
.then(function(res){
return res.data;
});
}
return {
getClients: getClients,
};
}
})();
(function () {
'use strict';
var module = angular.module('app');
module.component("client", {
templateUrl: "app/client/client.html",
controllerAs: "model",
controller: function (ClientsService) {
var model = this;
//getClients() now returns a promise that is resolved
//when the client list is loaded
ClientsService.getClients().then(function(clients){
model.clients = clients;
console.log(model.clients);
});
}
});
})();
It is because, the http request has not been completed. You will have data only after completion of http request. You can try following code. Also return http promise from the service.
module.component("client", {
templateUrl: "app/client/client.html",
controllerAs: "model",
controller: function (ClientsService) {
var model = this;
ClientsService.getClients().then(function(clients){
model.clients = clients;
console.log(model.clients)
})
}
});
Change Service like this:
(function () {
'use strict';
angular
.module('app')
.service('ClientsService', Service);
function Service($http) {
function getClients() {
return $http.get('app/client/clients.json')
.then(function(res){
return res.data;
});
}
return {
getClients: getClients,
};
}
})();
I want to inject a service into app.config any idea please ?I want to inject a service into app.config any idea please ?I want to inject a service into app.config any idea please ?
app.js
'use strict';
angular.module('crud', [
'ngRoute',
'angular-jwt',
'ngSails',
'ngMessages',
'ngResource'
])
.config(function ($httpProvider,$routeProvider, $locationProvider,$sailsProvider,jwtInterceptorProvider,User) {
//$httpProvider.interceptors.push('jwtInterceptor');
//console.log($sailsProvider);
$routeProvider
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
});
Serviceuser.js
'use strict';
angular.module('crud').service('User', function ($sails) {
//console.log($sails);
return {
signup: function (data) {
return $sails.post('/api/user',data);
}
}
});
Here you go straight from the docs:
Registering a Service with $provide
You can also register services via the $provide service inside of a module 's config function:
angular
.module('myModule', [])
.config(['$provide ',
function($provide) {
$provide.factory('serviceId ', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
}
]);
This technique is often used in unit tests to mock out a service'
s dependencies.
Hope this helps.
(function() {
'use strict';
angular
.module('example.app', [])
.config(['$provide',
function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
}
])
.controller('ExampleController', ExampleController)
.service('exampleService', exampleService);
exampleService.$inject = ['$http'];
function ExampleController(exampleService) {
var vm = this;
vm.update = function(person, index) {
exampleService.updatePeople(person).then(function(response) {
vm.persons = response;
}, function(reason) {
console.log(reason);
});
};
}
// good practice to use uppercase variable for URL, to denote constant.
//this part should be done in a service
function exampleService($http) {
var URL = 'https://beta.test.com/auth/authenticate/',
data = {},
service = {
updatePeople: updatePeople
};
return service;
function updatePeople(person) {
//person would be update of person.
return $http
.post(URL, person)
.then(function(response) {
return response.data;
}, function(response) {
return response;
});
}
}
})();
you can use like:
angular.module('app', ["ui.router"])
.config(function config ($stateProvider){
$stateProvider.state("index", {
url:"",
controller: "FirstCtrl as first",
templateUrl: "first.html"
})
.state("second", {
url:"/second",
controller:"SecondCtrl as second",
templateuRL:"second.html"
})
})
here is the full working example with plunker
I've just started using Angular alongside RequireJs and so far I have created a structure that looks like this:
app.js
app.core.js
app.controllers.js
app.services.js
The core module is where I hinge dependencies and pull in the services and controller modules, like this for example:
(function () {
var dependancies = ['angular'];
define(dependancies, function (angular) {
return angular.module('app.services', [])
.factory('VehicleService', ['$injector', function ($injector) {
var stub = {};
require(['../Angular/Services/VehicleService'], function (VehicleService) {
angular.extend(stub, $injector.invoke(VehicleService));
});
return stub;
}]);
});
})();
And each service is created in its own file like so:
(function () {
define(function () {
return ['$http', function ($http) {
return {
getAllMakes: function () {
return $http.get('/Api/RegisteredVehicle/GetAllMakes')
.success(function (response) {
return {
vehicleName: response
}
});
}
};
}];
});
})();
How can I now use $stateprovider.state.resolve and get my service instantiated correctly?
.state('quote', {
url: '/quote',
templateUrl: '/Sales/Dashboard/CreateQuoteVehicle',
controller: 'QuoteProposalCtrl as vm',
resolve: {
vehicleInfo: function () {
var stub = {};
require(['../Angular/Services/VehicleService'], function (VehicleService) {
angular.extend(stub, $injector.invoke(VehicleService));
});
return stub;
}
}
})
On your core angular module, inject $stateProvider, then put in the states. It should pull in the rest of your dependancies. This should then be loaded as the main starting requirejs file.
(function () {
var dependancies = ['angular', 'app.core', 'app.controllers', 'app.services'];
define(dependancies, function (angular) {
var app = angular.module('myApp', ['app.core', 'app.controllers', 'app.services']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('quote', {
url: '/quote',
templateUrl: '/Sales/Dashboard/CreateQuoteVehicle',
controller: 'QuoteProposalCtrl as vm',
resolve: {
vehicleInfo: function () {
var stub = {};
require(['../Angular/Services/VehicleService'], function (VehicleService) {
angular.extend(stub, $injector.invoke(VehicleService));
});
return stub;
}
}
})
});
return app;
})();
Depending on your setup you'd be loading the app something like:
<script data-main="scripts/app" src="scripts/require.js"></script>
One thing, im not sure you need this require, since it should already be loaded with the app.services dependancy.
var stub = {};
require(['../Angular/Services/VehicleService'], function (VehicleService) {
angular.extend(stub, $injector.invoke(VehicleService));
});
return stub;
I want to develop a generic translator component with configurable url and paramsFn. Here paramsFn can either be a plain function or a function with service dependencies. paramsFn is expected to return a promise.
(function () {
"use strict";
angular.module("translator-app", [])
.provider(translatorProvider);
function translatorProvider() {
var
url,
paramsFn;
//Provider Config Functions
function setUrl (pUrl) {
url = pUrl
};
function setParamsFn (pParamsFn) {
paramsFn = pParamsFn;
};
function factory ($http, $q) {
//Service Function Pseudo
function translate(key) {
if (translateions are cached) {
//return promis of cached translations
} else {
/*
make http call with configured url and
paramsFnto fetch translations.
Cache translations.
Return promise with translations.
*/
}
} //translate
//Service Object
return {
translate: translate
};
} // factory
factory .$inject = [
"$http"
"$q"
];
//Exposed functionality
this.setUrl = setUrl;
this.setParamsFn = setParamsFn;
this.$get = factory;
}
}();
An application can use translator after configuring it. User app provide will be able to provide paramFn with service dependencies. paramFn will be invoked later when translator.translate(...) method is called.
(function () {
"use strict";
angular.module('the-app', ["translator-app"])
.config(translatorConfigurator)
.controller(AppController)
function translatorConfigurator (translatorProvider) {
function theParamsFn (someService) {
//use someService to generate and return params object
}
theParamsFn.$inject = [
"someService"
];
translatorProvider.setUrl("/url/to/translator");
translatorProvider.setParamsFn(theParamsFn);
}
function AppController (translator) {
translator.translate("the-key").then(function (translated) {
//do somethid with 'translated'.
});
}
translatorConfigurator.$injec = [
"translatorProvider"
];
AppController.$inject = [
"translator"
];
}());
How can I achieve this?
Short Story:
According to Angular $injector documentation
// inferred (only works if code not minified/obfuscated)
$injector.invoke(function(serviceA){});
// annotated
function explicit(serviceA) {};
explicit.$inject = ['serviceA'];
$injector.invoke(explicit);
// inline
$injector.invoke(['serviceA', function(serviceA){}]);
Novel
Once upon a time there was a poor translatorProvider. Angular, a great super hero, helped translatorProvider to be feature rich by its $injector weapon. translatorProvider built its getParameters function inside factory function and used it in translate.
(function () {
"use strict";
angular.module("translator-app", [])
.provider(translatorProvider);
function translatorProvider() {
var
url,
paramsFn;
//Provider Config Functions
function setUrl (pUrl) {
url = pUrl
};
function setParamsFn (pParamsFn) {
paramsFn = pParamsFn;
};
function factory ($injector, $http, $q) {
function getParameters() {
var
promise,
fn;
if (paramsFn) {
fn = $injector.invoke(paramsFn);
promise = $q.resolve(fn());
} else {
promise = $q.resolve()
}
return promise;
}
//Service Function Pseudo
function translate(key) {
if (translateions are cached) {
//return promis of cached translations
} else {
getParameters()
.then(function (params) {
return $http({
url: url,
params: params
});
})
.then(function (response) {
var extracted = ...; //extract field from response.data
//put extracted into cache
return $q.resolve(extractedField)
});
}
} //translate
//Service Object
return {
translate: translate
};
} // factory
factory .$inject = [
"$injector",
"$http"
"$q"
];
//Exposed functionality
this.setUrl = setUrl;
this.setParamsFn = setParamsFn;
this.$get = factory;
}
}();
Now translator can be configured as below.
(function () {
"use strict";
angular.module('the-app', ["translator-app"])
.config(translatorConfigurator)
.controller(AppController)
function translatorConfigurator (translatorProvider) {
function theParamsFn (someService) {
return function () {
//returns some parameters object
}
}
theParamsFn.$inject = [
"someService"
];
translatorProvider.setUrl("/url/to/translator");
translatorProvider.setParamsFn(theParamsFn);
}
function AppController (translator) {
translator.translate("the-key").then(function (translated) {
//do somethid with 'translated'.
});
}
translatorConfigurator.$inject = [
"translatorProvider"
];
AppController.$inject = [
"translator"
];
}());
After these changes translatorprovider becomes more powerful and help many other modules and they lived happily ever after.
I have integrated requirejs with my angular app.
But while loading app, it gives me an error 'Argument 'appCtrl' is not a function, got undefined'
Here is my controller code :
define(['Angular'], function (angular) {
function appCtrl($scope, pathServices) {
alert('sa');
}
function homeCtrl($scope, brandService) {
console.log('dfd');
}
});
And along with this, it gives error for 'unknown provider pathServices'
Service code is :
serviceConfig.js
define([
'Angular',
'common/Services/services',
'current/js/services'
], function(angular, commonServices, loacalStorageServices, currentServices) {
"use strict";
var services = {
commonServices : commonServices,
currentServices : currentServices,
};
var initialize = function (angModule) {
angular.forEach(services,function(service, name) {
angModule.service(name, service);
});
}
return {
initialize: initialize
};
});
common/services.js
define(['Angular'], function (angular) {
var app = angular.module('myApp.services', []);
app.factory('pathServices', function($http, $q, $rootScope) {
function pathServices() {
alert('as');
}
return new pathServices();
});
app.factory('anotherServices', function($http, $q, $rootScope) {
function anotherServices() {
alert('as');
}
return new anotherServices();
});
});
current/services.js
define(['Angular'], function(angular) {
var app = angular.module('myApp.services', []);
app.factory('brandsService', function() {
function brandsService() {
var autoCompleteData = [];
this.getSource = function() {
return autoCompleteData;
}
this.setSource = function(states) {
autoCompleteData = states;
}
}
return new brandsService();
});
});
in serviceConfig.js I have included 2 service files.. But the problem is, the last current/service.js file overwrites all files.. How can I include multiple service files ?
I am new to requirejs. How can I use controller function and services using requirejs ?
Can anyone help ?
You have to declare your functions in the global (window) namespace, or register them in your module with the moduleName.controller('controllerName',controllerFn)
So either
define(['Angular'], function (angular) {
window.appCtrl = function($scope, pathServices) {
alert('sa');
}
window.homeCtrl = function($scope, brandService) {
console.log('dfd');
}
});
or
define(['Angular'], function (angular) {
var module = angular.module('theModuleName');
module.controller('appCtrl', function($scope, pathServices) {
alert('sa');
});
module.controller('homeCtrl', function($scope, brandService) {
console.log('dfd');
}
});
should fix this error (I prefer the second approach).