I am trying to fetch a drop downlist before the page load using angular $http. I tried few combinations but it keep on giving the same error:
Error: [$injector:unpr] Unknown provider: officeListProvider <- officeList <- myController
http://errors.angularjs.org/1.4.3/$injector/unpr?p0=officeListProvider%20%3C-%20officeList%20%3C-%20myController
I am few weeks old in angular so please pardon in case of any silly mistakes.
var myApp = angular.module('myApp',['ngRoute']);
myApp.config(['$routeProvider',function ($routeProvider) {
$routeProvider.when('../../home/goEeUpdateAngular.obj', {
templateUrl: '/employee_update_angular.jsp',
controller: 'myController',
resolve: {
officeList: function(officeListFactory) {
return officeListFactory.getOfficeList();
}
}
});
}]);
myApp.factory('officeListFactory', function($http, $window) {
$window.alert("Hi");
var factoryResult = {
getOfficeList: function() {
var promise = $http({
method: 'GET',
url: '../../home/goOfficesList.obj'
}).success(function(data, status, headers, config) {
console.log (data);
return data;
});
return promise;
}
};
console.log (factoryResult.getOfficeList());
return factoryResult;
});
myApp.controller('myController',function ($scope,officeList) {
$scope.officeListFactory = officeListFactory.data;
});
The error says "officeListProvider" is not present or not visible, you need to add it as dependency.
Please try the below change:
var ctrl = angular.module('myApp.controllers', []);
to
var ctrl = angular.module('myApp.controllers', ['myApp.services']);
and also please use the same service name it is either srvOfficeList or officeList, and also check your service factory, it is not right - example:AngularJS : factory $http service
Hope it will fix the issue.
Please try to create a CodePen (or similar tool) while posting the question, so that the Answer can tried/fixed in there and shared back with you.
In controller you should call only officeList. Here is the working JSFIDDLE. I too sample webapi instead of your url
var myApp = angular.module('myApp',['ngRoute']);
myApp.config(['$routeProvider',function ($routeProvider) {
$routeProvider.when('../../home/goEeUpdateAngular.obj', {
templateUrl: '/employee_update_angular.jsp',
controller: 'myController',
resolve: {
officeList: function(officeListFactory) {
return officeListFactory.getOfficeList();
}
}
});
}]);
myApp.factory('officeListFactory', function($http, $window) {
$window.alert("Hi");
var factoryResult = {
getOfficeList: function() {
var promise = $http({
method: 'GET',
url: '../../home/goOfficesList.obj'
}).success(function(data, status, headers, config) {
console.log (data);
return data;
});
return promise;
}
};
console.log (factoryResult.getOfficeList());
return factoryResult;
});
myApp.controller('myController',function ($scope,officeList) {
$scope.officeListFactory = officeList.data; //changes are made here
});
Related
Here is my code :
Js:
angular.module('main', [])
.config(['$locationProvider', '$routeProvider',
function($locationProvider, $routeProvider) {
$routeProvider.when('/tables/bricks', {
controller: "myController",
resolve: {
"check" : function($location){
if(!$scope.bricks) {
$route.reload();
}
}
},
templateUrl: 'tables/bricks.html'
});
$routeProvider.otherwise({
redirectTo: '/tables/datatables'
});
}
])
.controller('myController', function($scope, $location, $http) {
var vm = this;
$scope.Bricks = function(){
$location.path('/tables/bricks');
};
vm.getbricks = function(n){
var url = n;
$http({
method: 'GET' ,
url: url,
})
.then(function successCallback(data) {
$scope.bricks = data.data;
console.log($scope.bricks);
}, function errorCallback(response) {
console.log(response);
console.log('error');
});
};
});
HTML:
<button ng-click="vm.getbricks(n.bricks_url);Bricks();"></button>
After click the button in html, my page goes into /tables/bricks, but nothing happend, because resolve probably is wrong. What I want - that i could go to /tables/bricks only then, when $scope.bricks exist, so only when vm.bricks() will be called.
Thanks for answers in advance!
I think your problem is that the vm.getbricks will always return something (in success or error handler), so will never be falsy, and you will always call the Bricks() constructor. try to return true on success callback and false in error callback.
$scope is for controllers, which it can't reach in the config. Instead, you should be returning something from a service, which will be called during your resolve. E.g. if(YourService.getbricks())
Solution: move your logic from a controller into a service. And make sure to return a value from it that can be checked in the config.
app.service('BrickService', function() {
this.getbricks = function(url) {
return $http.get(url) // return the Promise
.then(function(response) {
return response.data; // return the data
}, function(error) {
console.log(error);
});
};
});
With this you can inject the service into the config and run its function.
angular.module('main', [])
.config(['$locationProvider', '$routeProvider',
function($locationProvider, $routeProvider) {
$routeProvider.when('/tables/bricks', {
controller: "myController",
resolve: {
"check": function(BrickService) { // inject
if ( BrickService.getbricks() ) { // run its function
$route.reload();
}
}
},
templateUrl: 'tables/bricks.html'
});
$routeProvider.otherwise({
redirectTo: '/tables/datatables'
});
}
])
You can also use the loaded values in the controller after they have been resolved. For that, you would need to simply return it. So change the logic to this:
resolve: {
"check": function(BrickService) { // inject
var bricks = BrickService.getbricks(); // run its function
if ( bricks ) {
$route.reload();
}
return bricks; // return the result (note: it's not a Promise anymore)
}
}
Then you can inject this resolve into your controller:
.controller('myController', function($scope, $location, $http, check) {
var vm = this;
vm.bricks = check;
...
(Note check was added)
I am new to Angularjs and studied a lot. But I stuck at a point. Google doesn't help me. I have a controller and I have data in $scope.results
app.controller('manage_categories', function($scope, $http, $filter, $window) {
$scope.results = [];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
});
})
now i want to access the same in other without any other $http call. I have done with another call but i don't want this . because i need this in many other controllers.something like this
app.controller('manage_users', function($scope, $http, $filter, $window,results) {
$scope.results = results;
//~ $http({
//~ url: base_url + 'employee/fetchData?table=results',
//~ method: "POST",
//~ }).success(function(data) {
//~ $scope.results = data;
//~ });
})
or any other method. Thanks.
update
I tried this
var myApp = angular.module('myApp',[]);
myApp.factory('results', function() {
return {
name : [{id:21,name:'this is test'}]
};
});
app.controller('manage_users', function($scope, $http, $filter, $window,results) {
$scope.results = results;
})
This is working fine . But not working with $http call .
var myApp = angular.module('myApp',[]);
myApp.factory('results', function($scope,$http) {
$scope.results=[];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
});
return {
name : results
};
});
update 2
after answers i write it like
var canapp = angular.module('canApp', ["ngRoute", "angularFileUpload"]);
canapp.service('ResultsFactory', ['$http', function($http) {
// http call here
var url=base_url + 'employee/fetchData?table=results';
$http.post(url,data).success(function(data){
this.results = data;
});
}])
call like this
canapp.controller('get_candidates', function($scope, $http, $filter, $timeout, $window, ResultsFactory) {
$scope.check=ResultsFactory.results;
});
but it is not setting the value in template
Use $broadcast to share the data between controllers. Your code will look like this
app.controller('manage_categories', function($scope, $http, $filter, $window, $rootScope) {
$scope.results = [];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
$rootScope.$broadcast("results",data);
});
});
app.controller('otherCtrlr', function($scope, $rootScope) {
$rootScope.$on("results", function(event, data){
$scope.results = data;
});
});
But using a service call in the controller is not a best approach. Create a factory and create a method to call your service.
From controller you need to call this method. But to avoid two service calls, you definitely need to use broadcast/emit(depending on data transfer is from parent or child)
There are various possible way of communicating between two controllers. If you just Google share data between controllers angularjs, you may found various links:
Using Services to Share Data Between Controllers
Sharing Data Between Controllers
Share data between AngularJS controllers
Passing data between controllers in Angular JS?
So, in short, possible ways are:
Using Angular Factories (recommended)
Using $rootScope (not recommended)
Using top most controller's scope as root scope
You can do this:
app.factory('ResultsFactory', resultsFactory);
resultsFactory.$inject = ['$http'];
function resultsFactory = function(){
var self = {};
var results = null;
self.getResults = function(){
if(!results){
$http.post(url,data).success(function(data){
results = data;
});
}else{
return results;
}
}
return self;
}
Only the first time that you call to ResultsFactory.getResults() this executes the $http call.
Here's a small fiddle explaining how to share data between controllers.
https://jsfiddle.net/frishi/zxnLwz6d/10/
(Check the browser console to see that both controllers can access data via the service.)
Basically the premise of a service is that it is a singleton that can be used by all the controllers registered on your module.
You want to make that $http call in a service:
.service('myService', ['$http', function($http) {
this.getData = function(){
// Simple GET request example:
return $http({
method: 'GET',
url: 'https://api.github.com/users/mralexgray/repos' // example API
}).then(function successCallback(response) {
return response;
}, function errorCallback(response) {
// return error message
});
}
}])
In your controller:
.controller('Controller2',['$scope','myService',function ($scope,myService) {
$scope.foo = myService.getData();
//resolve the promise:
$scope.foo.then(function(data){
console.log(data);
})
}
])
It is strongly recommended to use separated services as frishi pointed out. This sample is in single file and module just to make it readeable. Following implementation stores the promise and actual request is only made on the initial call to getFoo. The rest will get the response from the in memory promise.
'use strict';
angular.module('foo', [])
.factory('FooResource', function SessionResource($http) {
var fooPromise;
return {
getFoo: function getFoo() {
if(!fooPromise) {
fooPromise = $http.post('employee/fetchData?table=results');
}
return fooPromise;
}
};
})
.controller('FooController', function($scope, FooResource) {
FooResource.getFoo().then(function getFooSuccess(data) {
$scope.results = data;
});
});
I use this angular code with ionic framework
may be its help you..
my factory is..
angular.module('starter.services', [])
.factory('Chats', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var chats = [{
id: 0,
name: 'Ben Sparrow',
lastText: 'You on your way?',
face: 'img/ben.png'
}, {
id: 1,
name: 'Max Lynx',
lastText: 'Hey, it\'s me',
face: 'img/max.png'
}, {
id: 2,
name: 'Adam Bradleyson',
lastText: 'I should buy a boat',
face: 'img/adam.jpg'
}, {
id: 3,
name: 'Perry Governor',
lastText: 'Look at my mukluks!',
face: 'img/perry.png'
}, {
id: 4,
name: 'Mike Harrington',
lastText: 'This is wicked good ice cream.',
face: 'img/mike.png'
}];
return {
all: function() {
return chats;
},
remove: function(chat) {
chats.splice(chats.indexOf(chat), 1);
},
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
});
and i use this factory in many controllers
.controller('ChatsCtrl', function($scope, Chats) {
$scope.chats = Chats.all();
$scope.remove = function(chat) {
Chats.remove(chat);
};
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
in this code factory hit http:// request only one time and i use response on two controllers.
Hope its help you.
I want send a http request and get response of this request. I want if data is save, I get database information and if doesn't save, I get errors. For this, I want use .then in angularjs. I create angularjs controller and services to do this. I have below code in angularjs part:
bolouk.js:
'use strict';
var app = angular.module('app');
app.controller('BoloukCtrl', ['$scope', 'Bolouks', function($scope, Bolouks){
$scope.save = function(){
Bolouks.create($scope.bolouk).then(function(data){
$scope.saveBolouk = data;
},function(err){
$scope.err = err;
}
);
};
}]);
boloukService.js:
'use strict';
var app = angular.module('boloukService', ['ngResource']);
app.factory('Bolouks', function($resource) {
return $resource('/api/bolouks.json', {}, {
create: { method: 'POST', isArray: false }
});
});
and I have below code in rails server:
bolouks_controller.rb:
def create
#bolouk = Bolouk.create(bolouk_params)
if #bolouk.valid?
##bolouk.save
respond_with #bolouk, :location => api_bolouks_path
else
respond_with #bolouk.errors, :location => api_bolouks_path
end
end
private
def bolouk_params
params.require(:bolouk).permit(:boloukcode, :north, :south, :east, :west)
end
Request send to rails server correctly and data is save to database right, but I cannot get response of request and when I run function`, I get below error in chrome console:
TypeError: undefined is not a function
at Scope.$scope.save (http://localhost:3000/assets/controllers/bolouk.js?body=1:19:39)
at http://localhost:3000/assets/angular.js?body=1:10973:21
at http://localhost:3000/assets/angular.js?body=1:20088:17
at Scope.$eval (http://localhost:3000/assets/angular.js?body=1:12752:28)
at Scope.$apply (http://localhost:3000/assets/angular.js?body=1:12850:23)
at HTMLFormElement.<anonymous> (http://localhost:3000/assets/angular.js?body=1:20087:21)
at HTMLFormElement.jQuery.event.dispatch (http://localhost:3000/assets/templates/jquery-1.10.2.js?body=1:4627:9)
at HTMLFormElement.elemData.handle (http://localhost:3000/assets/templates/jquery-1.10.2.js?body=1:4295:46)
I think I don't use .then correctly in angularjs controller, I check $q method too, but again get this error. Any one have idea to solve this problem?
you have assign both module in same variable. this may conflict your code. so use this code:
bolouk.js:
'use strict';
var app = angular.module('app',['ngResource']);
app.controller('BoloukCtrl', ['$scope', 'Bolouks', function($scope, Bolouks){
$scope.save = function(){
Bolouks.create($scope.bolouk).$promise.then(function(data){
$scope.saveBolouk = data;
})
.catch(function (err) {
console.log(err);
})
};
}]);
boloukService.js:
'use strict';
app.factory('Bolouks', function($resource) {
return $resource('/api/bolouks.json', {}, {
create: { method: 'POST', isArray: false }
});
});
var app = angular.module('app',['boloukService']);
app.controller('BoloukCtrl', ['$scope', 'Bolouks', function($scope, Bolouks){
$scope.save = function(){
var user = Bolouks.get();
user.get(function(resp) {
//request successful
}, function(err) {
//request error
});
};
}]);
angular.module('boloukService', ['ngResource']);
app.factory('Bolouks', function($resource) {
var savedData = {}
function get() {
return $resource('/api/bolouks.json', {}, {
create: { method: 'POST', isArray: false}
});
}
return {
get: get
}
});
try this one :)
I am using the $cacheFactory to store a language JSON file for the app, and i run a factory method every new route like this:
index.js
$routeProvider
.when('/',{
'templateUrl':'views/home/index.html',
'controller':'Home',
'resolve': {
'onEnter': function ($rootScope, langFactory) {
return langFactory.getLangFile($rootScope.lang.appLang);
}
}
})
.when('/auth/login',{
'templateUrl':'views/auth/login.html',
'controller':'AuthLogin',
'resolve': {
'onEnter': function ($rootScope, langFactory) {
return langFactory.getLangFile($rootScope.lang.appLang);
}
}
})
factories.js
.factory('langFactory', ['$rootScope', '$window', '$http', '$cacheFactory', '$q', function ($rootScope, $window, $http, $cacheFactory, $q) {
var getLangFile = function (langCode) {
var deferred = $q.defer()
, cache = $cacheFactory('langCache');
if (!!!cache.get('cache' + $rootScope.lang.appLang)) {
$http.get(langCode + '-langFile-to-be-REMOVED.json').success(function (response) {
cache.put('cache' + $rootScope.lang.appLang, response);
deferred.resolve();
}).error(function (err) {
$window.console.error('Unable to retrieve app language: ' + err);
deferred.reject(err);
});
} else {
deferred.resolve();
}
return deferred.promise;
};
return {
'getLangFile':getLangFile
};
}])
On first page load it works , then if i browse, without refreshing, to auth/login i get a console error:
[$cacheFactory:iid] CacheId 'langCache' is already taken!
Seems like (since i call the factory method on every route) it cant use the same id !?
I actually dont know what to do to fix this, any help appriciated, thanks.
This is what worked for me:
cache = $cacheFactory.get('langCache') || $cacheFactory('langCache');
Ok thanks to a guy on IRC i fixed this problem, i just had to change this:
var getLangFile = function (langCode) {
var deferred = $q.defer()
, cache = $cacheFactory('langCache');
to
var cache = $cacheFactory('langCache')
, getLangFile = function (langCode) {
var deferred = $q.defer();
I would like to delay the initialization of a controller until the necessary data has arrived from the server.
I found this solution for Angular 1.0.1: Delaying AngularJS route change until model loaded to prevent flicker, but couldn't get it working with Angular 1.1.0
Template
<script type="text/ng-template" id="/editor-tpl.html">
Editor Template {{datasets}}
</script>
<div ng-view>
</div>
JavaScript
function MyCtrl($scope) {
$scope.datasets = "initial value";
}
MyCtrl.resolve = {
datasets : function($q, $http, $location) {
var deferred = $q.defer();
//use setTimeout instead of $http.get to simulate waiting for reply from server
setTimeout(function(){
console.log("whatever");
deferred.resolve("updated value");
}, 2000);
return deferred.promise;
}
};
var myApp = angular.module('myApp', [], function($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/editor-tpl.html',
controller: MyCtrl,
resolve: MyCtrl.resolve
});
});
http://jsfiddle.net/dTJ9N/1/
Since $http returns a promise, it's a performance hit to create your own deferred just to return the promise when the http data arrives. You should be able to do:
MyCtrl.resolve = {
datasets: function ($http) {
return $http({method: 'GET', url: '/someUrl'});
}
};
If you need to do some processing of the result, use .then, and your promise is chained in for free:
MyCtrl.resolve = {
datasets: function ($http) {
return $http({method: 'GET', url: '/someUrl'})
.then (function (data) {
return frob (data);
});
}
};
You could always just put "ng-show" on the outer-most DOM element and set it equal to the data you want to wait for.
For the example listed on the Angular JS home page you can see how easy it is: http://plnkr.co/CQu8QB94Ra687IK6KgHn
All that had to be done was
That way the form won't show until that value has been set.
Much more intuitive and less work this way.
You can take a look at a near identical question here that uses resources, but it works the same way with $http. I think this should work
function MyCtrl($scope, datasets) {
$scope.datasets = datasets;
}
MyCtrl.resolve = {
datasets: function($http, $q) {
var deferred = $q.defer();
$http({method: 'GET', url: '/someUrl'})
.success(function(data) {
deferred.resolve(data)
}
return deferred.promise;
}
};
var myApp = angular.module('myApp', [], function($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/editor-tpl.html',
controller: MyCtrl,
resolve: MyCtrl.resolve
});
});