Create the stack template

Each stack requires a Knockout template called stack.template to render the stack.

The stack.template file must reside in the /stack/<stack-type>/templates directory. Using the stack’s RegionViewModel object, the stack.template can access the sub-regions within the stack, via the regions observable array, and the widgets within each sub-region, via the widgets observable array for each sub-region.

This section provides some examples to show you how you might create a template that integrates Bootstrap UI controls with a stack’s content. The following code sample shows the stack template for a tabbed container:

<div class="tabbedContainer">
   <!--  RENDER Bootstrap tabs -->
   <ul class="nav nav-tabs" data-bind="attr: { id: 'tabbedNav-'+id()+'-pills'}">
      <!-- ko foreach: regions -->
        <li role="presentation" data-bind="css: {active: $index() === 0},
             attr: { id: 'tabbedNav-'+$parent.id()+'-pill-'+$index() }">
         <a data-toggle="tab" data-bind="
             attr: { 'href':'#tabbedContainer-' + $parent.id() + '-tab-' + $index()}">
             <span data-bind="text: displayName"></span>
         </a>
       </li>
     <!-- /ko -->
   </ul>
   <!—RENDER tabbed content -->   <div class="tab-content">
     <!-- ko foreach: regions -->
       <div role="tabpanel" class="stage tab-pane" data-bind="
             attr: { id: 'tabbedContainer-'+$parent.id()+'-tab-'+$index() },
             css: {active: $index() === 0}">
         <!—RENDER widgets in each tab -->
         <!-- ko foreach: widgets -->
           <div data-bind="
               template: {name: templateUrl(),templateSrc: templateSrc()}">
           </div>
         <!-- /ko -->
       </div>
     <!-- /ko -->
   </div>
 </div>

This template includes two ko foreach: regions bindings. The first iterates over the stack’s sub-regions and creates a tab for each sub-region. The second iterates over the sub-regions again and renders the contents of each tab. The content rendering is accomplished through a ko for each: widgets binding that iterates over the widgets contained in each sub-region.

Similarly, the following code excerpt shows the rendering of widgets in collapsible panels:

<!-- RENDER displayName from the stack -->
 <h2 data-bind="text:displayName"></h2>
 <div class="panel-group" id="accordion" role="tablist">
   <!-- RENDER stack sub-regions -->
   <!-- ko foreach: regions -->
     <div class="panel panel-default">
       <div class="panel-heading" role="tab" id="headingOne">
         <h4 class="panel-title">
           <a role="button" data-toggle="collapse" data-parent="#accordion"
               data-bind="attr: {
                      'href': '#accordionContainer-' + $parent.id() + '-tab-' + $index()},
                       text:displayName" aria-expanded="true" aria-controls="collapseOne>
          </a>
         </h4>
       </div>
       <div class="panel-collapse collapse" role="tabpanel"
          aria-labelledby="headingOne"
          data-bind="attr: {
             id: 'accordionContainer-'+$parent.id()+'-tab-'+$index() },
             css: {in: $index() === 0}">
       <div class="panel-body">
         <!-- RENDER widgets within each sub-region -->
         <!-- ko foreach: widgets -->
           <div data-bind="template: {
              name: templateUrl(),
              templateSrc: templateSrc()}">
           </div>
         <!-- /ko -->
       </div>
      </div>
     </div>
   <!-- /ko -->
 </div>

This code iterates over the sub-regions in the stack and renders a collapsible panel for each one. To define the content for each panel, the code iterates over the widgets in each sub-region and renders them using the template defined in the template data-bind.