When I have multiple id parameters in query, $routeParams.id gives me an array.
That's great. But, if only one id is present in the query, I get a string.
/?id=12&id=34&id=56 // $routeParams.id = ["12", "34", "56"]
/?id=12 // $routeParams.id = "12"
This is bad. Because in the first case, $routeParams.id[0] gives "12",
while in the second one, it gives "1" (first char of "12").
I can work this around by inserting an empty id= to all my links, but this is ugly.
See in Plunker
Is "type-checking in controller" my only option? If so, how do I do it?
index.html:
<html ng-app="app">
<head>
<script src="//code.angularjs.org/1.3.15/angular.js"></script>
<script src="//code.angularjs.org/1.3.15/angular-route.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
home.html:
#/?id=12<br/>
#/?id=12&id=34&id=56<br/>
#/?id=12&id=<br/>
<pre>id: {{id | json:0}}</pre>
<pre>id[0]: {{id[0] | json}}</pre>
script.js:
angular.module('app', ['ngRoute'])
.config([
'$routeProvider',
function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'home.html',
controller: 'HomeCtrl'
});
}
])
.controller('HomeCtrl', [
'$scope', '$routeParams',
function($scope, $routeParams) {
$scope.id = $routeParams.id;
}
]);
EDIT:
For those who wonder, what I am trying to achive is: inter-controller (or inter-view) communication. User selects some items in one view, and sees details for those selected items in the next view. See in Plunker.
The best way to do it is not to use id param multiple times but separate your values with another character and always get an array and you are ready to go!
script.js
(function() {
var app = angular.module('app', ['ngRoute']);
app.config([
'$routeProvider',
function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'home.html',
controller: 'HomeCtrl'
});
}
]);
app.controller('HomeCtrl', [
'$scope', '$routeParams',
function($scope, $routeParams) {
$scope.id = $routeParams.id.split('-');
}
]);
})();
home.html
<p>
#/?id=12-34-56 Array
</p>
<p>
#/?id=12 Array
</p>
<pre>id: {{id | json:0}}</pre>
<pre>id[0]: {{id[0] | json}}</pre>
I wonder why you are passing different values to a single id. However, this should solve your problem
angular.module('app', ['ngRoute'])
.config([
'$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'home.html',
controller: 'HomeCtrl'
});
}
])
.controller('HomeCtrl', [
'$scope', '$routeParams', function($scope, $routeParams) {
$scope.id = angular.fromJson($routeParams.id);
}
]);
Related
Please see my plunkr here
https://plnkr.co/edit/hk7Z0jMwOfoUwJZ98F7a?p=preview
In my app.js I have two controllers and a routeprovider with a resolve for TestController
var app = angular.module('app', ['ngRoute']);
app.controller('DefaultController', ['$scope', function($scope){
$scope.welcome = "Hello World";
}]);
app.controller('TestController', ['$scope', 'context', '$routeParams', function($scope, context, $routeParams){
$scope.text = "TestController loaded!"
}]);
app.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider){
$routeProvider.
when('/test1',{
templateUrl: 'test1.html',
controller: 'TestController',
resolve: {
context: function(){return 'test';}
}
})
}])
In my html, I have an ng-include which should also load test.html in the default view
<body ng-controller="DefaultController">
<h1>{{welcome}}</h1>
<div ng-include="'test.html'" ng-controller='TestController'></div>
</body>
I cannot take the resolve out of the routeProvider as I still need it to when the user goes to '../test'
Is there any way I can resolve contextProvider from the ng-include?
or is there better ways to do this?
Any help would be greatly appreciated.
Create a factory/service and use that:
app.factory('fooResolver', function() {
return {
resolveMe: function() {
return 'test';
}
}
});
Now, use this in your router config:
app.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider){
$routeProvider.
when('/test1',{
templateUrl: 'test1.html',
controller: 'TestController',
resolve: {
context: function(fooResolver) {
return fooResolver.resolveMe();
}
}
})
}])
And do the same in your controller:
app.controller('TestController', ['$scope', 'fooResolver', '$routeParams', function($scope, fooResolver, $routeParams){
$scope.text = "TestController loaded!"
var context = fooResolver.resolveMe();
}]);
<script>
var app= angular.module('myApp', ['ngRoute', 'ngResource']);
app.factory('Greeter', ['$resource',function($resource){
return $resource(
'http://123.com/processor-url.php',{
},{
query: {
method:'GET',
/*params: { myvar: myvarActual },*/
isArray:true
}
}
);
}]);
app
.controller('appointmentController', ['$scope', 'Greeter',function($scope,$routeParams,Greeter){
alert($routeParams.myvar);
Greeter.query(function(data) {
$scope.output = data.myvar;
});
}]);
app.controller('homeController', ['$scope', function($scope){
}])
/*Final Config After Loading Everything*/
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/appointments/:myvar', {templateUrl: 'appointments.html', controller: 'appointmentController'});
$routeProvider.when('/home', {templateUrl: 'home.html', controller: 'homeController'});
$routeProvider.otherwise({redirectTo: '/home'});
}]);
</script>
In the above code, seems the controler is not even recognize myvar that was suppose to be included in the routeProvider's myvar. As the alert will show undefined, instead of the actually value of myvar (i.e. .../appointments/1066 ... if so I expect $routeParams.myvar = 1066, and alert($routeParams.myvar) should be 1066
$routeParams is missing from the dependency declaration so currently it's looking for myvar on Greeter which doesn't exist...
app
.controller('appointmentController', ['$scope', 'Greeter',function($scope,$routeParams,Greeter){
Should be...
app
.controller('appointmentController', ['$scope', '$routeParams', 'Greeter', function($scope, $routeParams, Greeter){
I have an ApplicationController on the body tag. Inside this controller I am setting the username on a response from the server. Somehow the username variable is only available within the HomeController, which is currently not implemented.
index.html
<body ng-controller="ApplicationController">
Welcome {{username}}.
<div ng-view></div>
</body>
home.html
<div>You are logged in as {{username}}.</div>
Javascript
angular.module('APP', [
'ngRoute',
'APP.services',
'APP.controllers',
'APP.auth'
])
.config(function($routeProvider, $httpProvider) {
$httpProvider.interceptors.push('httpRequestInterceptor');
$routeProvider.when("/", {
templateUrl: "/static/partials/home.html",
controller: "HomeController"
});
return $routeProvider.otherwise({
redirectTo: "/"
});
}
);
angular.module("APP.controllers", ['ui.bootstrap.modal'])
.controller("HomeController", function($scope, $rootScope) {
})
.controller('ApplicationController', function($scope, $rootScope, USER_ROLES,
AUTH_EVENTS, AuthService, $modal,
UserService) {
$scope.username = null;
$scope.setCurrentUser = function(user) {
$scope.username = user.username;
}
$rootScope.$on(AUTH_EVENTS.loginSuccess, function(event) {
UserService.get().then($scope.setCurrentUser);
});
});
Generated output
<body>
Welcome
<div>You are logged in as AceUser</div>
</body>
Update 1
If I select the ApplicationController element and then run angular.element($0).scope() I can see the scope and the username available. But still it is not output in the document.
Update 2
The index.html was being generated with Django. Django was processing the template variable and not sending it as output. The solution was to wrap the variable with the {% verbatim %} tag. I will leave this up here for anyone who also has this problem.
Not quite sure why it works in the HomeController. I put together a working Plunk for you to compare your code with.
angular.module('APP', [
'ngRoute',
'APP.controllers'
])
.config(function($routeProvider, $httpProvider) {
$routeProvider.when("/", {
templateUrl: "home.html",
controller: "HomeController"
});
return $routeProvider.otherwise({
redirectTo: "/"
});
});
angular.module("APP.controllers", [])
.controller("HomeController", function($scope, $rootScope) {})
.controller('ApplicationController', function($scope, $rootScope) {
$scope.username = null;
$scope.setCurrentUser = function(user) {
$scope.username = user.username;
}
$scope.setCurrentUser({username: 'bob'});
});
I am having a lot of trouble understanding how stateParams are supposed to work. Everywhere I look suggests that this should pass an item_id of 456 when I travel to the URL /#/manage/456, but instead $stateParams is an empty object. Furthermore, in the $state object that is passed to MainCtrl, I can access all of the parameters by using $state.params, however this seems to be undesirable and hackish.
angular
.module('router',['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider)
{
$stateProvider
.state('manage',
{
url: '/manage',
templateUrl: '/templates/main.html',
controller: 'MainCtrl'
})
.state('manage.item_id',
{
url: '/:item_id',
templateUrl: '/templates/main.html',
controller: 'MainCtrl'
})
}])
.controller('MainCtrl', ['$scope', '$stateParams', '$state', function($scope, $stateParams, $state)
{
// empty object
console.log('$stateParams: ', $stateParams);
// shows the variables i want
console.log('$state.params: ', $state.params);
}])
What you're trying to do should work fine, see this JSFiddle: http://jsfiddle.net/ahchurch/gf7Fa/14/
<script type="text/ng-template" id="item.tpl.html">
embeded item template
</script>
<script type="text/ng-template" id="main.tpl.html">
<ul>
<li>change route</li>
</ul>
<div ui-view></div>
</script>
<div ui-view></div>
angular.module('myApp',['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider)
{
$urlRouterProvider.otherwise("/manage");
$stateProvider
.state('manage',
{
url: '/manage',
templateUrl: 'main.tpl.html',
controller: 'MainCtrl'
})
.state('manage.item_id',
{
url: '/:item_id',
templateUrl:'item.tpl.html',
controller: 'MainCtrl'
})
}])
.controller('mainController', function(){})
.controller('MainCtrl', ['$scope', '$stateParams', '$state', function($scope, $stateParams, $state)
{
// empty object
console.log("main controller");
console.log($stateParams);
}]);
One thing I noticed is that your template is the same file for both states, so you may just be seeing the initialization of the "manage" state, and never seeing the "manage.item_id" state.
Somehow my app stopped working during development and I really cannot get what's wrong with it.
I've removed everything, the only code remaining is:
function handlerControl($scope, $routeParams, $location){
$scope.route = $routeParams;
}
var app = angular.module('Hello', []).config(
function($routeProvider){
$routeProvider.when('/:a/:b', {controller: handlerControl});
}
);
and html is
<body ng-app="Hello">
<div ng-controller="handlerControl">
{{route}}
</div>
</body>
omitting head part with including everything.
When I go to
http://helloday/#/a/b/
I'm getting an empty hash while expecting to get {a: 'a', b: 'b'}
What I'm doing wrong?
Bit modified(to make it work) jsFiddle: http://jsfiddle.net/wWDj2/http://jsfiddle.net/wWDj2/
Routing requires you use ngView, and that you specify either a template or a templateUrl:
App code.
var app = angular.module('myApp', []);
app.config(function($routeProvider) {
$routeProvider.when('/foo/:id', {
controller: 'FooCtrl',
template: '<h1>Foo {{id}}</h1>'
})
.when('/bar/:test', {
controller: 'BarCtrl',
templateUrl: 'bartemplate.html'
})
.otherwise({
controller: 'DefaultCtrl',
template: '<h1>This is the default</h1>'
});
});
app.controller('FooCtrl', function($scope, $routeParams) {
$scope.id = $routeParams.id;
});
app.controller('BarCtrl', function($scope, $routeParams) {
$scope.test = $routeParams.test;
});
app.controller('DefaultCtrl', function($scope){});
Your main page's markup:
<div ng-app="myApp">
Foo 123
Bar Blah
Default route
<hr/>
<div ng-view>
<!-- your processed view will show up here -->
</div>
</div>