so i have been following a tutorial on how to use AngularJS ui route. I manage to get the views working just fine. However in trying to get the states to work and its just not working. I followed the tutorial exactly but for some reason my states to just show up. Hopefully someone can help me out.
Scirpt.js
var routerApp = angular.module('routerApp', ['ui.router']);
routerApp.config(function($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /home
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'views/home.html',
controller: 'homeCtrl'
})
.state('home.list', {
url: '/list',
templateUrl: 'views/partial-home-list.html',
controller: function($scope) {
$scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
}
})
.state('home.paragraph', {
url: '/paragraph',
template: 'I could sure use a drink right now.'
})
.state('about', {
url: '/about',
templateUrl: 'views/about.html',
controller: 'aboutCtrl'
})
.state('/views/about', {
// Figure out later
});
});
index.html
<!-- Page Content -->
<div id="page-content-wrapper" ng-app="routerApp">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<h1>Content Page</h1>
<p>This is where the template of the vast amount of pages will be loaded. This will keep it a single page applcatino. The
main page will inject the html that needs to be loaded to the user. While the top nav bar will allow the user to
view the rest of the website, which will be separate pages
</p>
<p>Make sure to keep all page content within the <code>#page-content-wrapper</code>.</p>
Toggle Menu
</div>
</div>
</div>
<!-- Angular Template, this is where content will be injected -->
<div ng-include="pages"></div>
<div ui-view></div>
</div>
</div>
home.html
<div class="jumbotron text-center">
<h1>The Homey Page</h1>
<p>This page demonstrates <span class="text-danger">nested</span> views.</p>
<a ui-sref=".list" class="btn btn-primary">List</a>
<a ui-sref=".paragraph" class="btn btn-danger">Paragraph</a>
</div>
partial-home-list.html
<div>
<ul>
<li ng-repeat="dog in dogs">{{ dog }}</li>
</ul>
</div>
Plunker
http://plnkr.co/edit/cN5uM1m20DHGps8cZgzt
Since you are using nested states and views ("home.list" is nested inside "home"), you need to include <div ui-view></div> in your home.html as well.
For further information: https://github.com/angular-ui/ui-router/wiki/Nested-States-&-Nested-Views
Good luck! :)
Related
I am working on a project where I have a created a directive for a multi step form. Essentially trying to replicate this. The project layout has a header,navigation, a content page (which includes a ui-view) depending on the tab selected on the navigation tab.
Now there is a form tab which when clicked routes to a HTML page which includes this form directive. The directive calls the template (which includes another ui-view) loads the html content but failed to load the nested state. How do I set the default state?
The project directory looks like
src
main
app
directive
formData
formData.js
formData.tpl.html
formInterest.tpl.html
formProfile.tpl.html
formFinal.tpl.html
views
header.html
leftNavigation.html
appRun.html
app.js
index.html
The app.js file has states defined as
$stateProvider
.state('landingPage', {
url: '/landingPage',
templateUrl: 'views/landingPage.html'
})
.state('appRun', {
url: '/appRun',
templateUrl: 'views/appRun.html'
})
.state('appRun.first', {
url: '/first',
templateUrl: 'directives/formData/formProfile.tpl.html'
})
.state('appRun.second', {
url: '/second',
templateUrl: 'directives/formData/formInterest.tpl.html'
})
.state('appRun.third', {
url: '/third',
templateUrl: 'directives/formData/formFinal.tpl.html'
});
The appRun.html looks like
<form-data></form-data>
The formData.js directive looks like
var formData = angular.module('formData',[]);
formData.directive('formData',function(){
return {
restrict: 'EA',
scope: {},
replace: true,
link: function($scope, element, attributes){
},
controller: function($scope,$attrs,$http){
$scope.processForm = function(){
console.log("processFrom");
}
},
templateUrl: 'directives/formData/formData.tpl.html'
}
});
the formData.tpl.html looks like
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div id="form-container">
<div class="page-header text-center">
<h2>Let's Be Friends</h2>
<!-- the links to our nested states using relative paths -->
<!-- add the active class if the state matches our ui-sref -->
<div id="status-buttons" class="text-center">
<a ui-sref-active="active" ui-sref=".first"><span>1</span> Profile</a>
<a ui-sref-active="active" ui-sref=".second"><span>2</span> Interests</a>
<a ui-sref-active="active" ui-sref=".third"><span>3</span> final</a>
</div>
</div>
<!-- use ng-submit to catch the form submission and use our Angular function -->
<form id="signup-form" ng-submit="processForm()">
<!-- our nested state views will be injected here -->
<div ui-view></div>
</form>
</div>
<!-- show our formData as it is being typed -->
<pre>
{{ formData }}
</pre>
</div>
</div>
When I click on appRun state it shows up the content in formData.html but ui-view doesn't show a default state. How do I add a default state such that when the formData.html is loaded it also shows appRun.first state?
Use
<ng-include="'directives/formData/formProfile.tpl.html'"/>
Inside <div ui-view></div>. This will be the default page.
The other option:
Mark state appRun abstract.
Whenever linking to appRun link to appRun.first instead.
http://plnkr.co/edit/F5jojPEBVaAIyMa0CXDw
I am having issues getting the ui-router to load a fragment into a bootstrap tab body. I linked my code example above. Please let me know if I missed something. I have looked at 10 different stack overflow examples and non of them have helped solve my problem.
I have an outer ui-view that loads the initial page fragment fine.
<div id="view" ui-view></div>
Next I have the fragment that is loaded (This is where the tabs are set up)
<div class="row">
<div class="col-lg-10 col-lg-offset-1">
<ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
<li ng-repeat="tab in tabs" ui-sref="{{tab.link}}" ui-sref-active="active"><a>{{tab.label}}</a></li>
</ul>
<div id="my-tab-content" class="tab-content" ui-view="tabs"></div>
</div>
</div>
Following that I have a two fragment pages that for test only have some text in them (request-tab.html and approved-tab.html)
Finally, I have the js file that routes the views. I left off the controllers to shorten the post. They are on the plunker if needed but they shouldn't be the issue.
var app = angular.module("BRAVO", ['ui.router', 'ui.bootstrap', 'ui.bootstrap.tpls']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/requestView/request');
$stateProvider
/* Main Views */
.state('requestView', {
url: '/requestView',
templateUrl: 'bravo_home.html',
controller: 'requestCtrl'
})
/*Other states here*/
/* Tabs */
.state('requestView.request', {
url: '/request',
view: {
'tabs': {
templateUrl: 'request-tab.html',
controller: 'requestTabCtrl'
}
}
})
.state('requestView.approved', {
url: '/approved',
view: {
'tabs': {
templateUrl: 'approved-tab.html'
}
}
});
})
plunker
<div class="row">
<div class="col-lg-10 col-lg-offset-1">
<ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
<li ui-sref-active="active" ng-repeat="tab in tabs"><a ui-sref="{{tab.link}}" >{{tab.label}}</a></li>
</ul>
<div id="my-tab-content" class="tab-content" ui-view="tabs"></div>
</div>
</div>
You should set your states like this:
$stateProvider
/* Main Views */
.state('requestView', {
url: '/requestView',
templateUrl: 'bravo_home.html',
controller: 'requestCtrl'
})
/*Other states here*/
/* Tabs */
.state('requestView.request', {
url: '/request',
templateUrl: 'request-tab.html'
})
.state('requestView.approved', {
url: '/approved',
templateUrl: 'approved-tab.html'
});
Then, in your bravo_home.html: <div id="my-tab-content" class="tab-content" ui-view></div>
Note that I removed the ="tabs". You can add controllers to your nested tab states as needed, for example:
// add "controller: 'requestTabCtrl'" to state
.controller("requestTabCtrl", function($scope) {
console.log('Hello Request Tab');
})
// add "controller: 'approvedTabCtrl''" to state
.controller("approvedTabCtrl", function($scope) {
console.log('Hello Approved Tab');
});
I am using angular routing for a admin panel project. Following is my angular js code.
app.js
(function() {
var app = angular.module("app", [
"ngRoute",
"app.dashboard",
"app.calendar",
"app.event"
]);
var dashboard = angular.module("app.dashboard");
dashboard
.config(function($routeProvider) {
$routeProvider.
when('/dashboard', {
templateUrl: '/views/dashboard/dashboard.html',
controller: 'DashBoardIndexController as ctrl'
}).
when('/dashboard/detail', {
templateUrl: "/views/dashboard/detailgraph.html",
controller: "DashBoardDetailController as ctrl"
})
});
......
......
//Controllers related to dashboard module
var calendar = angular.module("app.calendar");
calendar
.config(function($routeProvider) {
$routeProvider.
when('/calendar', {
templateUrl: '/views/calendar/calendar.html',
controller: 'CalendarIndexController as ctrl'
}).
when('/calendar/markevent', {
templateUrl: "/views/calendar/markevent.html",
controller: "CalendarEventController as ctrl"
})
});
......
......
//Controllers related to calendar module
}());
For better code management, I am dividing various module of application and including them in main app module.
After login, the first route loaded will be of dashboard (/dashboard). But before route provider initialized and dashboard loaded, I need to fetch the user's rights level and accordingly create the side navigation menus in parent page. Below is my parent page:
home.html
<body ng-app="app">
<header>
<nav id="mynav" class="bold z-depth-1" role="navigation">
<div class="nav-wrapper container">
<a id="logo-container" href="#" class="brand-logo text-darken-1">Logo</a>
<div class="container">
<a href="#" data-activates="slide-out" class="button-collapse top-nav full hide-on-large-only black-text"><i
class="mdi-navigation-menu"></i></a>
</div>
</div>
</nav>
<ul id="slide-out" class="side-nav fixed center-align">
<!-- This side menu items should be created based on user's rights --!>
</ul>
</header>
<main class="grey lighten-4">
<div id="main-container" class="container z-depth-1 ">
<div ng-view=""></div>
</div>
</main>
As you can see, before ng-view is loaded with first route (/dashboard), I need to make server call to fetch the user's rights. I am relatively new to angular and I think we can do this by resolve promise. But here two modules are different (app and app.dashboard).
What could be the correct way to solve this problem?
Following is my simple routes in app.js -
.state('signup', {
url: '/signup',
templateUrl: 'templates/signup.html',
controller: 'signupCtrl'
})
.state('profile', {
url: '/profile',
abstract: true,
templateUrl: 'templates/profile.html',
})
.state('profile.init', {
url: '/profile-init',
templateUrl: 'templates/profile-init.html'
})
I created a button in signup page on click which should take the user to profile-init page code - $state.go('profile.init')
in profile.html I placed -
<ion-content style="background: #c3c3c3"></ion-content>
in profile-init.html page -
<ion-header-bar class="bar-positive">
<h1 class="title">Profile</h1>
</ion-header-bar>
<div class="row">
<div class="col col-10"></div>
<div class="col col-80 padding">
Thanks for showing your interest
</div>
<div class="col col-10"> </div>
</div>
<ion-footer-bar class="bar-stable">
<button class="button button-clear" ng-click="hello()">Forward</button>
</ion-footer-bar>
But it is moving to /#/profile/profile-starter page but only a background color is coming not text, though I checked the browser console template is loading, let me know what I am doing wrong here.
Create ion-nav-view
<ion-nav-view name="profile"></ion-nav-view>
and modify routes in app.js
.state('profile.init', {
url: '/profile-init',
views: {
'profile': {
templateUrl: 'templates/profile-init.html'
}
}
})
Can't comment yet, and not available to test it but I think you need to use dot ('.') in your file name:
templateUrl: 'templates/profile.init.html'
And of course change the file name too.
I'm having trouble getting my routes to match up with my views. I have the following routes:
.state('tab.account', {
url: '/account',
abstract: true,
views: {
'tab-account': {
templateUrl: 'templates/tab-account.html',
controller: 'AccountController'
}
}
})
.state('tab.account.order', {
url: '/order/:id',
views: {
'order-view': {
templateUrl: 'templates/order-view.html',
controller: 'OrderController'
}
}
})
I have this in templates/tab-account.html
<ion-view title="Account">
<ion-content class="has-header padding">
<h1>Account</h1>
<h2>Your orders</h2>
<div class="card" ng-repeat="booking in bookings">
<div class="item item-text-wrap">
<b><a ng-click="viewOrder(booking.id)">{{ booking.carpark.city }}</a></b> on <b>{{ booking.date | date:'dd.mm.yyyy' }}</b>
</div>
</div>
I have this function in the controller for that view:
$scope.viewOrder = function(id) {
$state.go('tab.account.order', {id:id});
};
Then finally I have this view for the order:
<ion-view ui-view="orderView" title="Order">
<ion-content class="has-header padding">
<h1>Your Order</h1>
</ion-content>
The url seems to work, I end up with #/tab/account/order/1 but it doesn't load that final view!
Cheers in advance!
The ui-router configuration will depend on what you're trying to do.
It looks like you want the account view and the order view to be on separate pages, in which case you won't want it to be an abstract state, since from the ui-router wiki: "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."
I'm not entirely sure you even want a child state for the same reason, since "child states will load their templates into their parent's ui-view." (https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#nested-states--views).
If this is the case, then you can do something like this:
.state('tab.account', {
url: '/account',
templateUrl: 'templates/tab-account.html',
controller: 'AccountController'
})
.state('tab.order', {
url: '/account/order/:id',
templateUrl: 'templates/order-view.html',
controller: 'OrderController'
})
Here's a plunkr: http://plnkr.co/edit/uuEQcxbWchxQyGV7wMlw?p=preview
The views objects have been removed, since you don't really need them unless you have multiple nested views.
If however you wanted the order view on the same page, then you could do something like this: http://plnkr.co/edit/8Tb1uhVDM0HCW8cgPRfL?p=preview
<ion-view title="Account">
<ion-content class="has-header padding">
<h1>Account</h1>
<h2>Your orders</h2>
<div class="card" ng-repeat="booking in bookings">
<div class="item item-text-wrap">
<b><a ng-click="viewOrder(booking.id)">{{ booking.carpark.city }}</a></b> on <b>{{ booking.date | date:'dd.mm.yyyy' }}</b>
</div>
</div>
<ui-view></ui-view> <!-- Where the child view will load -->
</ion-content>
</ion-view>
app.js:
.state('tab.account', {
url: '/account',
templateUrl: 'tab-account.html',
controller: 'AccountController'
})
.state('tab.account.order', {
url: '/order/:id',
templateUrl: 'order-view.html',
controller: 'OrderController'
})
You'll also probably want to remove your ion-content from the order view template, or else you might get some funky double scroll issues.
Hope this helps! Ui-router is pretty confusing, but their wiki has some great documentation and examples to clear things up.