AngularJS $routeProvider.when() 's resolve route parameter - what is that 'key'? - angularjs

AngulaR resolve API
The API says for resolve:
key – {string}: a name of a dependency to be injected into the controller.
#egghead, there is this video on the topic:
egghead - Angular resolve
What i do not understand is what that key object is for and why the author of the above video does inject the controller into itself

key – {string}: a name of a dependency to be injected into the
controller.
app.config(function($routeProvider) {
$routeProvider.
when('/', {
controller: 'ListCtrl',
resolve: {
myResolve: function(MyService) {
return MyService();
}
},
templateUrl:'./views/list.html'
})
});
Instead of (in the controller)
app.controller('MyController',function($scope,MyService){
$scope.data = MyService();
});
if you use resolve
app.controller('MyController',function($scope,myResolve){
$scope.data = myResolve;
});
UPDATE
a working example
<!doctype html>
<html ng-app="myModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="content" data-ng-view=""></div>
<script src="http://code.angularjs.org/1.0.8/angular.min.js"></script>
<script>
var myModule = angular.module('myModule', []);
myModule.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: './index.html',
controller: 'IndexCtrl',
resolve: {
hello: function(Hello) {
return Hello.getMessages();
}
}
})
.otherwise({
redirectTo: '/'
});
});
myModule.factory('Hello', function($q, $timeout) {
var getMessages = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve('Hello');
}, 1000);
return deferred.promise;
};
return {
getMessages: getMessages
};
});
myModule.controller('IndexCtrl',function($scope,hello){
$scope.hello = hello;
});
</script>
</body>
</html>
the view
<p>{{hello}}</p>

Related

Redirect to other view with controller method and routh

i want when user click on someone user ,show new view for that information.
I have two controlles,first get list of user,and it is work fine,but second controller have function which hava param of users id,but they show blank page.I realy don t know how to redrect view from second controller method.
This is my code:
<html>
<head>
<title>Angular JS Views</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-route.js"></script>
</head>
<body>
<h2>AngularJS Sample Application</h2>
<div ng-app = "app">
<p>view Students</p>
<p>View Student</p>
<div ng-view></div>
<script type = "text/ng-template" id = "viewStudents.htm">
<ul ng-repeat="entry in pacijenti">
<li>{{ entry.ime }}</li>
<li>{{entry.prezime}}</li>
<li>{{entry.jmbg}}</li>
<button type="button" ng-click="getP(entry.jmbg)" >
</button>
<a ng-href='#viewStudent' ng-click="myCtrl.getP(entry.jmbg)" >click me</a>
</ul>
</script>
<script type = "text/ng-template" id = "viewStudent.htm">
<ul ng-repeat="entry2 in pac">
<li>{{entry2.dijagnoza}}</li>
<li>{{entry2.bolest}}</li>
link1
</ul>
</script>
</div>
<script>
var app = angular.module("app", ['ngRoute']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/viewStudents', {
templateUrl: 'viewStudents.htm',
controller: 'HomeController'
}).
when('/viewStudent', {
templateUrl: 'viewStudent.htm',
controller: 'myCtrl'
}).
otherwise({
redirectTo: '/viewsStudents'
});
}]);
app.factory('photos', ['$http', function($http) {
return $http.get("http://localhost:8080/mavenproject2/fizijatar/12345/pacijenti")
.success(function(response) {
return response;
})
.error(function(response) {
return response;
});
}]);
app.controller('HomeController', ['$scope', 'photos', function($scope, photos) {
$scope.pacijenti=this;
photos.success(function(response) {
$scope.pacijenti =response;
});
}]);
app.controller('myCtrl', function($scope, $http) {
$scope.pac=this;
$scope.getP=function(jmbg){
$http.get("http://localhost:8080/mavenproject2/fizijatar/12345/pacijenti/"+jmbg+"/pregledi")
.then(function(response) {
$scope.pac = response.data;
}, function(response) {
$scope.pac = "Something went wrong";
});
};
});
</script>
</body>
</html>
Modify your route to accept a jmbg id:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/viewStudents', {
templateUrl: 'viewStudents.htm',
controller: 'HomeController'
}).
when('/viewStudent/:jmbg', {
templateUrl: 'viewStudent.htm',
controller: 'myCtrl'
}).
otherwise({
redirectTo: '/viewsStudents'
});
}]);
Then in the controller, retrieve the jmbg id:
app.controller('myCtrl', function($scope, $http, $routeParams) {
$scope.pac = this;
$scope.jmbg = $routeParams.jmbg;
$scope.getP = function(jmbg){
$http.get("http://localhost:8080/mavenproject2/fizijatar/12345/pacijenti/"+jmbg+"/pregledi")
.then(function(response) {
$scope.pac = response.data;
}, function(response) {
$scope.pac = "Something went wrong";
});
// Call the getP function with the jmbg id
$scope.getP($scope.jmbg);
};
});
The link to open the student view would look like this:
<a ng-href="#viewStudent/{{entry.jmbg}}">click me</a>
Here is a working plunker example: https://plnkr.co/edit/99aDJkuvIDopNoILNFGB?p=preview -- Please note, I removed the photo factory usage, and instead hard coded example data.

How can you manually reload a directive?

I have the following code in my Auth factory:
login: function(user) {
return $http
.post('/login', user)
.then(function(response) {
Session.setUser(response.data);
$cookies.put('userId', response.data._id);
$state.go('home', { reload: true });
// $window.location.href = '/';
})
;
},
The problem is that my navbar doesn't get updated (I have properties in the view that are data bound to vm.currentUser; see below). It does when I use $window.location.href = '/', but doing that messes up my tests.
I figure that the solution would be to manually reload the navbar directive. How can I do that? This is what the directive currently looks like:
angular
.module('mean-starter')
.directive('navbar', navbar)
;
function navbar() {
return {
restrict: 'E',
templateUrl: '/components/navbar/navbar.directive.html',
controller: NavbarController,
controllerAs: 'vm'
};
}
function NavbarController(Auth) {
var vm = this;
Auth
.getCurrentUser()
.then(function(currentUser) {
vm.currentUser = currentUser;
})
;
vm.logout = function() {
Auth.logout();
};
}
ok, after you explained further what is broken I noticed that the problem is that in your factory you are not properly returning the deferred promise like deferred.resolve. I should explain, I'm specifically looking around the question of how to "manually reload a directive" because you should not have to manually reload a directive, that's an antipattern. Directives should take care of themselves.
I made a demo. After the proper Auth factory finishing it's thing, with deferred.resolve the directive updates all on it's own because the bound model has changed. Check it out, it solves your problem:
http://plnkr.co/edit/u1FakV?p=preview
var app = angular.module('plunker', []);
app.factory('Auth', ['$timeout', '$q',
function($timeout, $q) {
function getCurrentUserFake() {
var deferred = $q.defer();
setTimeout(function() {
deferred.resolve('Joe Smith');
}, 1000);
return deferred.promise;
}
function getCurrentUser() {
var deferred = $q.defer();
$http.get('/login')
.success(function(data) {
deferred.resolve(data)
})
.error(function(data) {
deferred.reject(data);
});
return deferred.promise;
}
return {
getCurrentUser: getCurrentUser,
getCurrentUserFake: getCurrentUserFake
};
}
]);
app.directive('navbar', navbar);
function navbar() {
return {
restrict: 'E',
template: '<div>{{vm.currentUser}}</div>',
controller: NavbarController,
controllerAs: 'vm'
};
}
function NavbarController(Auth) {
var vm = this;
vm.currentUser = 'logging in...';
Auth
.getCurrentUserFake()
.then(function(currentUser) {
console.log(currentUser);
vm.currentUser = currentUser;
});
vm.logout = function() {
Auth.logout();
};
}
html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.3/angular.js" data-semver="1.4.3"></script>
<script src="app.js"></script>
</head>
<body>
<navbar></navbar>
</body>
</html>

could not modify view after calling ajax from controller using a factory

I have a demo app through which I want to display all countries data in a page(view) using angularjs.
Here is my code:
MyApp.js
var app = angular.module("MyApp", [ 'ui.bootstrap',
'ngRoute',
'MyControllers',
'MyFactory' ]);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/home', {
controller: 'MyController',
templateUrl: 'resources/modules/homeView/homeView.jsp'
})
.when('/view1', {
controller: 'MyController',
templateUrl: 'resources/modules/view1/view1.jsp'
})
.when('/view2', {
controller: 'MyController',
templateUrl: 'resources/modules/view2/view2.jsp'
})
.otherwise({redirectTo: '/home'});
}]);
MyControllers.js
var controllers = angular.module('MyControllers', []);
controllers.controller('MyController', ['$scope', 'Factory',
function($scope, Factory) {
$scope.countries = [];
$scope.showme = false;
$scope.CountryDetailsClick = function() {
var responsePromise = Factory
.getResponse("http://localhost:12345/DemoNew/getCountryList");
responsePromise.success(function(data, status, headers,
config) {
$scope.countries = data;
console.log("countryList size = " + $scope.countries.length);
$scope.showme = true;
});
responsePromise.error(function(data, status, headers,
config) {
alert("AJAX failed");
});
}
}]);
MyFactory.js
var myFactory = angular.module('MyFactory', []);
myFactory.factory('Factory', function($http) {
return {
getResponse : function(url) {
return $http.get(url);
}
}
});
View1.jsp
<body ng-view>
<h1 class="page-header">View1</h1>
{{countries.length}}
</body>
View2.jsp
<body ng-view>
<h1 class="page-header">View2</h1>
{{showme}}
</body>
homeView.jsp
<body ng-view>
<h1 class="page-header">Home</h1>
index.jsp
<body ng-app="MyApp" ng-controller="MyController">
<nav class="navbar navbar-default navbar-static-top" role="navigation"
style="margin-bottom: 0">
Country Details
Country Rate Plans
</nav>
<div id="page-wrapper" ng-view>
</div>
</body>
Now I am getting on console as :-
countryList size = 268
which is correct, I am using spring for backend. I am able to fetch data from the database.
But in View1 I get:
0
Also in View2 I get:
false
That means I am not able to reflect the fetched data to the view. Please help :(
===============================================================
After suggestions given by rob, i changed the following:
I changed my MyFactory.js to:
var myFactory = angular.module('MyFactory', []);
myFactory.factory('Factory', function($http) {
var current = {};
var factory = {
getResponse: function(urlReq){
var data = $http({method: 'GET', url: urlReq}).then(function (result){
current = result.data;
}, function (result){
alert("ERROR: No data returned");
});
},
getList: function(){
return current;
}
}
return factory;
});
And MyControllers.js to:
var controllers = angular.module('MyControllers', []);
controllers.controller('MyController',
function($scope, Factory) {
$scope.CountryDetailsClick = function() {
Factory.getResponse("http://localhost:12345/DemoNew/getCountryList");
}
});
controllers.controller('MyController3',
function($scope, Factory) {
console.log("in controller3");
});
controllers.controller('MyController2',
function($scope, Factory) {
console.log("in controller2");
$scope.countries = Factory.getList();
$scope.showme = true;
});
MyApp.js
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/home', {
controller: 'MyController',
templateUrl: 'resources/modules/homeView/homeView.jsp'
})
.when('/view1', {
controller: 'MyController3',
templateUrl: 'resources/modules/view1/view1.jsp'
})
.when('/view2', {
controller: 'MyController2',
templateUrl: 'resources/modules/view2/view2.jsp'
})
.otherwise({redirectTo: '/home'});
}]);
View2.jsp
<body ng-view>
<h1 class="page-header">View2</h1>
{{showme}}
{{countries}}
</body>
When I click on Country Details, I get "true" and an empty array, but when I click Country Details after clicking Country Rate Plans, it works perfectly fine.
Please find the flaw.!!
You are using the same controller from index.jsp and from your views. So Angular is creating two instances of your controller each with it's own scope. You are calling CountryDetailsClick() from the ng-controller in index.jsp's scope but you are trying to show the value of countries.length from the view's scope.
If you want to share some functionality or state between different controllers (e.g. your CountryDetailsClick() function) then put it in a service.

ngRoute resolve injector issue

I'm getting an error saying,
[$injector:unpr] http://errors.angularjs.org/1.4.1/$injector/unpr?p0=qProvider%20%3C-%20q%20%3C-%20searchResult
When I use the following config and controller. I'm trying to resolve and http request on a specific route.
.when('/fsr/:first', {
templateUrl: 'views/fsr.html',
controller: 'fsrCtrl',
resolve: {
searchResult: ['$http', 'q', function($http, $q) {
var def = $q.defer();
var samples;
$http.get('/api/fsr').success(function(data, status){
samples = data;
def.resolve(data);
})
return {
getSamples: function() {
return def.promise;
}
}
}]
}
})
.controller('fsrCtrl', ['$scope', 'searchResult', function($scope, searchResult){
searchResult.getSamples().then(function(data){
console.log(data);
})
}])
Why I'm getting this?
Here are the solution, change q to $q.
searchResult: ['$http', '$q', function($http, $q) {
...
}
var app = angular.module('webbapp', ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
console.log('woot');
$routeProvider
.when('/fsr', {
templateUrl: 'fsr.html',
controller: 'fsrCtrl',
resolve: {
searchResult: ['$http', '$q', function($http, $q) {
var def = $q.defer();
var samples;
$http.get('/api/fsr').success(function(data, status){
samples = data;
def.resolve(data);
})
return {
getSamples: function() {
return def.promise;
}
}
}]
}
})
}])
.controller('fsrCtrl', ['$scope', 'searchResult', function($scope, searchResult){
searchResult.getSamples().then(function(data){
console.log(data);
})
}])
angular.bootstrap(document, ['webbapp']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello Plunker!</h1>
Load Fsr view
<div ng-view=""></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular-route.min.js"></script>
<script src="app.js"></script>
</body>
</html>

I can't get where that "Error: $injector:unpr Unknown Provider" is from

All works fine if I don't inject into controller "getChildrenNumber", after then I get the error from $injector.
I've read even this https://docs.angularjs.org/error/$injector/unpr, but it seems not be one of that cases
HTML (index.html):
<html class="no-js" ng-app="myApp" ng-strict-di>
.
.
.
<script src="jsLib/angular_v1.4.js" type="text/javascript"></script>
<script src="jsLib/angular-ui-router.min.js" type="text/javascript"></script>
<script src="jsLib/angular-ui-router-statehelper.min.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<script src="routes.js" type="text/javascript"></script>
routes.js:
var config = ["$urlRouterProvider", "$stateProvider", "$locationProvider", function($urlRouterProvider, $stateProvider, $locationProvider){
$urlRouterProvider.otherwise("/multi");
$stateProvider
.state("multi",{
url: "/multi",
views: {
"": {
templateUrl: "multipleView.htm",
controller: "MainCTRL",
controllerAs: "ctrl"
},
"viewA#multi": {
templateUrl: "testingBlock.htm",
controller: "MainCTRL",
controllerAs: "ctrl"
},
"viewB#multi": {
templateUrl: "app/templates/login.htm",
controller: ["$scope", "getChildrenNumber", function($scope, getChildrenNumber){
$scope.nameApp = "nameAppChanged";
$scope.children = getChildrenNumber + " Miao";
}]
}
},
resolve: {
getChildrenNumber: ["$http", function($http){
return "Some response from an API";
}]
}
});
}];
angular
.module("myApp")
.config(config);
app.js:
angular
.module("myApp", ["ui.router"])
.controller("MainCTRL", ["$scope", "getChildrenNumber", function($scope, getChildrenNumber){
this.nameApp = "myApp";
$scope.children = getChildrenNumber;
}]);
You are implementing it the wrong way..
Firstly, in routes.js
$stateProvider
.state("multi",{
url: "/multi",
views: {
// Views Code here //
},
resolve: {
getChildrenNumber: getChildrenNumber
}
});
}];
then you have to create your factory:
angular.module('myApp')
.factory('children', ['$http', function ($http) {
return {
getChildrenNumber: getChildrenNumber
};
function getChildrenNumber() {
return "Some response from an API";
}
}]);
After this you can inject it in your controller as children

Resources