vendredi 25 mars 2016

Ember.js Render Only Once

So I have an Ember application that is very "stupid". It has a bunch of components for displaying various formats of data (tree, table, list, etc). It has 1 route, which is a complete wildcard. When you go to a url, Ember requests the same url resource from the server. If the resource is of type "table", it renders the "table" component and display the data. It does the same for any other type.

This works great. But the user needs a navigation bar. So Ember requests a list of all "pages" from the server and creates a navigation bar. The problem is, it rerenders the navigation bar every time you change pages.

How can I make the nav component request the data and load and then not be rerendered? The "Help" button on the navbar is displayed if the page has a help file otherwise it is not displayed. So the navbar is not exactly the same on every page. I can remove the help button from the navbar if it is easier. Thanks.

Route JS:

import Ember from 'ember';
import util from '../utils/utilities';

export default Ember.Route.extend({
  model() {
    var path = this.get('router.url');
    path = path.replace(/^\/|\/$/g, '');
    if (path === '') {
      path = 'Home';
    }

    var model = {
      navigation: null,
      page: null,
      api: path.replace(/\//g,"_")
    };

    util.httpGet('pages').then(function(navigation) {
      util.getPaths(path).map(function(path) {
        return util.setActive(navigation, path);
      });
      Ember.set(model, 'navigation', navigation);
    });

    util.httpGet('pages/' + model.api).then(
      function(page) {
        if (page.location[0] === 'special') {
          page.location = [];
        }
        Ember.set(model, 'page', page);
      },
      function(error) {
        var page = {
          title: error.status + ' Error',
          type: 'text-viewer',
          text: error.statusText
        };
        Ember.set(model, 'page', page);
      });

    return model;
  }
});

Route HBS:

{{navbar-component
  model=model
}}

<div class="page">
  <div class="pageHeader">
    {{#if model.page.location}}
      <ol class="breadcrumb">
        {{#each model.page.location as |item|}}
          <li>{{item}}</li>
        {{/each}}
        <h2 style="margin: 5px 0;">{{model.page.title}}</h2>
        <p>{{model.page.description}}</p>
      </ol>
    {{/if}}
  </div>
  <div class="pageContent">
    {{component model.page.type
      api=model.api
      page=model.page
    }}
  </div>
</div>

{{ember-notify messageStyle='bootstrap'}}

Nav JS:

import Ember from 'ember';
import util from '../utils/utilities';

export default Ember.Component.extend({
  model: null,
  showHelpModal: false,

  helpURL: Ember.computed('model', function() {
    return util.apiURL('pages/' + this.get('model').api + '/help');
  }),

  didInsertElement: function() {
    let _this = this;
    this.$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(event) {
      event.preventDefault();
      event.stopPropagation();
      _this.$(this).parent().siblings().removeClass('open');
      _this.$(this).parent().toggleClass('open');
    });
  },

  actions: {
    openHelp: function() {
      this.set('showHelpModal',true);
    }
  },
});

Nav HBS:

<nav class="navbar navbar-default navbar-fixed-top">
  <div class="container-fluid">

    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="">NexOSS</a>
    </div>

    <div class="collapse navbar-collapse">
      <ul class="nav navbar-nav">
        {{#each model.navigation as |item|}}
          <li class="{{if item.active 'active'}}">
            <a href="{{item.link}}" class="dropdown-toggle" data-toggle="dropdown">{{item.title}} <b class="caret"></b></a>
            <ul class="dropdown-menu multi-level">
              {{partial "navbar-dropdown"}}
            </ul>
          </li>
        {{/each}}
      </ul>
      <ul class="nav navbar-nav navbar-right">
        {{#if model.page.help}}
          <li><a href="#" {{action "openHelp"}}>Help</a></li>
        {{/if}}
        <li><a href="editor/{{model.page.link}}">Edit</a></li>
      </ul>
    </div>

  </div>
</nav>

<div id="helpModal">
  {{#bs-modal title="Help" open=showHelpModal body=false footer=false size="lg"}}
    {{#bs-modal-body}}
      {{pdf-viewer
        src=helpURL
        height=600
      }}
    {{/bs-modal-body}}
    {{#bs-modal-footer as |footer|}}
      {{#bs-button type="warning" icon="glyphicon glyphicon-remove" action=(action "close" target=footer)}}
        Close
      {{/bs-button}}
    {{/bs-modal-footer}}
  {{/bs-modal}}
</div>

For more details see repo if necessary but I tried to include everything needed. Repo: http://ift.tt/1RpZBza




Aucun commentaire:

Enregistrer un commentaire