AngularJS UI-Router multiple pages

22,271

Solution 1

As you expected, it is not so difficult, there is a plunker.

The trick is to move the common stuff for all views inside of the specific template e.g. common.html and create the abstract state. Other words, the index.html will remain clean:

<body>

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

And its previous content (content of the index.html) would be moved to common.html. The state definition could look like this:

$stateProvider
  .state('common', {
    templateUrl: 'tpl.common.html',
    abstract: true,
  })
  .state('dashboard', {
    url: '/dashboard',
    parent: 'common',
    ...
  })
  .state('crm', { 
    url: '/crm',
    parent: 'common',
    ...
  })
  .state('login', {
    url: '/login',
    templateUrl: 'tpl.login.html',
  });

$urlRouterProvider.otherwise('/crm');

What is interesting (I'd say) is that we introduced abstract state, without url. So the all current logic will remain, just the abstract will play role of a layout template.

Check more here: example

Solution 2

I also had this problem before, refer to THIS if you're interested. In that link, I also handled returnUrl and 401 http status code in case the user is not authorized.

In your case, I suggest you design your application like this:

index.html:

<!DOCTYPE html>
<html data-ng-app="npAdmin">
<head>
...
</head>
<body data-ui-view>

</body>
...
</html>

main.html:

  <header>
      <data-user-profile class="user-profile"></data-user-profile>
  </header>

  <section class="content-wrapper">
      <aside data-main-menu></aside>
      <div class="main-content" data-ui-view></div>
  </section>

  <footer class="row"></footer>

login.html

(include your html for this view)

App.js:

var app = angular.module('npAdmin', ['ui.router']);

app.config(['$httpProvider', '$stateProvider', '$urlRouterProvider', function($httpProvider, $stateProvider, $urlRouterProvider) {

    $stateProvider
    .state('login',{
       url:"/login",
       templateUrl: '/app/login.html',
       controller: 'LoginCtrl'
     })
    .state('main',function(){
       url:"/",
       templateUrl: '/app/main.html',
       controller: 'MainCtrl',
       abstract: true //you could use abstract state or not depending on your design 
    })
    .state('main.dashboard', { //inherit from your main
        url: '/dashboard',
        templateUrl: '/app/dashboard/dashboard.html',
        controller: 'DashboardCtrl'
    })
    .state('main.crm', { //inherit from your main
        url: '/crm',
        templateUrl: '/app/crm/crm.html',
        controller: 'CrmCtrl'
    })

Explanation:

As angular is SPA, your index.html should cover all views of your application. There are multiple ways to ensure that. In this example, the login is also a state in your application that is separated from your main. By utilizing state inheritance in angular router, you could further have child states in your main which are dashboard and crm in this case.

Share:
22,271
swolfish
Author by

swolfish

Updated on July 31, 2022

Comments

  • swolfish
    swolfish almost 2 years

    As Angular is SPA that's terrific, but what if I need some other page not related to index.html, how is realised by UI-Router states with different ui-views?

    For example, I have index.html:

    <!DOCTYPE html>
    <html data-ng-app="npAdmin">
    <head>
    ...
    </head>
    <body>
       <header>
          <data-user-profile class="user-profile"></data-user-profile>
      </header>
    
      <section class="content-wrapper">
          <aside data-main-menu></aside>
          <div class="main-content" data-ui-view></div>
      </section>
    
      <footer class="row"></footer>
    ...
    </body>
    </html>
    

    app.js:

    var app = angular.module('npAdmin', ['ui.router']);
    
    app.config(['$httpProvider', '$stateProvider', '$urlRouterProvider', function($httpProvider, $stateProvider, $urlRouterProvider) {
    
        $stateProvider
        .state('dashboard', {
            url: '/dashboard',
            templateUrl: '/app/dashboard/dashboard.html',
            controller: 'DashboardCtrl'
        })
        .state('crm', {
            url: '/crm',
            templateUrl: '/app/crm/crm.html',
            controller: 'CrmCtrl'
        })
    ...
    

    Now I need login.html which is totally different from index.html (don't need index's header, footer, sidebar) but config stateProvider only looks to index.html ui-view and changes content to it by states. How to combine login.html?

    It seems not that hard, but I don't get it.

  • Ed B
    Ed B almost 10 years
    In addition to the above, if you're going to have a separate Login page make sure you implement an Authentication Check service. This way, if the user isn't logged in they'll be re-directed to the login page. See this video for a basic implementation.
  • Khanh TO
    Khanh TO almost 10 years
    @Ed B: Sure, because that's not included in the question. And we will check that for all requests, not only for login page.
  • swolfish
    swolfish almost 10 years
    Thanks a lot, very exhaustive answer but with some minor mistakes. Radim's solution with abstract state seems as perfect solution.
  • swolfish
    swolfish almost 10 years
    Now I know how to use abstract state property. Thank you.
  • Khanh TO
    Khanh TO almost 10 years
    @swolfish: I did not test the code, I just gave the idea. And as I said, there are multiple ways to do that. It's just a matter of design.
  • Radim Köhler
    Radim Köhler almost 10 years
    Great to see that;) ui-router is incredible and really powerful... Enjoy it ;)
  • Radim Köhler
    Radim Köhler about 9 years
    @KillABug I would suggest, issue question. Show more details. You will surelly get an answer. Or let me know I can check it as well. Comment is not suitable for investigating why is your code not working... Does it make sense?
  • Radim Köhler
    Radim Köhler about 9 years
    @KillABug If I will know, I will help. But your question will target more guys than must me, so you will get answer... I am sure
  • KillABug
    KillABug about 9 years