0

Using angular 1.6, here are the components I need to have:

+-------------------+
|side|              | 
|bar |              |
|... |     view     |
|... |              |
|... |              |
+-------------------+
  • side bar: placed on left. using ng-repeat and updates dynamically.
  • view: rest of the app. template is static but contents changes when click on side bar.

when the user clicks on each list <li> of side bar, it updates the view. only view content/model will change. not the html template.

Important: I just don't want to write a code in <body>. Would like to have sidebar in one html file and view in another associated with their controllers and render the whole app through ng-view in <body>.

The side bar updates dynamically so that I cannot specify state in config() for each.

any other standard architecture is appreciated.

DragonKnight
  • 1,740
  • 2
  • 22
  • 35
  • 1
    This is really too broad for Stack Overflow. What have you tried so far? – David L Apr 18 '17 at 18:26
  • @DavidL I just need a guidance about architecture. haven't started yet because I dont want to write code in body. I am removing progress bar part. – DragonKnight Apr 18 '17 at 18:30
  • 1
    Understandable, but that isn't what Stack Overflow is for. it's for concrete questions. This is subject to opinion (as architecture always is) and is too broad to provide a ***concrete*** answer. – David L Apr 18 '17 at 18:32
  • @DavidL Just a simple verbal answer works. I can write the side bar with ng-repeat and update the view through ng-view but I am assuming its not a good idea to write detail code in body. I thing it should be in another html file to be rendered via ng-view. correct me if i am wrong. – DragonKnight Apr 18 '17 at 18:37

1 Answers1

1

As mentioned in the comments, there are multiple architecture and framework choices that can be made to implement the type of templating you're looking for. I'll provide a basic example based on something I've used in the past with angular, using ui-router and child/nested views.

Lets say you have an index.html like:

<body>
    <div ui-view="header" class="header"></div>
    <div ui-view="main" class="main"></div>
    <div ui-view="footer" class="footer"></div>
</body>

The index page just has the layout for the most high level view, namely header, content and footer. If you have no need for header and footer, you can just ignore/remove it. Now the layout your are looking for, with a side bar on the left and the content on the right, will be placed within the main view. To do this lets declare another page which will define this structure, call it landing.html (use bootstrap for simplicity):

<div class="container-fluid">
  <div class="row landingContainer">
    <div class="col-md-2 col-sm-4 col-xs-3 sidebarSection">
      <div class="row item" ng-click="landing.changePage('content1')">
        <span>Show Content 1</span>
      </div>
      <div class="row item" ng-click="landing.changePage('content2')">
        <span>Show Content 2</span>
      </div>
      <div class="row item" ng-click="landing.changePage('content3')">
        <span>Show Content 3</span>
      </div>
    </div> 
    <div class="col-md-10 col-sm-8 col-xs-9 contentSection">
      <div ui-view="content"></div>
    </div> 
  </div>
</div>

You can think of this page as the root of your layout. The page is split into a left and right section using bootstrap columns. The left side contains the listing of all your content views. You can use li, i just prefer divs. The right side will be where the dynamic part of the page is, where the content will change based on the item selected in the side bar. Each component view is a child of the landing page, it inherits all the features of the parent and then adds its own content into the ui-view, similar to how landing.html added its content into the main ui-view. Now lets take a look at the ui-router config that makes all this work.

function routerConfig($stateProvider, $urlRouterProvider) {
    $stateProvider
      .state('landing', {
        url: '/landing',
        views: {
         'header': {
            templateUrl: 'app/components/header/headerPrivate.html',
            controller: 'HeaderController',
            controllerAs: 'header'
          },
          'main': {
            templateUrl: 'app/landing/landing.html',
            controller: 'LandingController',
            controllerAs: 'dashboard'
          },
          'footer': {
            templateUrl: 'app/components/footer/footer.html',
            controller: 'FooterController',
            controllerAs: 'footer'
          }
        }
      })
      .state('landing.content1', {
        url: '/content1',
        views: {
         'content': {
            templateUrl: 'app/content1/content1.html',
            controller: 'Content1Controller',
            controllerAs: 'content1'
          }
        }
      })
      .state('landing.content2', {
        url: '/content2',
        views: {
         'content': {
            templateUrl: 'app/content2/content2.html',
            controller: 'Content2Controller',
            controllerAs: 'content2'
          }
        }
      })
      .state('landing.content3', {
        url: '/content3',
        views: {
         'content': {
            templateUrl: 'app/content3/content3.html',
            controller: 'Content3Controller',
            controllerAs: 'content3'
          }
        }
      })
    $urlRouterProvider.otherwise('/');
}

Here you'll notice that the landing page route defines the configuration for the 3 main views, header, main and footer. The url path will be /landing. Then content1, content2 and content3 are defined as children by nesting them within landing using the dot notation: landing.content1. The url paths for each child will then resolve to /landing/content1, /landing/content2, landing/content3. So now anytime you navigate to those locations only the content for that specific child will be nested within the landing pages "content" ui-view and the remaining layout of the page stays the same.

For the sake of completion, this is how the landing controller might look:

function LandingController($state) {
    var vm = this;

    vm.changePage = function(page){
        $state.transitionTo('landing.'+page, null, null);
    }    
}
Sasang
  • 1,261
  • 9
  • 10
  • That is a very good explanation. Thank you. What this is not covering is that the side bar populates with ng-repeat and it is dynamic. I dont know how to set dynamic state in config() for that which I dont think it is recommended in angular. do you have any solution for that too? thanks. :) – DragonKnight Apr 18 '17 at 21:39
  • 1
    How does the dynamic list in the side bar impact the content view? Are you fetching html dynamically also, to display in the content area? – Sasang Apr 18 '17 at 21:41
  • each item of the side bar has an ID and some summery info. when you click on that it should update the view based on that item. The view includes a lot more info including some graphs, other tables, etc. And nothing is static. Basically on each click on side bar on the left I have to make a new call. Since the view is dynamic I cannot provide state for each in config(). So the answer is yes i think. – DragonKnight Apr 18 '17 at 21:54
  • 1
    So if you have dynamic data for the view, thats fine you can display all that using a single view as needed using angular directives. Provided the multiple views maintains some similar structure between them. If however everything is different and the layout itself changes dynamically and drastically, where you depend on some backend to provide the html, then you can in fact dynamically register ui router states at runtime. Take a look at this answer: http://stackoverflow.com/a/25872852/7852085 – Sasang Apr 18 '17 at 22:11
  • not actually, the problem is states for side bar in which each component has many detail itself and html template for that is also more complex than creating directive for that. its not just a simple list. – DragonKnight Apr 18 '17 at 23:07