Skip to content

Instantly share code, notes, and snippets.

@rodrigomf24
Last active March 19, 2018 06:04
Show Gist options
  • Save rodrigomf24/4db311224010a73a8c434927bc4af005 to your computer and use it in GitHub Desktop.
Save rodrigomf24/4db311224010a73a8c434927bc4af005 to your computer and use it in GitHub Desktop.
navigation-components-development

Level One Component

There are two ways of using the level one component fleet navigations, you can feed the fleet navigations context throught the model/service approach or through the Ember DS models.

Example using the Ember DS Models:

{{#level-one-navigation}}
  {{#block-slot 'app-name'}}
    {{level-one-navigation/app-name
	    appName='Health Advisor'
	    icon='polymer'
	}}
  {{/block-slot}}
  {{#block-slot 'fleet-navigations' as |levelOneNavigation|}}
    {{levelOneNavigation.fleetNavigation
      model="site"
      placeholder="Select Site"
      selectedContext=levelOneNavigation.availableContext.site
      clearOnIndex=(array 'plant' 'unit')
    }}
    {{levelOneNavigation.fleetNavigation
      model="plant"
      placeholder="Select Plant"
      disabled=(not levelOneNavigation.availableContext.site)
      selectedContext=levelOneNavigation.availableContext.plant
      optionsFilterContext=(array levelOneNavigation.availableContext.site)
      routeParams=(array levelOneNavigation.availableContext.site.value)
      clearOnIndex=(array 'unit')
    }}
    {{levelOneNavigation.fleetNavigation
      model="unit"
      placeholder="Select Unit"
      disabled=(not levelOneNavigation.availableContext.plant)
      selectedContext=levelOneNavigation.availableContext.unit
      routeParams=(array levelOneNavigation.availableContext.site.value levelOneNavigation.availableContext.plant.value)
    }}
  {{/block-slot}}
{{/level-one-navigation}}

The above example will require the following to be configured:

  • Each model used in a fleet navigation needs to map to an existing Ember DS model, the following attributes need to be added to each model:
export default DS.Model.extend({
	// This route will be the one used after an option is selected
	onSelectedRoutePath:  'auth.sites.site',
	// This route will be the one used for the "View All" button
	indexPage:  'auth.sites',
	// This will tell the base model to use the entire object as value of the options
	useObjectForRoute: true,
});

Example using the model/service approach

{{#level-one-navigation}}
  {{#block-slot 'app-name' as |levelOneNavigation|}}
    {{levelOneNavigation.appName
      appName='Dummy App'
      icon='polymer'
    }}
  {{/block-slot}}
  {{#block-slot 'fleet-navigations' as |levelOneNavigation|}}
    {{levelOneNavigation.fleetNavigation
      service="customer"
      placeholder="Select Customer"
      selectedContext=levelOneNavigation.availableContext.customer
      clearOnIndex=(array 'site' 'unit')
    }}
    {{levelOneNavigation.fleetNavigation
      service="site"
      placeholder="Select Site"
      disabled=(not levelOneNavigation.availableContext.customer)
      selectedContext=levelOneNavigation.availableContext.site
      clearOnIndex=(array 'unit')
      optionsFilterContext=(array levelOneNavigation.availableContext.customer)
      routeParams=(array levelOneNavigation.availableContext.customer.value)
    }}
    {{levelOneNavigation.fleetNavigation
      service="unit"
      placeholder="Select Unit"
      disabled=(not levelOneNavigation.availableContext.site)
      selectedContext=levelOneNavigation.availableContext.unit
      optionsFilterContext=(array levelOneNavigation.availableContext.customer levelOneNavigation.availableContext.site)
      routeParams=(array levelOneNavigation.availableContext.customer.value levelOneNavigation.availableContext.site.value)
    }}
  {{/block-slot}}
{{/level-one-navigation}}

The example above will require the following to be configured:

  • Each service attribute needs to map to an existing service in the application, each service needs to have the following structure:
// All model services needs to extend from the BaseModelService
import BaseModelService from 'siemens-ember-shared/services/level-one-navigation/base-model';

export default BaseModelService.extend({
  indexPage: 'customer',
  onSelectedRoutePath: 'site',
  contextName: 'customer',
  getList() {
	// You can use anything in here, you just have to return a promise that resolves to an array of options
    return new Promise((resolve) => {
      const options = [1,2,3,4,5].map((value) => {
        return {
          label: `Customer ${value}`,
          value
        };
      });
      resolve(options);
    });
  }
});

Keep in mind that if your page refreshes the SPN service is cleared out, if the selected context is used in your route segments from your route class you will have to define the context back, for example:

...
// Get the customer object from the parent route
const customer = this.modelFor('customers.show');
const spnCustomer = this.get('siemensPortalNavigation').getContext(
  'customer',
  'levelOneContext'
);
// You evaluate if the customer is defined and if the spn context has a value assigned for customer (on page refresh it will never have a value)
if (customer &&  !spnCustomer) {
  this.get('siemensPortalNavigation').setContext(
    'customer',
    {value: customer.get('id'), label: customer.get('name')},
    'levelOneContext'
  );
}

Level Two Component

Example:

<!-- application.hbs -->
<div class="d-flex flex-row w-100">
	{{#if  levelTwoNavigationEnabled}}
		{{outlet  'level-two-navigation'}}
	{{/if}}
	<div class={{concat (if  levelTwoNavigationEnabled  'w-75'  'w-100') ' d-flex flex-column p-3'}}>
		{{outlet}}
	</div>
</div>

In the example above the levelTwoNavigationEnabled flag is injected through the LevelTwoNavigation Mixin, it can be imported from the siemens-ember-shared addon like this:

import LevelTwoNavigation from  'siemens-ember-shared/mixins/level-two-navigation';

export default  Ember.Route.extend(LevelTwoNavigation, {
	rootRouteName:  'application',
});

Inject this mixin on all routes that make use of the level two navigation, if you have a route that doesn't make use of this navigation component, you will still have to inject it but you will need to define the following property disableLevelTwoNavigation in your Route class like in the example bellow:

import LevelTwoNavigation from  'siemens-ember-shared/mixins/level-two-navigation';

export default  Ember.Route.extend(LevelTwoNavigation, {
	rootRouteName:  'application',
	disableLevelTwoNavigation: true
});

Each route defines its own template for the content that will be shown in the level two navigation, the LevelTwoNavigation mixin will search for a folder inside your routes folder matching the name of the route that is implementing it and inside the folder it will search for a navigation-items.hbs file, the contents of this file should look the following:

{{#level-two-navigation as |levelTwoNavigation|}}
  {{#levelTwoNavigation.navigationItem 
    'overview' iconName="settings"
  }}
    Overview
  {{/levelTwoNavigation.navigationItem}}
  {{#levelTwoNavigation.parentNavigationItem title="My Health" iconName="local-hospital"}}
    {{#levelTwoNavigation.navigationItem 'my-health.show.unit.index' isChild=true}}
      Units
    {{/levelTwoNavigation.navigationItem}}
  {{/levelTwoNavigation.parentNavigationItem}}
{{/level-two-navigation}}

In the example above you can see the use case of a nested menu where "My Health" opens to "Units", you can use the same approach for n-th amount of navigation items.

From the levelTwoNavigation you can access the SPN context fron the availableContext property.

Level Three Component

The level three navigation is stright forward, you just need to drop this in your handlebars template:

{{level-three-navigation}}

It will do the rest for you, one thing to note is that it follows the Ember documentation routing structure example, that makes use of index and show routes:

./my_route
./my_route/index.js
./my_route/show.js
./my_route/show
./my_route/show/child_route
./my_route/show/child_route/index.js
./my_route/show/child_route/show.js
./my_route/show/child_route/show
./my_route/show/child_route/show/child_1.js
./my_route/show/child_route/show/child_2.js

This approach provides a route pattern and with this we can generate breadcrumbs dynamically. If your application doesn't follow such practice you will have to refactor your routes structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment