AngularJS nested states using stateProvider - angularjs

I am trying to implement nested states using stateProvider. Facing issues while loading the nested states using url-routing. I have created two independent states and 2 nested states for one of the inndependent state. Please check the state configuration below:
.state('state1',{
url : "/page1",
templateUrl : "/views/page1.html",
contoller : 'page1ctrl'
})
.state('state2', {
url : "/page2",
templateUrl : "/views/page2.html",
controller : 'page2ctrl'
})
state('state2.nestedstate1', {
url : "/:nestedstate1", //passing as parameter
templateUrl : "/views/temp1.html",
controller : 'page2ctrl'
})
.state('state2.nestedstate1.nestedstate2', {
url : "/nestedstate2/:param1/:param2",
templateUrl : "/views/temp2.html",
controller : 'ctrl'
})
Issue : If I try to load complete page directly using complete url index.html/page2/nestedstate1/nestedstate2/fname/lname, it will first load data from last child state nestedstate2 and then fall back to its parent state 'nestedstate1' and also updates the url to index.html/page2/nestedstate1.
Required behaviour is to execute parent state first then the child state. For Example, nestedstate1 is necessary to load before nestedstate2.
Please suggest if I am missing any configuration.
Thanks

I created working example here. It is 1:1 to your scenario.
In the above script I found only one typo:
// missing dot
state('state2.nestedstate1', {
// should be
.state('state2.nestedstate1', {
The example is then working, while using these calls:
<a ui-sref="state1">
// ui-sref
<a ui-sref="state2">
<a ui-sref="state2.nestedstate1({nestedstate1: 'theNestedStateA'})">
<a ui-sref="state2.nestedstate1.nestedstate2({
nestedstate1: 'theNestedStateB', param1: 'value1' ,param2: 'value2'})">
// href
<a href="#/page2">
<a href="#/page2/nestedstate0">
<a href="#/page2/nestedstate1/nestedstate2/fname/lname">
All the rest should be almost the same. You can compare this working version with your local code, to find out what is wrong...
Check it here
Extend
Each view in (state2 chain) is provided with its own controller
.state('state2', {
url : "/page2",
templateUrl : "/views/page2.html",
controller : 'page2ctrl'
})
.state('state2.nestedstate1', {
url : "/:nestedstate1", //passing as parameter
templateUrl : "/views/temp1.html",
controller : 'page2Nestedctrl'
})
.state('state2.nestedstate1.nestedstate2', {
url : "/nestedstate2/:param1/:param2",
templateUrl : "/views/temp2.html",
controller : 'ctrl'
})
And they are like this:
.controller('page2ctrl', ['$scope', function ($scope) {
console.log('page2ctrl')
}])
.controller('page2Nestedctrl', ['$scope', function ($scope) {
console.log('page2Nestedctrl')
}])
.controller('ctrl', ['$scope', function ($scope) {
console.log('ctrl')
}])
Then when navigating to url: page2/nestedstate1/nestedstate2/fname/lname, we can see this in console:
page2ctrl
page2Nestedctrl
ctrl
And that should show, that all the states are initiated in expected order

Related

'/:routeparams' is overriding other route in angularjs

app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'junk.html',
})
. .when('/:pageuniqueid', {
templateUrl : 'page.html',
})
// route for the about page
.when('/first', {
templateUrl : 'first.html',
})
// route for the contact page
.when('/second', {
templateUrl : 'second.html',
});
});
If i type 'example.com/first' in the URL then instead of getting first.html i am getting page.html.
I am implementing the page that user can access directly with their dynamic pageid after base URL.
I want to get page.html only if it is not matched with the other routes. Is there a way to achieve this?
The order of the route definitions matters.
If you define the '/first' route before the '/:pageuniqueid', it should work.
The angular router stops evaluating the routes after the first match.
So in order to get the page.html as a fallback, you should put it as last entry in the list.

angularjs routing - stay on page and do nothing on "otherwise" method

I need to set Angularjs routing to do nothing on "otherwise" method.
var townApp = angular.module('townApp', ["ngRoute"]);
townApp.config(function($routeProvider){
$routeProvider
.when("/dashboard", {
templateUrl : "/profile/dashboard/"
})
.when("/payments", {
templateUrl : "/profile/payments/",
})
.otherwise(
/* DO NOTHING.*/
)
});
Right now, it cleans the ng-view directive upon changing url to an undefined one and that's not what I need.
How can I make it stay on the same page and do nothing?
I found this Here.
I have no idea what is happening but it works as i want.
townApp.config(function($routeProvider){
$routeProvider
.when("/dashboard", {
templateUrl : "/profile/dashboard/"
})
.when("/payments", {
templateUrl : "/profile/payments/",
})
.otherwise({redirectTo: $routeProvider});
});

Pass value to a template pages using Angular

I'm pretty new in Angular since today. :)
I've followed a lot of tutorials since this morning and for each one the same question from my side without answer.
I saw that my navigation could be as simple as the following:
<h3>HTML</h3>
<ul class="nav navbar-nav navbar-right">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
JS
scotchApp.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
// route for the about page
.when('/about', {
templateUrl : 'pages/about.html',
controller : 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl : 'pages/contact.html',
controller : 'contactController'
});
});
But how it works if I need to page some value to a template page ?
And how can I get this passed value to use it in my template page ?
Thanks for your help.
Simply
define variable in controller $scope.variablename=value;
access in template as variablename inside double quotes or access as {{variablename}} outside the tag.
Don't forget to inject $scope dependency in controller.
Its all about using REST.
So lets say you want to pass a email id to your contact page, this is how your code would change.
//change in your html link. I have hard coded email for convenience. You could get it from $scope
<li>Contact</li>
Then you have to add the variables in your REST URL
//changes in your app.js
// route for the contact page
.when('/contact', {
templateUrl : 'pages/contact.html/:emailId',
controller : 'contactController'
});
And finally changes in your controller.
You'll have to add dependency for "$stateParams" and then the variable value will be available in your controller
scotchApp.controller ('contactController',['$stateParams', function($stateParams){
var emailId = $stateParams.emailId;
]})

Angularjs and dynamic routes

I am trying to create a link in my template angularjs by doing something like:
<a ng-href="/#!/content/[[value.id]]">[[key]]</a>
But I am wondering myself if is possible do something like symfony2 does, example:
routing.yml
home_redirect:
path: /
defaults:
_controller: FrontendBundle:Controller:function
path: /home
permanent: true
options:
expose: true
And using it in your twig template by doing:
one link to home
That is really, really helpful because I don't have to "hardcode" all my routes.
To ensure a proper routing, you can use ui-router.
Here is an exemple on plunker
How this works :
1 - Follow the installation guide on their github
2 - Write your state definition :
app.config(function($stateProvider, $urlRouterProvider){
//If no route match, you'll go to /index
$urlRouterProvider.otherwise('/index');
//my index state
$stateProvider
.state('index', {
url: '/index',
templateUrl: 'index2.html',
controller: 'IndexCtrl'
})
//the variable state depending on an url element
.state('hello', {
//you will be able to get name with $stateParams.name
url: '/hello/:name',
templateUrl: 'hello.html',
controller: 'HelloCtrl'
})
});
3 - Write links by their state name :
//add this directive to an html element
//This will go to /index
ui-sref="index"
//This will go to /hello/
ui-sref="hello"
//This will go to /hello/ben
ui-sref="hello({name:'ben'})"
//This will go to /hello/{myname}
ui-sref="hello({name:myname})"
4 - Get the param into your controller :
//inject $stateParams
app.controller('HelloCtrl', function($scope, $stateParams){
$scope.controller = "IndexCtrl";
//get the param name like this
$scope.name = $stateParams.name;
});
Hope it helped. Also keep in mind the ui-router got some really powerful tools such as resolve and nested state/view. You'll probably need theses now or later.
PS : If the plunker don't work, just fork it and save again.
You could do this :
'use strict';
angular.module('AngularModule')
.config(function ($stateProvider) {
$stateProvider
.state('YourStateName', {
url: '/your/url',
views: {
'aViewName': {
templateUrl:'views/components/templates/yourTemplate.html',
controller: 'YourController'
}
},
resolve: {
}
});
});
// then in your controller
angular.module('AngularModule')
.controller('MyController',function($scope, $state){
$scope.goTo = function(){
$state.go('YourStateName');
}
}
);
//in your html make sure the <a> tag is in scope with the 'MyController'
<a ng-click='goTo'>[[key]]</a>
or
you can just do this :
<a ng-href="/your/url"></a>
that way you bypass the controller you can still put logic in the controller that was specified in the state

How to handle long dynamic urls with angular ui-router?

I am building the front-end app for a REST service, and most of the resources are located at long urls where most of the segments are dynamic based on records created in the app by users. Obviously I won't be able to know or create hardcoded routes for most of these records.
My question I suppose is how to handle urls like this with ui-router:
<semester>/<program>/<class>/enrollment
or
<semester>/myclasses/<class>/assignments
There is always at least one static, predictable segment in every resource url, and the segments are always in a predictable order.
Do I make abstract states for each segment in the url like:
$stateProvider.state(semester)
.state(program)
.state(class)
.state(assignments);
??
I've tried building routes that look like this:
param = {
name: "param",
url: "/:hue/:temp/param",
templateUrl: "http://localhost:81/route/tpl/param.tpl.html",
controller: "paramController"
};
but it ends up sending me back to the .otherwise() state when I link to the "param" state.
Thanks for any help, I'm a bit stumped.
I had a similar problem and I quickly coded this:
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('app', {
url : "/app",
abstract : true,
templateUrl : "layout/navigation-drawer.tpl.html"
}).state('app.help', {
url : "/help",
views : {
'menuContent' : {
templateUrl : "layout/help.html"
}
}
}).state('app.settings', {
url : "/settings",
views : {
'menuContent' : {
templateUrl : "layout/settings.html"
}
}
}).state('app.rate-us', {
url : "/rate-us",
views : {
'menuContent' : {
templateUrl : "layout/rate-us.html"
}
}
}).state('app.projects', {
url : "/projects",
views : {
'menuContent' : {
templateUrl : "layout/projects.html",
controller : 'ProjectsCtrl'
}
}
}).state('app.forms', {
url : "/:project_name/forms",
views : {
'menuContent' : {
templateUrl : "layout/forms.html",
controller : 'FormsCtrl'
}
}
}).state('app.entries', {
url : "/:project_name/:form_name/entries/:form_id",
views : {
'menuContent' : {
templateUrl : "layout/entries.html",
controller : 'EntriesCtrl'
}
}
});
which is working, "/:project_name/:form_name/entries/:form_id" will resolve to something like app/Mirko_test/University/entries/1
Ok so I tested this out and it works in my case. It fails when the state is only a parameter, but it seems as long as each state has a non-parameterized bit, ui-router is able to parse down to children states. I haven't seen this case demonstrated or explained anywhere before. Most tutorials only cover simple hardcoded nested states and not parameterized ones.
It's not ideal, but it works.
I hope this helps someone else facing this issue. :)
var app = angular.module('app', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ( $stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise("/");
$locationProvider.html5Mode(true);
var semester = {
name: "semester",
abstract: true,
url: "semester/:sem",
templateUrl: "http://localhost:81/route/to/semtemplate.tpl.html",
controller: "semesterController"
},
program = {
name: "program",
parent: sem,
url: "program/:prg",
templateUrl: "http://localhost:81/route/to/prgtemplate.tpl.html",
controller: "programController"
},
classes = {
name: "classes",
parent: prg,
url: "/classes",
templateUrl: "http://localhost:81/route/to/clstemplate.tpl.html",
controller: "classesController"
};
$stateProvider.state(sem)
.state(prg)
.state(classes);
}]);
app.controller('paraController', ['$scope', '$stateParams', '$state',function($scope, $state, $stateParams){
console.log('paraController instantiated');
$scope.sem = $stateParams.params.sem;
$scope.prg = $stateParams.params.prg;
}]);
As this is a hierarchical REST api this pattern works perfectly, and when also taking advantage of scope inheritance from each controller it should be a good fit for my project. I haven't tested extremes of nested states, but it would be interesting to see how it behaves under even more parameterized states. The only limitation I have found is that each state needs to have a non-parameterized part as well. So /:sem fails but semester/:sem works fine.
It's not ideal as it makes URLs longer, but I haven't found a workable alternative.
I know this question is old, but I had essentially the same question recently and found the official answer. Apparently, angular ui-router now supports the notion of URL Parameters in URL Routing, which allow you to specify parameters, along the lines of the following:
$stateProvider
.state('contacts.detail', {
url: "/contacts/:contactId",
templateUrl: 'contacts.detail.html',
controller: function ($stateParams) {
// If we got here from a url of /contacts/42
expect($stateParams).toBe({contactId: 42});
}
})
For more info, go here: https://github.com/angular-ui/ui-router/wiki/URL-Routing#url-parameters

Resources