I'm trying to get ui-router to properly work with nested ui-view elements but I'm having trouble getting the nested view to actually render. Here's my code:
app.js
'use strict';
var lunchrApp = angular.module('lunchr', ['ui.router', 'lunchrControllers']);
lunchrApp.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider.
state('mainPage', {
url: '/',
templateUrl: '/partials/main.jade',
controller: 'MainPageController'
})
.state('users', {
url: '/users',
templateUrl: '/partials/users.jade',
controller: 'UserController'
})
.state('users.matching', {
url: '/matching',
templateUrl: '/partials/users.matching.jade'
})
.state('users.matched', {
url: '/matched',
templateUrl: '/partials/users.matched.jade'
})
.state('register', {
url:'/register',
templateUrl: 'partials/register.jade',
controller: 'RegisterController'
});
$locationProvider.html5Mode(true);
}]);
Here's /partials/users.jade (which gets properly displayed in the div(ui-view) in the body tag)
div(class='container')
h1 Welcome
p(ng-repeat='user in users').
Username: {{user.email}}
Firstname: {{user.firstname}}
Lastname {{user.lastname}}
a(ui-sref='users.matching', class='btn btn-default') Start matching me!
a(ui-sref='users.matched', class='btn btn-default') Simulate a match!
div(ui-view)
Here are partials/users.matching.jade
div
h1 We're matching you!
and partials/user.matched.jade
div
h1 You've been matched!
I can successfully navigate to http://localhost:3000/users/matched but when I do, the html is identical to when I go to http://localhost:3000/users.
Why isn't the nested ui-view being correctly populated?
TL;DR
Just put
doctype html
at the top of the jade file that contains <div ui-view>.
If you want more info, there are a number of pretty easy solutions.
More details
The issue basically comes down to the fact that jade is outputting
<div ui-view="ui-view">
which angular can't understand. So you have to make some changes to the output so it's something angular can consume.
Option 1
IMHO, the simplest option would be to put
doctype html
at the top of the jade file that contains <div ui-view>. You must do this even if your jade file is contained within another file that already has doctype html.
Option 2
You can write
.div(ui-view="")
instead of
div(ui-view)
This forces jade to output <div ui-view>.
Option 3
Angular will be fine if you specify a class named ui-view on your div:
<div class="ui-view">
Option 4
Maybe the hackiest way would be to write the raw HTML like this:
<div ui-view>
That makes jade output it exactly the way you typed it.
Related
I have
<base href="/!#/">
at the top of my index.html file. When I go to URL http://localhost:5000/ everything works fine, it instantly add #!/ so the URL is http://localhost:5000/#!/ and page display as expected.
At the server side I have following code which should allow me to use my files
app.use(express.static(path.join(__dirname, 'public')));
Structure of my files is something like:
bookApp(folder)
server.js
public(folder)
index.html
app.js(ngRoute)
views(folder)
css(folder)
controllers(folder)
and my AngularJS routing is:
(function () {
'use strict';
angular
.module('app', [
'ngRoute'
])
.config(config);
function config ($routeProvider) {
$routeProvider
.when('/', {
controller: 'PostsCtrl',
templateUrl: 'views/posts.html'
})
.when('/register', {
controller: 'registerCtrl',
templateUrl: 'views/register.html'
})
.when('/login', {
controller: 'loginCtrl',
templateUrl: 'views/login.html'
})
.otherwise('/');
}
})();
The very first page (views/posts.html) load as expected but when I click
<li>Sign in</li>
the URL is http://localhost:5000/login not as like I thought http://localhost:5000/!#/login.
and it display:
Cannot GET /login
when I manually change URL to http://localhost:5000/#!/login it works fine.
How to fix this behavior?
The only solution I see is to get rid of <base> tag and in every link manually in href directive add !# before slash.
It looks like you are forgetting the ng-view directive: <div ng-view></div> which is the container for the content that is provided by your routing. Place this above your script if you have everything contained in one file.
You can also try:
<ng-view></ng-view>
<div class="ng-view"></div>
Is there any particular reason you are still using Angular 1? I know this isn't technically answering your question, but I would highly recommend that you start using the latest Angular. You can still keep legacy code but it will make a lot of what you are doing a lot cleaner and clear.
Anguilar 1.5.*
I can not get angular to use my template cache. I gave it a invalid path name on purpose so I would get html file not found. But instead it is not using template cache and just requesting the html files.
templates.js
angular.module("gulpTemplates", []).run(["$templateCache", function($templateCache) { $templateCache.put("aaaa/views/examples.html"
...
app.js
var gulpNewy =
angular
.module('gulpNewy', ['ngRoute', 'gulpTemplates'])
.config(function($routeProvider) {
$routeProvider
.when('/home', {
templateUrl: 'views/home.html',
controller: 'homeCtrl'
})
.when('/examples', {
templateUrl: 'views/examples.html'
})
.when('/screen-shots', {
templateUrl: 'views/screen-shots.html'
})
index.html
<div class="col-xs-12" ng-view></div>
What am I doing wrong?
Ok, I found the issue.
If you are using ng-view, templateCache will not work by default for you. This is because with ng-view you do not need to use ng-include. templateCache needs to be used with ng-include or $templateCache.get.
Regardless of $templateCache.get, ng-view will not look in templateCache.
When I use ngView and call a controller inside another one, this makes any process twice :
$routeProvider
.when('/', {
templateUrl: '/main.html',
controller: 'main'
})
.when('/user', {
templateUrl: '/user.html',
controller: 'user'
})
});
<body ng-controller="main">
<div ng-view><!--here is another controller --></div>
</body>
When using ngInclude there is not this problem. What is wrong with using ngView?
It looks like if you are using your main controller twice:
By referencing it in the template as ng-controller
In the routing config of the "/" route
Probably you want remove the ng-controller from your index page?
I had a working prototype of state views with hardcoded values, but when I tried to include a controller, it breaks the ui-sref links, and they don't seem to point to anything. I can remove the ng-controller attribute and they work again though, and display just fine.
I've also tried attaching ng-controller to a div in the template as well, foregoing a controller in index.html altogether, and while that doesn't break the link, I can't get any expressions in the template to work, and having a controller would be sub-optimal for the purposes of my app if I could avoid it.
What limitations of controllers and views am I misunderstanding?
index.html snippet
<div class="main" ng-controller="MainCtrl">
<a ui-sref="StateA">AAAAA</a>
<div ui-view></div>
</div>
app.js
var app = angular.module('app', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('StateA', {
url: "/a",
templateUrl: "views/a.html",
controller: "MainCtrl"
})
});
MainCtrl.js
app.controller("MainCtrl", [$scope, function($scope, paramGroups) {//empty controller//}]);
Apart from some of the syntax errors you have going on your fundamental problem is understanding of how ui-router works.
When you define something like:
.state('StateA', {
url: "/a",
templateUrl: "views/a.html",
controller: "MainCtrl"
})
It means, that when you go to route /a the partial a.html that will get rendered in your ui-view will get the scope for MainCtrl.
There's no point defining ng-controller='MainCtrl' on the element that is parent of ui-view because, ui-view will automatically get the scope for MainCtrl when the route resolves.
Route breaks when you declare that ng-controller because you are trying to nest same controller inside itself.
Developing a POC for an application.
Technologies being used : ASP.Net MVC4 and AngularJs.
Initialy while getting started i was using ngRoute and $routeProvider. The links used to redirect to the server to the required controller action and pages used to load in the div marked with ng-view directive. But my requirement was to laod multiple and nested views. So, had to switch to $stateProvider which supports such requirements.
Now i am facing the issue of the links not getting redirected. The "Project" link redirects but the "Opportunity" does not. My requirement is to load a view inside the first div and then one more view into AddOpportunityContainer
Following below is the code which i had written. Can anyone help me what wrong i have been doing. Had already spent quite an amount of tme on it.
Referred Libraries:
angular.js and angular-ui-router.js
The Code:
var GuidanceApp = angular.module('GuidanceApp', ['ui.router']);
var configFunction = function ($stateProvider, $httpProvider, $locationProvider) {
$stateProvider
.state('Projects', {
url: '/Projects',
templateUrl: 'Projects/Index'
})
.state('Opportunity', {
url: '/Opportunity',
templateUrl: '/Opportunity/Index',
views:{
"AddOportunityContainer": {
templateUrl: '/Opportunity/Create'
}
}
});
}
configFunction.$inject = ['$stateProvider', '$httpProvider', '$locationProvider'];
GuidanceApp.config(configFunction);
Following is the HTML of home page. And as you can see, the last div is marked with ui-view now instead of ng-view as in case of ngRoute and $routeProvider
<div>
<ul>
<li>Projects</li>
<li>Opportunity</li>
<li>Adjustments</li>
<li>Summary</li>
</ul>
</div>
<div ui-view></div>
Different partial view to be loaded on click of Opportunity link.
<h2>Opportunity-Index</h2>
<div ui-view="AddOportunityContainer"></div>
Your link for anchor element should be corrected as below without leading '/':
<li>Projects</li>