angularjs ui-router - How to toggle `ui-view` - angularjs

I want to have a button on parent-view to turn on and off the ui-view. Just like how ng-show works. How can I do that?
One idea is to have empty.html(that is empty) as child view and call it when we want to hide ui-view. But I believe it should be better than that.

As you expected and as you suggested - the native solution with UI-Router is - state nesting. So, either parent or some child will just hide that view:
Parent
.state('parent', {
views: {
'': { templateUrl: parent.html},
'toggle#parent': {templateUrl: notEmpty.html },
}
...
Child
.state('parent.child', {
views: {
'toggle': {templateUrl: Empty.html }, // now it is hidden
}
...
There is similar Q & A with working example
Using UI-Router - Is it possible to set only single ui-view using regular syntax?

Have you tried actually using ng-show? You could apply ng-show to the div that houses the ui-view and just reference a function in your controller that sets it to false on the ng-click of the button.

Related

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;
}

render angular route inside another page

I am novice to angularjs. i want to know that is there any way to render html template based on route inside div of other page. let me explain with an example.
/Employee/Add is route which show a add.html template to add new employee.
can i render this add.html or /Employee/Add route in other 'abc.html' page ??. i know we can use ng-include directive to render any html template. but i am looking based on route.
is that possible ??
You can do this using UI-router. Your basically creating a child state. Common use case is to create Tabs within a page. It would look something like this:
.state('league.games', {
url: '/games',
views: {
'tabContent': {
templateUrl: 'app/games/games.html',
controller: 'GamesCtrl',
controllerAs: 'vm',
resolve: {
initialData: ['$stateParams', 'gamesInitialDataService',
function($stateParams, gamesInitialDataService) {
return gamesInitialDataService.getData($stateParams.leagueId);
}]
}
}
}
})

Nested Views VS Separate

I'm trying to decide on an Angular Structure for my app. I started with the Angular Full Stack Generator.
In UI-Router, you can nest states. It seems logical for me to nest related states. ex: Registration, Registration.form, Registration.confirmation.... but those nested states seem to rely on each child view and parent view being viewed on the same page.
Meaning the parent will have an <ui-view> tag that will insert the child view when called.
Is it possible to have a nested state replace the parent?
Or do I have just make unnested states?
Or is this a case for an abstract state?
There is a working example
Child replacing parent is almost "native" UI-Router solution. Let's have this state definitions:
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
})
.state('parent.child', {
url: "/child",
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
})
And this would be the tpl.html, in our case used for both states:
<div ui-view>
<h3>current state name: <var>{{$state.current.name}}</var></h3>
...
</div>
So, what we can see, parent root HTML element, does have attribute ui-view. That means, that this element also plays a role of a target for a child.
Check it in action here

ui-sref not working in nested views

Homework I've done - reviewed almost 8-9 ui-sref related questions (how to, complex examples, etc.) on this site, the related plunks, Scotch.io, etc. I can't seem to figure why my code is not working. I've spent 6-7 hours debugging the app and I can't seem to find the issue.
My page is divided into
a) layout.html - this forces the bootstrap grid system
b) app-navbar - nav bar on top (code is cut-n-paste of bootstrap example for now...)
c) app-accordion - uses the ui bootstrap accordion to display n number of items
d) app-right - right side comprises some UI elements and a ui-grid
The ui-view for all elements render correctly ... i.e., the "index" state is being called in my controller. I added a couple of simple buttons in app-navbar.html just to debug...
<ul class="nav nav-pills">
<li role="presentation" class="active"><a ui-sref="view1">View1</a></li>
<li role="presentation"><a ui-sref="view2">View2</a></li>
</ul>
<div ui-view="view-test"></div>
here's a snippet of my controller code:
.state('view1', {
url: '/view1',
views: {
'view-test': {
templateUrl: 'view1.html',
controller: 'View1Ctrl'
}
}
})
When I hover over the buttons, I see that the .../view1 and 2 show up on the browser's footer but when I click them nothing happens. For now, the accordion still uses href but it stops working if I use ui-sref. Once I get past this, that's the next question ... how do you use ui-sref for controls like accordion?
Any ideas on what might be going on? The plunk: http://plnkr.co/edit/c89j3eFvYyguMt0QznAI
There is updated working plunker. I made 2 changes.
Firstly I upgraded your version to UI-Router 0.2.13 (fixes some issues, simply always use the latest)
Secondly, I added the missing piece in state defintion: who is my parent
.state('view1', {
url: '/view1',
parent: 'index', // here is explicit setting who is parent
views: {
'view-test': {
templateUrl: 'view1.html',
controller: 'View1Ctrl'
}
}
})
Check it here
EXTENDED, based on the comment below, with few cites from documentation
Methods for Nesting States
States can be nested within each other. There are several ways of nesting states:
Using 'dot notation'. For example .state('contacts.list', {}).
Use the ui-router.stateHelper to build states from a nested state tree. Courtesy of #marklagendijk.
Using the parent property with the parent name as string. For example: parent: 'contacts'
Using the parent property with the parent object. For example parent: contacts (where 'contacts' is a stateObject)
...
Parent Property using State Name String
Alternately, you can specify the parent of a state via the parent property.
$stateProvider
.state('contacts', {})
.state('list', {
parent: 'contacts'
});

Angular ui tab with seperate controllers for each tab

I would like to make a bootstrap tabset with each tab having it's own controller. Can anyone point me in which direction I should go.
Currently I have made several difference controllers, which I would like to be used in a tabset instead of having them displayed as a different route.
I know I could fake it by having the tabset in the difference controller templates displaying the given controllers tab as active, but I would like to be able to have a main TabController with several child controllers (for each tab)
If you are using angular ui router you can use nested states to do this.
Create an abstract state with a view that contains the tabs and a nested ui-view
Create a child state for each of your tabs, each inheriting from the abstract state
Each child state can set the content of the nested ui-view, and define a controller
$stateProvider.state( 'tabs', {
abstract: true,
url: 'tabs',
views: {
"tabs": {
controller: 'TabsCtrl',
templateUrl: 'tabs.html'
}
}
})
.state('tabs.tab1', {
url: '', //make this the default tab
views: {
"tabContent": {
controller: 'Tab1Ctrl',
templateUrl: 'tab1.html'
}
}
})
.state('tabs.tab2', {
url: '/tab2',
views: {
"tabContent": {
controller: 'Tab2Ctrl',
templateUrl: 'tab2.html'
}
}
});
Why don't you put a directive on each tab that has it's own controller? If you are using 1.x. Separate your code out by directive not tabs

Resources