My application has a bunch of states defined using ui-router
home.js
//....
.config(($stateProvider, $urlRouterProvider) => {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
template: '<home></home>',
access: {restricted: false}
})
.state('single',{
url: '/post/:slug',
params: {id: undefined},
template: '<single></single>',
access: {restricted: false}
})
})
// ... some other stuff
At the same time, I have my CMS routes defined in admin.js like so:
import createTemplate from './create/create.post.html';
import adminLayout from './admin.layout.html';
.config(($stateProvider, $urlRouterProvider) => {
$stateProvider
.state('admin', {
abstract: true,
url: '/admin',
template: adminLayout
})
.state('admin.create', {
url: '/create',
template: createTemplate,
access: {restricted: true}
})
.state('admin.posts', {
url: '/posts',
template: '<allposts></allposts>',
access: {restricted: true}
})
.state('admin.edit', {
url: '/edit/:id',
template: '<editpost></editpost>',
access: {restricted: true}
});
})
I have 2 master layouts-one for the the non-CMS routes, and the other for the CMS routes. The reason for keeping them distinct is because they have different UI elements; different enough to justify keeping them in different layouts.
app.html
<div class="app">
<div class="container">
<div class="body row">
<div class="col-md-2">
<navbar menu-items="ac.navItems" orientation="vertical" logo="true"></navbar>
</div>
<div ui-view></div>
<footer class="col-md-6 col-md-offset-2">
<span translate="{{'footer.copyright_symbol.fragment'}}"></span>
{{'footer.copyright_years.fragment' | translate}} {{'colophon.author_name.fragment' | translate}}
</footer>
</div>
</div>
admin.layout.html
<div>
<div ui-view></div>
</div>
The problem I am facing is that whenever I navigate to /admin/create or any of the admin routes, I see the layout for app.html as well as the layout for admin.layout.html together.
How do I configure the ui-views such that I can have distinct layouts for the non-CMS routes and the CMS ones?
Try to give a specific name for each different views, see this :
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-views
Related
I am new to angularjs, I am not able to understand the concept of $stateprovider
I want to create a header that has menu and logo and the body content should change when clicked on menu items accordingly, code is given below, please check and answer my query
HTML
<div ui-view = "header"></div>
<div ui-view = "content"></div>
JS
var App=angular.module('test', ["ui.router", "App.controllers", "ui.bootstrap"]);
App.config(function ($stateProvider){
$stateProvider
.state('test', {
url: '',
views: {
'header': { templateUrl: '/templates/header.html'}
}
});
})
Thank You
Since you have taken two views, one for header and other for content,
<div ui-view = "header"></div>
<div ui-view = "content"></div>
The route also should have two different named routes.
views: {
'header': { templateUrl: '/templates/header.html'},
'content': { templateUrl: '/templates/content.html'}
}
From this,
<div ui-view = "header"></div> opens header.html and <div ui-view = "content"></div> opens content.html
Here is the code,
var App=angular.module('test', ["ui.router", "App.controllers", "ui.bootstrap"]);
App.config(function ($stateProvider){
$stateProvider
.state('test', {
url: '',
views: {
'header': { templateUrl: '/templates/header.html'},
'content': { templateUrl: '/templates/content.html'}
}
});
})
In the HTML,
<ul class="nav nav-pills main-menu right">
<li role="presentation"><a ui-sref="test" class="active">Home</a></li>
<li role="presentation">Bus Chart</li>
<li role="presentation">My Bookings</li>
<li role="presentation">Reviews</li>
<li role="presentation">Contact</li>
</ul>
The first li click goes to our test state as given in routes.
Here is the documentation for the same
In config File
// State definitions
$stateProvider
.state('test', {
abstract: true,
views: {
'main#': {
templateUrl: 'app/../../full-view.html'
},
'header#test': {
templateUrl: '/templates/header.html' // correct path to the template
// controller: 'HeaderController as vm' if needed
},
'footer#test': {
templateUrl: '/templates/footer.html' // correct path to the template
// controller: 'FooterController as vm' if needed
}
}
});
HTML
in content-only.html
<div>
<div ui-view = "content"></div>
</div>
in full-view.html
<div class="container">
<div ui-view="header"></div>
<div>
<div ui-view="content"></div>
</div>
<div ui-view="footer"></div>
</div>
in index.html
<body>
<div ui-view="main"></div>
</body>
in other modules(example)
views: {
'content#test': {
templateUrl: 'app/main/policies/policies.html'
// controller: 'PoliciesController as vm' if needed
}
}
so that whatever you append to content#test will comes under ui-view="content"
for routing avoid using href="", use ui-sref="" since you are using ui-router
example ui-sref="app.home" or ui-sref="app.about" rather than usinghref="#/home" or href="#/about"
When I run my application it directs to localhost:8080/#/ and the header and footer which I setup in the app.html is called:
<div id="wrap">
<main id="main" class="container-fluid clear-top">
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
//content here
</div>
</div>
</nav>
<div ui-view id='content-container'></div>
</main>
</div>
<footer class="footer">
//content here
</footer>
I have created two HTML pages and I want one of the html page to be shown when the app first loads.
Code in A.html:
<input type="text" class="form-control" data-ng-model="searchAll">
<a class="clear" data-ng-click="clearSearch()">X</a>
Code in B.html:
<input type="text" class="form-control" data-ng-model="search">
I have the following code in my router.js:
export default ['$stateProvider', '$urlRouterProvider', ($stateProvider, $urlRouterProvider) => {
$stateProvider
.state('app', {
url: '/',
template: require('./app.html'),
controller: 'AppCtrl',
controllerAs: 'app'
})
.state('app.A', {
url: 'A',
template: require('./A/index.html'),
controller: 'ACtrl',
controllerAs: 'a'
})
.state('app.B', {
url: B
template: require('./B/index.html'),
controller: 'B',
controllerAs: 'B'
});
$urlRouterProvider.otherwise('/');
}];
The header and footer should be in all the pages and the page A.html should be loaded when the app starts. Could anyone let me know how I could achieve this.
I think that you should set your 'app' state as abstracted.
using :
//...
abstract:true
//...
and removing the url property.
This way, the next app child state with root url "/" will be the first displayed on the screen :
.state('app.a', {
url: '/',
template: require('./A/index.html'),
controller: 'ACtrl',
controllerAs: 'a'
})
I think better you call A.html URL in otherwise and keep the header and footer in the index.html instead of creating a separate state for this.
export default ['$stateProvider', '$urlRouterProvider', ($stateProvider, $urlRouterProvider) => {
$stateProvider
.state('app.A', {
url: '/A',
template: require('./A/index.html'),
controller: 'ACtrl',
controllerAs: 'a'
})
.state('app.B', {
url: '/B',
template: require('./B/index.html'),
controller: 'B',
controllerAs: 'B'
});
$urlRouterProvider.otherwise('/A');
}];
I'm using the Ionic Framework to create a mobile app, but I'm having a difficult time with the UI Router. I've gotten a few screens working properly, but I can't seem to get nested views working on a state with parameters. I'd like a URL that looks like /legislator/1/profile. It would have a header with the name of legislator #1 and tabs below. The profile tab would be automatically visible and clicking on other tabs (e.g. /legislator/1/votes) would change the content, but not the header
I wound up abandoning the tabs & sidemenu starter projects to customize my nested views. Here's what I have in app.js. The home and people.* states work correctly, but I can't seem to load the legislator screen with the profile view in place. I've tried changing the abstract & controller attributes, but no luck yet.
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: "/home",
templateUrl: "templates/home.html",
controller: "homeController"
})
.state('people', {
url: "/people",
abstract: true,
templateUrl: "templates/people.html"
})
.state('people.legislators', {
url: "/legislators",
templateUrl: "templates/legislators.html",
controller: "legislatorController"
})
.state('people.following', {
url: "/following",
templateUrl: "templates/following.html",
controller: "followingController"
})
.state('legislator', {
url: "/legislator/{legislatorId:int}",
templateUrl: "templates/legislator.html",
abstract: true
})
.state('legislator.profile', {
url: "/legislator/{legislatorId:int}/profile",
templateUrl: "templates/legislator.profile.html",
controller: "profileController"
})
.state('legislator.votes', {
url: "/legislator/{legislatorId:int}/votes",
templateUrl: "templates/legislator.votes.html",
controller: "votelistController"
})
$urlRouterProvider.otherwise('/home');
// if none of the above states are matched, use this as the fall-back
})
How is this scenario supposed to work in the UI Router? Once I have $stateProvider configured, how should the tabs link to the nested states?
Thanks for any help you can give me.
Maybe your solution is as simple as replacing the classic href by Ui Router's ui-sref:
replace
<ion-tab ... href="#/legislator/{ scopeLegislatorId }/profile">...</ion-tab>
by
<ion-tab ... ui-sref="legislator.profile({ legislatorId: scopeLegislatorId })">...</ion-tab>
Where scopeLegislatorId is the legislatorId, available from your scope.
If that doesn't help, please provide us with your html files (e.g. legislator.html and legislator.profile.html).
You can use following method to create separate views.
state('people.following',{
data:{
anyVar: {
label: 'cp',
text : 'anyText'
}
},
views: {
'content#people': angularAMD.route({
template: infoView,
controller: 'custInfoCtrl',
controllerUrl: 'modules/custCtrl'
}),
'mobileView#people': angularAMD.route({
template: mobileView,
controller: 'mobileCtrl',
controllerUrl: 'modules/mobileBottomViewCtrl'
})
}
})
<pre>
<div ui-view='contentArea'> </div>
<div ui-view='mobileView'> </div>
</pre>
RobYed pointed me in the right direction to figure out the right way to define my states. Here's the bones of what I wound up with.
app.js:
.state('legislator', {
url: "/legislator",
templateUrl: "templates/legislator.header.html",
abstract: true,
})
.state('legislator.profile', {
url: "/{seq_no:int}/profile",
templateUrl: "templates/legislator.profile.html",
controller: "profileController"
})
templates/legislator.header.html:
<ion-nav-view animation="slide-left-right">
<div class="bar bar-header" ng-controller="profileController">
{{legislator.name}}
</div>
<div class="tabs tabs-striped tabs-top">
<a class="tab-item" ui-sref="legislator.profile" ng-class="{selected: is('legislator.profile')}">
{{'Profile' | translate}}
</a>
<a class="tab-item" ui-sref="legislator.votes" ng-class="{selected: is('legislator.votes')}">
{{'Votes' | translate}}
</a>
<a class="tab-item" ui-sref="legislator.stats" ng-class="{selected: is('legislator.stats')}">
{{'Stats' | translate}}
</a>
</div>
<div ui-view></div>
</ion-nav-view>
templates/legislator.profile.html:
<ion-content>
<div class="bar bar-stable has-subheader" style="height:145px;">
{{legislator.whatever}}
Content Here
</div>
</ion-content>
profileController.js:
'use strict';
angular.module('myApp').controller('profileController', function($scope, $rootScope) {
$scope.legislator = $rootScope.legislators[$stateParams.seq_no-1];
});
Links from other states:
<a ui-sref="legislator.profile({seq_no:legislator.seq_num})"></a>
I am having a problem in my view. The view is loaded twice and I have no idea what's going on.
What I have done in my index file is this:
<body class="ng-cloak">
<!--Menus-->
<div class="container-fluid">
<div data-ng-controller="HomeCtrl" class="row">
<!--Here is the ui view directive-->
<div class="col col-md-12" data-ui-view ></div>
</div>
</div>
<!--script files here-->
</body>
On the routes file I have these. The problem only occurs when i visit the contact.inner page
$stateProvider
.state('home', {
url: '/',
templateUrl: 'partials/home.html'
})
.state('contact', {
url: '/contact',
templateUrl: 'partials/contact.html'
})
.state('contact.inner', {
url: '/inner',
templateUrl: 'partials/inner.html'
});
I am trying to create nested view with angular breadcrumb ... and here the problem is in state app.input1.input2 its own template input2 is not loading.. its only loading app.input1 continuously...
If I try to give wrong templateUrl in app.input1.input2 then it throws error back but when I give correct path then its not loading same template and any error .. it just loading same template of app.input1
Suggest me some idea why that template is not loading?
#app.js
$stateProvider
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'view/abc.html',
data: {
breadcrumbProxy: 'app.start'
}
})
.state('app.start', {
url: '/start',
templateUrl: 'view/start.html',
data: {
displayName: 'start',
}
})
.state('app.input1', {
url: '/input1',
templateUrl: 'view/input1.html',
data: {
displayName: 'input1',
}
})
.state('app.input1.input2', {
url: '/input2',
templateUrl: 'view/input2',
data: {
displayName: 'input2',
}
});
$urlRouterProvider.otherwise('app.start');
index.html
<div ui-view></div>
abc.html
<div ui-view></div>
start.html
<div>
<a ui-sref="app.input1">Input1</a>
</div>
input1.html
<div>
<a ui-sref="app.input1.input2">Input2</a>
</div>
input2.html
<div>bla bla bla bla</div>
Here is a working plunker. Change made is here:
input1.html
<div>
<a ui-sref="app.input1.input2">Input2</a>
<div ui-view></div> // anchor for child
</div>
The input2 is a child state of input1. So we need to create an anchor/target for it. Check the plunker here
Also, I used this as otherwise:
$urlRouterProvider.otherwise('/app/start');