AngularJS UI-Router, A state view for all url expect one? - angularjs

Is it possible with ui-router (plugin for AngularJS), to have a state (and his template) for all url expect one or two ?
Thx guys !

If there are things you show in the normal, user-accessible area of your app, but not in the "admin" section, I would organize it such that you have two "base" views, like so:
$stateProvider.state("app", {
abstract: true,
views: {
"graph#": { /* view config */ }
}
}).state("admin", {
abstract: true
});
Then, all of your other states will inherit from one or the other (i.e. "app.foo" or "admin.foo"). As long as you have a <ui-view name="graph"></ui-view> in the root of your base template, it will populate with content in your "app" states, but not your "admin" states. Hope that makes sense.

Related

Create a new angularjs route (IStateProvider) without using parent index

Currently there is an existing website already that uses the main index as the parent index. All the other view and controller uses the parent's side navigation and header. Basically it uses the ui-view main for each of these controllers to display their content.
However, I now need to create a new page within the same project that needs to not use the parent's header and side navigation. Rewriting the whole children will take too much time because there are literally hundreds of views.
Any recommendation for the new route to break out of the iframe or parent?
EDIT: Or perhaps is it possible to hide the parent data while in my new page?
I have done something like this in my project :
$stateProvider.state('landing', {
url: "/landing",
templateUrl: "/appViews/landing.html",
resolve: loadSequence('landingCtrl'),
title: 'Landing'
//************ Set up b2b states*****************************************************************
}).state('b2b', {
url: "/b2b",
template: '<div ui-view class="fade-in-right-big smooth"></div>',
abstract: true
}).state('b2b.login', {
url: '/login',
template: '<div ui-view class="fade-in-right-big smooth"></div>',
abstract: true
});
as you see landing and b2b use completely two different templates here.

Multiple named views with dynamic routing in angularjs

Edit: Here is the complete code at Plunker. Though I can not c anything in execution but same code working at local. However gives a console error though
It all works perfect. But due to :id in /news/:id/, i am getting jquery/angular errors in console which can not be tracked anywhere in my code
I can not c What i am doing wrong.
Edit: Solved plunker https://plnkr.co/edit/FWcuBgGpVdMj3CroFrYJ
First of all you are trying to use ui-router but you're including ngRoute script in your plunker. Change it to
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.min.js"></script>
Then everything should work fine!
I suggest you a few changes...
1. Use ui-sref instead of href because it's much easier to define
ui-sref="post({id:1})" which turns into href="#/news/1"
If you would like to change url some day, then you will have to just change your route file, not each href.
$stateProvider
.state('post', {
url: "news/:id"
or
$stateProvider
.state('post', {
url: "archive/:id"
or
$stateProvider
.state('post', {
url: "whatever/:id"
2. Use abstract state
In your example it's a way better to define abstract state which holds header, content and footer - it's a typical use case.
ui-router
Abstract States
An abstract state can have child states but can not get activated
itself. An 'abstract' state is simply a state that can't be
transitioned to. It is activated implicitly when one of its
descendants are activated.
Some examples of how you might use an abstract state are:
To prepend a url to all child state urls. To insert a template with
its own ui-view(s) that its child states will populate. Optionally
assign a controller to the template. The controller must pair to a
template. Additionally, inherit $scope objects down to children, just
understand that this happens via the view hierarchy, not the state
hierarchy. To provide resolved dependencies via resolve for use by
child states. To provide inherited custom data via data for use by
child states or an event listener. To run an onEnter or onExit
function that may modify the application in someway. Any combination
of the above. Remember: Abstract states still need their own
for their children to plug into. So if you are using an
abstract state just to prepend a url, set resolves/data, or run an
onEnter/Exit function, then you'll additionally need to set template:
"".
Here's a plunker which shows how I would do it.
https://plnkr.co/edit/5FvJaelyxdl5MuALt5VY?p=preview
Hope it helps.
Look at the documentation for ui router named views,
You can use following syntax for using multiple views
$stateProvider
.state('state',{
url: '',
views: {
'header': {
templateUrl: 'views/header.html',
controller: 'headerCtrl'
},
'content': {
template: '<div ui-view=" "></div>', //<-- child templates loaded to here
},
'footer': {
templateUrl: 'views/footer.html',
controller: 'footerCtrl'
}
}
})
.state('state.post', {
url: 'news/:id/:KeyWords'
templateUrl: 'views/post.html' //<-- This goes into content's ui-view
});
I'm guessing you want to keep the header and footer and change content views.
You can achieve this by making this state as parent to all other states
suppose
.state('main',{
abstract: true,
views: {
'header': ... ,
'content': {
template: '<ui-view></ui-view>',
}
'footer': ...
}
})
then all the child views will load their views in the ,
ex: in main.child etc, your template will load in the content's <ui-view></ui-view> tag
If you need to use a custom template depending on keywords you can do the following:
.config(['$routeProvider',
function($routeProvider, $routeParams) {
$routeProvider
.when('/news/:id/:keyWords', {
template: '<div ng-include="url"></div>',
controller: "exampleController"
})
then in the exampleController
function($routeParams, $scope) {
$scope.url = $routeParams.keyWords;
}

Angular ui-router: nested views vs multiple views

ui-router is a great alternative to angular's standard router; it supports nested states and views and multiple views.
I am a little confused, though, by the difference between the two. It seems to me that multiple views can almost always be thinked and implemented as nested views of an "higher-order" component. For example, if we consider an app with a sidebar and a content box, we may model them as two "parallel" views or as making the sidebar the parent view and the content-pane its nested child view that depends on the selected sidebar item.
The readme itself seems to suggest the division is not really clear-cut:
Pro Tip: While multiple parallel views are a powerful feature, you'll often be able to manage your interfaces more effectively by nesting your views, and pairing those views with nested states.
When should I use multiple views and when nested views? Is there some criteria that can help you choose most of the time which is the correct way to model the states, nested vs multiple?
In my understanding, the multiple views are primarily for layout purpose, while the nested views are for parent-children hierarchical views. Using the case you mentioned as an example:
The sidebar and the content could be arranged as two distinct views:
$stateProvider.state('main', {
abstract: true,
url: '/main', //base url for the app
views: {
'': {
//this serves as a main frame for the multiple views
templateUrl: 'path/to/the/main/frame/template.html'
},
'sideBar#main': {
templateUrl: 'path/to/the/sidebar/template.html'
},
'content#main': {
templateUrl: 'path/to/the/content/template.html'
}
}
});
The path/to/the/main/frame/template.html template may contain the following frame:
<div class="row"> Header section </div>
<div class="row>
<div class="col-sm-4"><div ui-view="sideBar"></div></div>
<div class="col-sm-8"><div ui-view="content"></div></div>
</div>
Then in the sideBar or the content templates, you can nest their children subview/partials.
Nested states can be used with both nested and parallel views.
Just to note something about nested states.
What makes nested states great is that you can easily share/inherit data from parent to child view.
e.g:
Lets say you have some pages that require a user has logged in.
$stateProvider
.state('admin', {
url: '/admin'
resolve: { authenticate: authenticate }
})
.state('admin.users', {
url: '/users'
})
function authenticate(Auth) {
if (Auth.isLoggedIn()) {
// Resolve the promise successfully
return $q.when();
} else {
$timeout(function() {
// This code runs after the authentication promise has been rejected.
// Go to the log-in page
$state.go('login', {}, {reload:true});
});
// Reject the authentication promise to prevent the state from loading
return $q.reject();
}
Now every state that is a child state of admin has to pass authenticate service ( even if you navigate directly to admin/users/ ).
So basically in the resolve you can put anything and all the child states will inherit from that.
As for parallel views you have complete control over your layouts.
#TonyGW's example is great
You can use them both in your app at the same time,
I mean nested states and parallel views and you also can have parallel nested views. It really depends on the structure of your layout layout.
If you want child states to appear inside the html of the parent state you have to use nested views.

Creating layouts with multiple nested views using angular-ui-router

I have tried several examples on using the ui-router and the state manager. My nested views and routes are not working as I hoped. Here is an example of how I am configuring the states:
$stateProvider
.state("main", {
abstract: true,
url: "/main",
views: {
"layout": {
templateUrl: "main.index.html"
},
"mainNavigation#main": {
templateUrl: "main-navigation-partial.html"
}
},
onEnter: function() {
console.log("enter main");
}
})
.state("main.dashboard", {
url: "/dashboard",
views: {
"container#main": {
templateUrl:"main-dashboard.html"
}
}
});
As you can see, I have an abstract state named main. All main views will use the mainNavigation view. There is also a container view area where the content for each section will reside. There is an index.html that will be used by all states. So, I may, down the road have an abstract state name client with accompanying states and views.
I can see the individual html files being loaded, but the views are not being populated in the correct named view areas. I have created a plunk that demonstrates how I want to manage my templates and views.
Your main state is loading main.index.html into a ui-view named layout. In your plunker, your root ui-view is unnamed. So to fix this, add a name to that ui-view.
http://plnkr.co/edit/xKDcuk99OACQR73LR0hf?p=preview
<div ui-view='layout'>
Or, you could leave the ui-view unnamed and change the view to reflect that.
"": {
templateUrl: "main.index.html"
}
For more on view naming, see the ui-router wiki.

ui-router routing 2 different states with different templates

I'm using ui-router 0.2.10. My application has two different templates, index.html & index2.html. I've created an abstract state, and i'm referencing both indexs' in their respective states, The problem is I can access the first route fine, but when I try to access the next route it just keeps defaulting to the first route. The abstract templates live in the same folder.
What am I missing here?
.config(["$stateProvider", "$urlRouterProvider", function(sp, urp) {
urp.otherwise("/index1");
sp.state("index1", {
abstract:true,
url: "/index1",
templateUrl: "index.html"
});
sp.state("index1.id", {
url: "/id",
template: "views/partials/index.partial.html",
controller: function($scope,$state){
$state.go('index1.id');
}
});
sp.state("index2", {
abstract:true,
url: "/index2",
templateUrl: "index2.html"
});
sp.state("index2.id", {
url: "/id",
template: "views/partials/index2.partial.html",
controller: function($scope,$state){
$state.go('index2.id');
}
});
}])
I'm assuming that you're trying to go to an abstract state and that won't work as abstract states will only be activated when you go to a child of that abstract state, i.e. you can't direct go to index1 or index2, so this is not legal:
urp.otherwise("/index1"); it should be: urp.otherwise("/index1/id"); instead.
also why are you going to the states again within their own controller? $state.go('index2.id'); is pointless since by the time that line of code is reached you are already in the state index2.id. I think you meant to put those lines of code inside the controllers of the abstract states! Last bit not least don't forget that your abstract states MUST have a ui-view themselves as they are hosting child states.
See plunk.

Resources