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.
Related
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;
}
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.
I am trying to setup my app with ui-router. I am familiar with basic nested views but I am wanting to do something more complex. I have my basic setup for the main views. I would like to have a chat popup that has its own views that are independent from the main views. I want to be able to navigate the main views and not affect the states in the chat popup. So how is this done? Do i need to have a abstract state for the chat? and then have nested views from there?
here is a visual.
and here is a plunker
plunker
$stateProvider
.state('root', {
abstract: true,
views: {
'#': {
template: '<ui-view />',
controller: 'RootCtrl',
controllerAs: 'rootCtrl'
},
'header#': {
templateUrl: 'header.html',
controller: 'HeaderCtrl',
controllerAs: 'headerCtrl'
},
'footer#': {
templateUrl: 'footer.html',
controller: 'FooterCtrl',
controllerAs: 'footerCtrl'
}
}
})
.state('root.home',{
parent:'root',
url:'/home',
templateUrl:'home.html',
controller: 'HomeController',
controllerAs:'homeCtrl'
})
.state('root.about',{
parent:'root',
url:'/about',
templateUrl:'about.html'
});
});
I suggest that, don't use footer as a ui-view, because it is completely independent of your states.
Then how?
Make your footer part as a template and use ng-include to render your footer part.
<footer ng-include="'/footer.html'"></footer>
And within footer.html you can specifies the controller for the footer view.
Benefits
No need to handle footer on each state
No need to pass chat history on every change in state.
Create Chat service/function with controllers in different js files and inject to the index.html and script.js. use bootstrap collapsible modal for pop-up chats.
Looking # your plunkr, you're on right track,though injecting controller from script.js via controllerAs is not scalable for larger app.
Instead you can create js files for each controller and service and separate partial views, just need to inject the services and controllers to index.html and mention partial views in stateprovider function.
I am not sure if You want to use route for the chat but there are two ways for you may be more
Use modals that can collabse and open when clicked like that of facebook here
Modals for bootstrap
Use angulars ngHide ngShow
For your navigation while using at sub elements on chat you can create one state for the chat and nest chat navigation in to you chat state so that any state change will not change your other chat states.
That means you will need to use substate concepts of ui-router
I have a question about multiple views. It's difficult to explain but I'll try:
Navigating to state 'About' and setting template url for ui-view 'columnOne' and ui-view 'columnTwo' was done succesfully
.state('about', {
url: '/about',
views: {
// the main template will be placed here (relatively named)
'': { templateUrl: 'partial-about.html' },
// the child views will be defined here (absolutely named)
'columnOne#about': { template: 'Look I am a column!' },
// for column two, we'll define a separate controller
'columnTwo#about': {
templateUrl: 'table-data.html',
controller: 'scotchController'
}
}
});
Now I would like to set the templateUrl of view 'columTwo' from view 'columnOne'.
How is this done? Is it possible?
The example your taking from there website is parallel view example not nested view nested view can be made by making a page and than making other states with . like registration is a page and multistep form than the page containing registration uiview will we state registration and the parts with be like registration.contact,registration.acadamics, registration.extraactivities. And really man there documentation is quiet confusing
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.