3

I want to be able to use two common components through out my app in all the states basically the header and the sidebar. I have read through the docs but i must have missed something. How can i reuse the header and sidebar in the states

  $stateProvider
    .state('home', {
        url: '/leads:id',
        views: {
          'details': {
              templateUrl: '../views/details.html',
              controllerProvider: function($stateParams) {
                  if($stateParams.id) {
                      return 'CompanyDetails as companydetails';
                  }else {
                      return 'NewCompanyDetailsController as companydetails';
                  }

              }
          },
          'sidebar': {
              templateUrl: '../views/sidebar.html'
            },
          'header': {
              templateUrl: '../views/header.html',
              controller: 'HeaderCtrl as header'
           },
          'vehicledetails': {
              templateUrl: '../views/vehicledetails.html',
              controller: 'VehicleDetailsController as vehicledetails'
          },
          'comments': {
              templateUrl: '../views/comments.html',
              controller: 'CommentsController as comments'
          },
          'saveupdate': {
              templateUrl: '../views/saveupdate.html',
              controller: 'SaveUpdateDetailsController as saveupdate'
          }
        }

    });

I want to create another state called 'data' for example which reuses the header and sidebar. How can I acheive this without requiring to write down all the the components again ?

I did a bit of reading and now, I have an updated state provider that displays the common header and sidebar on all routes but the data inside the actual container is not being displayed at all. Here is my updated code

$stateProvider
        .state('home', {
            abstract: true,
            views: {
              'header': {
                  templateUrl: '../views/header.html',
                  controller: 'HeaderCtrl as header'
              },
              'sidebar': {
                  templateUrl: '../views/sidebar.html'
               }
             },
             resolve: {
                  somedata: function(){return {}}
              }

        })
        .state('home.login', {
            url: '/',
            views: {
               'login@home': {
                          templateUrl: '../views/login.html'
                        }
                }
        })
        .state('home.leads', {
            url: '/leads:id',
            views: {
              'details@home': {
                  templateUrl: '../views/details.html',
                  controllerProvider: function($stateParams) {
                      if($stateParams.id) {
                          return 'CompanyDetails as companydetails';
                      }else {
                          return 'NewCompanyDetailsController as companydetails';
                      }
                  }
              },
              'vehicledetails@home': {
                  templateUrl: '../views/vehicledetails.html',
                  controller: 'VehicleDetailsController as vehicledetails'
              },
              'comments@home': {
                  templateUrl: '../views/comments.html',
                  controller: 'CommentsController as comments'
              },
              'saveupdate@home': {
                  templateUrl: '../views/saveupdate.html',
                  controller: 'SaveUpdateDetailsController as saveupdate'
               }
            }

        });

and my index.html

<body ng-app="MyApp">
    <div id="page-wrapper" ng-class="{'open': toggle}" ng-cloak class="open" ng-controller="SlideCtrl">
        <div id="sidebar-wrapper" ui-view="sidebar">
        </div>
        <div id="content-wrapper">
            <div class="page-content">
                    <!-- Header Bar -->
                    <div class="row header" ui-view="header">
                    </div>
                    <!-- Header Bar -->
                    <div ui-view="login"></div>
                    <div ui-view="details"  class="panel panel-default col-xs-11" ></div>
                    <div ui-view="vehicledetails"  class="panel panel-default col-xs-11" ></div>
                    <div ui-view="comments"  class="panel panel-default col-xs-11" ></div>
                    <div ui-view="saveupdate"></div>
            </div>
        </div>
    </div>
    <script src="js/main.js"></script>
</body>
Bazinga777
  • 5,140
  • 13
  • 53
  • 92
  • Have you already considered the parent state? I would vote for that. It could be few super root states .. abstract not effecting url.. but providing some same stuff to similar sub-state families... e.g. [here](http://stackoverflow.com/a/28826126/1679310) or [there](http://stackoverflow.com/a/29561066/1679310) – Radim Köhler May 29 '15 at 07:03
  • can you show the controller where you want to display that data? – coma May 29 '15 at 08:49
  • The problem is that even the template inside the login.html doesn't show up. So i am guessing I am still missing something there – Bazinga777 May 29 '15 at 08:51

2 Answers2

0

I actually managed to get this working now using this link https://stackoverflow.com/a/28826126/1679310

I will explain my answer since I couldnt understand how it worked before I did it on my own. You need this to be present for the child states to plug into it. https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#scope-inheritance-by-view-hierarchy-only

Basically you create a main ng-view inside the index.html that serves as the container to your others partials then you basically contain all the child ui-views inside another layout that will serve as the parent to all the states.

So in essence your structure is something like this

<body ng-app="MyApp">
<div id="page-wrapper" ng-class="{'open': toggle}" ng-cloak class="open" ng-controller="SlideCtrl">
   <div ng-view>
   </div>
</div>
<script src="js/main.js"></script>

and another file that has the layouts

 <div id="sidebar-wrapper" ui-view="sidebar">
    </div>
    <div id="content-wrapper">
        <div class="page-content">
                <!-- Header Bar -->
                <div class="row header" ui-view="header">
                </div>
                <!-- Header Bar -->
                <div ui-view="login"></div>
                <div ui-view="details"  class="panel panel-default col-xs-11" ></div>
                <div ui-view="vehicledetails"  class="panel panel-default col-xs-11" ></div>
                <div ui-view="comments"  class="panel panel-default col-xs-11" ></div>
                <div ui-view="saveupdate"></div>
        </div>
    </div>

Then you basically follow the pattern here

  $stateProvider
    .state('home', {
        abstract: true,
        views: {
            '@': {
                templateUrl: '../views/layouts.html'
                },
            'header@home': {
                templateUrl: '../views/header.html',
                controller: 'HeaderCtrl as header'
            },
            'sidebar@home': {
                templateUrl: '../views/sidebar.html'
             }
         }
    })
    .state('home.login', {
        url: '/',
        views: {
           'login@home': {
                      templateUrl: '../views/login.html'
                    }
            }
    })

For all your states. This worked for me and I am pretty sure that is the right way to do so.

Community
  • 1
  • 1
Bazinga777
  • 5,140
  • 13
  • 53
  • 92
0

There's a better way:

HTML part

Index file (index.html):

<html ng-app="app">

<head></head>

<body ui-view></body>

</html>

Base file (layout.html)

<header>
    Here's the header part
</header>
<aside>
    Here's the sidebar part
</aside>
<main ui-view>
    And here is where the app will be ran when you go to a state like "app.home"
</main>

States:

var states = {
    'app': {
        templateUrl: 'app/layout.html',
        controller: 'LayoutController as layout'
    },

    'app.home': {
        templateUrl: 'app/home.html',
        controller: 'HomeController as home'
    }
};

angular.forEach(states, function(config, name) {
    $stateProvider.state(name, config);
});
Darlan Alves
  • 503
  • 5
  • 13
  • The reason why i organized it in that way was because the header is dynamic and it needed to have it's own controller for the sake of better code oranigzation. – Bazinga777 Jun 01 '15 at 07:37
  • That's not a problem. inside layout.html you can have smaller chunks of code with different scopes as well. You can even have a header.html file added via ng-include and with a custom controller through ng-controller. – Darlan Alves Jun 01 '15 at 23:23