angular-ui / ui-router

The de-facto solution to flexible routing with nested views in AngularJS
http://ui-router.github.io/
MIT License
13.56k stars 3.01k forks source link

ui-view in Jade file doesn't work #247

Closed robhicks closed 10 years ago

robhicks commented 10 years ago

This seems to follow the documentation for nested states.

http://plnkr.co/edit/fp09uXZ8xM2suQBwvXr7

EDIT: updated title for more clarity.

robhicks commented 10 years ago

Okay, I modified it to work.

But I still can't get route state changes for children routes to work. I'm using the same structure as the plunker I linked above. When the state is changed through a link, the html is fetched from the server but never gets injected into the dom at the ui-view div. Looking at the state in the dom, this is what I'm seeing:

{"params":{},"current":{"url":"/sys_users","templateUrl":"/system/partials/sys_users","controller":"SysUsersCtrl","name":"system.sys_users"},"transition":null}

When a change occurs:

{"params":{},"current":{"url":"/all_users","templateUrl":"/system/partials/all_users","name":"system.all_users"},"transition":null}

I noted in both that transition is null. Should it be?

timkindberg commented 10 years ago

Everything looks to be working for me. I can navigate around with the links and even type the url into the address bar and its all working as expected.

robhicks commented 10 years ago

The plunkr works but I can't get my app to work.

I need to know how to debug ui-router in a more complex scenario.

In the app that I am porting it to use ui-router (previously used angular router and ng-includes), I have the following main page:

header with navigation div(ui-view) footer

Then for each main route that is added to the first ui-view, I have several sub routes. Each of these sub route partials includes:

left column menu right column with a ui-view

I can't get these subroutes to work. Ui router fetches the partials for the right column ui-view but they are never added to the dom. I have looked at the directive that seems responsible for making the dom changes but it is beyond my skill level.

I would really like to use ui-router. Any help would be appreciated.

timkindberg commented 10 years ago

Can you post snippets of your actual code? Maybe the plunkr had some difference that we can detect that you are overlooking...

nateabele commented 10 years ago

I noted in both that transition is null. Should it be?

$state.transition is a promise that represents the transition taking place, and is only non-null pending completion of template-loading, resolves, animation, and state events.

The plunkr works but I can't get my app to work. I need to know how to debug ui-router in a more complex scenario.

We can't debug what we can't see, so I'm not sure how we're supposed to help you. All I can suggest is that you either pare down your existing app to fit in a plunkr which we can help you debug, or download the plunkr code and scale it up to your app, incrementally checking to see if anything breaks.

robhicks commented 10 years ago

Thanks for your input.

I finally made it back to this problem and have updated the plunkr to demonstrate what I'm seeing in my app.

http://plnkr.co/edit/fp09uXZ8xM2suQBwvXr7

Note that the Create Account and Logout links don't work. I believe they are mapped correctly but transitions are not made and no console errors occur.

Thanks for your help.

laurelnaiad commented 10 years ago

here is a modified plunker

Of note:

Key changes:

    $urlRouterProvider.otherwise("/auth/login");
    $stateProvider
        //Authentication Routes
        .state('auth', {url: "/auth", abstract: true, templateUrl: "auth.html", controller: 'AuthCtrl'})
        .state('auth.login', {url: "/login", templateUrl: "login.html", controller: 'LoginCtrl'})
        .state('auth.createAccount', {url: "/create_account", templateUrl: "create_account.html", controller: 'CreateAccountCtrl'})
                  <a href="#/auth/create_account">Create Account</a> 

and

              <a href="/auth/logout">Logout</a>
robhicks commented 10 years ago

Stu,

Thanks for your help!

robhicks commented 10 years ago

I have been trying to play with angular-ui-router from time to time. I think it is a great project and I would like to use it in a future.

However, while I can get a plunker to work, using standard hmtl, I develop using ExpressJS (Jade), NodeJS and Angular. I can't get angular-ui-router to work in my development environment.

To demonstrate the difference, I have used angular-seed and angular-express-seed as starting points. angular-express-seed is based upon angular-seed. It simply converts angular-seed to use a different file structure, server routing mechanism (Express) and support Jade.

Since angular-seed is html based, it is fairly easy to modify it to work with angular-ui-router. To demonstrate, I forked and modified it. It can be found at https://github.com/robhicks/angular-seed.

After modifying angular-seed to support angular-ui-router, I also forked and modified angular-express-seed. The modified version is at https://github.com/robhicks/angular-express-seed.

You'll note that I added children routes of both view1 and view2. They work with angular-seed and do not work with angular-express-seed. No errors are thrown. It simply doesn't work. I can't figure out why.

Any help would be appreciated.

Rob

laurelnaiad commented 10 years ago

@robhicks I use jade and express with ui-router all the time (although I convert from jade to html at build time). Nothing's wrong with ui-router in this regard. You might want to post something sort of like this on stackoverflow.... after you've exhausted the routes you have available (logging, debug breakpoints, etc).

EDIT: I guess more generally, the problem you're presenting is very general and asking a lot of people, especially since you can't get it into a plunker. With express, obviously you can't do so, but it has an issues list, too, and so does Jade! This just doesn't feel like a ui-router issue.

robhicks commented 10 years ago

Stu,

I can appreciate that it appears too broad.

The basic problem is that I can't get angular-ui-router to add children partials to the dom.

Since your last post, I have spent several hours trying to figure out what is happening. What I can say is this:

  1. the dom delivered by express and by file are identical in the browser.
  2. the javascript configuration of angular is identical.

config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise("/view1"); $stateProvider .state('view1', {url: "/view1", templateUrl: "partials/partial1", controller: 'MyCtrl1'}) .state('view1.subpartial1', {url: "/subpartial1", templateUrl: "partials/partial1subpartial1"}) .state('view1.subpartial2', {url: "/subpartial2", templateUrl: "partials/partial1subpartial2"}) .state('view2', {url: "/view2", templateUrl: "partials/partial2", controller: 'MyCtrl2'}) .state('view2.subpartial1', {url: "/subpartial1", templateUrl: "partials/partial2subpartial1"}) .state('view2.subpartial2', {url: "/subpartial2", templateUrl: "partials/partial2subpartial2"}); } ]);

  1. When a route is selected (via link or $state.go()), angular retrieves all partials including children partials.
  2. In the case of the expressjs app, angular-ui-router does not add children partials to the dom. More specifically, in line 95 of viewDirectives.js, the child partials (strings) are empty when passed to the render function.

I would ask questions on stackoverflow about jade and express but i am positive they are not the problem. As mentioned, the html delivered to the browser from expressjs and static file read are identical. Also, the loading order of all the javascript is identical.

I am more than willing to delve deeper into debugging if you can give me some guidance.

Rob

timkindberg commented 10 years ago

Using angular 1.1.5? Using html5mode?

nateabele commented 10 years ago

Well, I suppose by virtue of the fact that one scenario works and the other one doesn't, they are not, in fact, identical.

I assume you've verified (via Web Inspector or whatever), that Express is actually serving the templates correctly?

robhicks commented 10 years ago

I'm using Angular 1.0.7 in both cases.

I have not set html5mode.

Yes, I have verified that the child templates are identical, with the exception of speed. Express is about 1ms slower.

Can you identify in the code where the templates get added to locals.$template?

Note: I am using Jade and it is being compiled into html on the server as part of the response cycle.

laurelnaiad commented 10 years ago

If you've verified that the HTML and Javascript are identical then you've gotten far enough to have access to the HTML and Javascript, right?

If so, why not grab that HTML and Javascript, put it in a plunker and show that it fails (and wonder why the exact same HTML and Javascript isn't failing when it pops out of a different server)?

If, on the other hand, you haven't verified that the HTML and Javascript are identical, then you could do that, then do the above.

Bottom line: if you've got two servers producing identical files and the browser is behaving differently, I'd be surprised. If you've got two servers producing different files andthe browser is behaving differently, I wouldn't be surprised at all.

If you've got two servers producing slightly different files and one works and the other doesn't, it should not be very difficult to find the problem.

nateabele commented 10 years ago

This.

robhicks commented 10 years ago

I have done as suggested. I have created 2 plunkers, each taken from the server response, one from express and one from a static file server (using node). Here they are:

http://plnkr.co/edit/aIAD5QYQnmnwlLToiQqu?p=preview (Express) http://plnkr.co/edit/aIAD5QYQnmnwlLToiQqu?p=preview (Static file server)

I can't see the difference between them, but true to running them locally, the Express version doesn't work and the static file server version does work.

laurelnaiad commented 10 years ago

Looks like a paste error :) They both work so they must both be the static one...

robhicks commented 10 years ago

Argh!

http://plnkr.co/edit/EExJoCKXErwxID5gIcg4?p=preview (Express)

laurelnaiad commented 10 years ago

ui-router supports named views, so you need to be careful about the value of your ui-view attribute.

    <div ui-view="ui-view"></div>

needs to be

    <div ui-view></div>

So, in your jade file, just write:

div(ui-view)

and you should be back on track. That jade lets us do this without a fuss is nice for angular purposes, because there are other templating languages out there that aren't as easy on people who need lots of value-less attributes.

robhicks commented 10 years ago

Stu,

That's exactly what I am doing. I guess Jade is expanding it. What version of Jade are you using? I am using 0.31.2.

laurelnaiad commented 10 years ago

https://github.com/robhicks/angular-express-seed/blob/master/views/partials/partial1.jade

Not there :)

I'm on my tablet so can't check versions but shouldn't matter.

robhicks commented 10 years ago

Yes, it's in the file because I used the server response. I can't get Jade to not expand div(ui-view) to div(ui-view="ui-view"), at least I think it's Jade that's doing it.

I did try

in place of div(ui-view) and that's seems to work.

laurelnaiad commented 10 years ago

Look at your repo. Its in the jade.

laurelnaiad commented 10 years ago

Anyway on the ui-router subject, it feels to me like this should throw an error but I haven't thought through the ramifications.

(Edit) specifically, the error would be a concrete state where a view has been declared in dom but not defined in the active branch of the state tree.

On the jade front I usually just do

.ui-view

in these cases.

robhicks commented 10 years ago

I hadn't updated the repo since I tried to verify that both the angular-express-seed and angular-seed files were the same.

I just pushed it. But it is still rendering to &#60div ui-view="ui-view"&#62 unless I explicitly insert &#60div ui-view&#62 in the Jade file

robhicks commented 10 years ago

Anyway, thanks for your help. What a horrendous way to get bit by a preprocessor.

laurelnaiad commented 10 years ago

Ill check my jade version. Pretty sure its not doing that

laurelnaiad commented 10 years ago

You can use three backticks to escape code in markdown btw

laurelnaiad commented 10 years ago

Ok, checked my code. I am using "naked" ui-view attribute in Jade and the code produces a "naked" ui-view in HTML.

One difference could be that I'm using grunt-contrib-jade to do the preprocessing at build time with these, perhaps relevant, options:

                compileDebug: false,
                pretty: true,

npm shows:

└─┬ grunt-contrib-jade@0.8.0
  └── jade@0.34.1 

We should probably take this to another venue if we want to talk about Jade any more.

robhicks commented 10 years ago

Thanks Stu!

robhicks commented 10 years ago

Use HTML in your jade file.

Jade won't expand it.

On Saturday, December 7, 2013, Liviu Macsen wrote:

Hy, I have same issue. Why ui.router care about ui-view vs. ui-view="ui-view"? We can't work around this limitation?

— Reply to this email directly or view it on GitHubhttps://github.com/angular-ui/ui-router/issues/247#issuecomment-30066018 .

secretfader commented 10 years ago

The current build of Jade (as of this comment) requires you to pass { doctype: 'html' } when compiling, or it will automatically expand attributes to include the value as well. Just a little FYI for the future folks who find and encounter this.

chuckweinberger commented 9 years ago

I just got hit by this problem. Glad to see the workaround.
Here is a similar question posted on StackOverflow: http://stackoverflow.com/questions/23056224/grunt-jade-compiler-filling-out-empty-attributes

chasevida commented 9 years ago

Thanks this got me as well. Using .ui-view as mentioned by Stu was the easiest /quickest solution for me.

jseminck commented 9 years ago

Issue still exists and just ran into it. Spent quite some time trying to figure out what was wrong until I found this thread. Using .ui-view still works.

deneboulton commented 9 years ago

This has just bit me too, wasted a couple of hours on it until I noticed the diff in the html that was generated :<

leandroz commented 8 years ago

I solved it adding doctype html

hanaarena commented 8 years ago

I defined the sub router in express router so solve the render jade template problem.

like below:

$stateProvider
  .state('gallery-index', {
     url: '/index',
     templateUrl:  'temp/index'
  })
  .state('gallery-info', {
     url: '/info',
     templateUrl: 'temp/info'
  });

 $urlRouterProvider.otherwise("/index");

in express router file:

router.get('/temp/index', function(req, res) {
  res.render('temp/index')
});

router.get('/temp/info', function(req, res) {
  res.render('temp/info')
});

hope that help others people...

CJYate commented 8 years ago

@hanaarena are your template files called "temp/index.jade"? There's no file extension on the templateUrl in your example; when I've tried this I have to explicitly set templateUrl: "path/filename.pug" (although it still doesn't work!). Have you got some setting in the main app that interprets the filename?

Also I don't like having to set a route explicitly for every route. It's not very DRY. I wonder whether there's a way to use a wild-card...?

hanaarena commented 8 years ago

@CJBrew I have set jade as my app default view engine so I can just use res.render(viewName) and express know what view file I want.uh..I have not use templateUrl yet and not found in expressjs.com api doc :(

yeah..jade work with ui-router is confused for me sometime. also never use wild-card