Search code examples
javascriptcssmeteormeteor-blazemeteor-helper

How can I programatically show/hide a button that is part of the body template in Meteor?


I am using the Template.dynamic feature in a Meteor app. The initial template displayed is the chief one, and often the user will want to go immediately back to it from whatever template they have moved to. I want to make this ability to move back to that initial/chief template very obvious with a "go back" button.

Let me first outline how I swap out the templates:

  Template.mnuScheduler.events({
    "click #mniOpenExisting": function () {
      Session.set('curTemplate', 'scheduleOpenExisting');
    },

  Template.body.helpers({
    currentTemplate: function () {
      return Session.get('curTemplate');
    }
  });

  <div class="container">
    {{> mnuScheduler}}
    {{> Template.dynamic template=currentTemplate}}

I don't want the 'go back' button to be visible on the main template, because there is no need to go back to itself.

I could put such a 'go back' button at the bottom of each template, and then show it in each templates OnRendered event:

$('btnBack').removeClass('hide');

...where the CSS class is:

.hide {
  visibility: hidden;
  display: none;
}

...but there's got to be a way to implement the DRY principle here, rather than duplicating a 'go back' button on each template.

At first I thought that if I were to put the "back button" in the body like so:

main.html:

<body>

  <div class="container">
    {{> mnuScheduler}}
    {{> Template.dynamic template=currentTemplate}}    
    {{> backButton}}
  </div>

</body>

<template name="backButton">    
    <div>
        <button class="hide" type="button" id="btnGoBack" name="btnGoBack">Go Back</button> 
    </div>
</template>

...I could add code like this where the template is swapped out:

  Template.mnuScheduler.events({
    "click #mniOpenExisting": function () {
      Session.set('curTemplate', 'scheduleOpenExisting');
      $('btnBack').removeClass('hide');      
    },

...but 'btnBack' is not part of the 'mnuScheduler' template, and so 'btnBack' is unrecognized there.

If I put the back button in only one place (the 'body' template), can I reference it from another template's events? Is there a way to do something like this:

  Template.mnuScheduler.events({
    "click #mniOpenExisting": function () {
      Session.set('curTemplate', 'scheduleOpenExisting');
      Template.body.$('btnBack').addClass('hide');      
    },

?

UPDATE

I guess I'm doing something wrong in trying to implement Michael Floyd's suggestion.

The chief template (the one that displays intially) is "tblScheduler". Here's what I added:

// main.html:

<body>
  <div class="container">
    {{> mnuScheduler}}
    {{> Template.dynamic template=currentTemplate}}
    {{#unless isChiefTemplate}}
      <button type="button" id="btnDisplayScheduleTemplate" name="btnDisplayScheduleTemplate">Display Schedule</button>
    {{/unless}}
    {{> footer}}
  </div>

</body>

// main.js:

Template.tblScheduler.helpers({
  jobLocations: function() {
    return JobLocations.find({}, {sort: {jl_jobloc: 1}, fields: {jl_jobloc: 1}});
  },
  isChiefTemplate: function() {
    return true;
  },
  . . .

Template.body.events({
  'click #btnDisplayScheduleTemplate': function() {
    Session.set('curTemplate', 'tblScheduler');
  }  
}); // Template.body.events({

But the "Display Schedule" button is still visible on the chief template (tblScheduler).

Note: The "body" event works - clicking the button does switch from any other template to the chief template (tblScheduler); it's just that that button is visible even on the chief template still that is the problem.


Solution

  • Defining the helper in Template.tblScheduler.helpers doesn't work, as you call it from the body template:

    Either create a global template like this:

    Template.registerHelper('isChiefTemplate', function(){
      return Session.get('curTemplate') === 'tblScheduler';
    })
    

    or define it on the Body template:

    Template.body.helpers({
      isChiefTemplate:  function(){
        return Session.get('curTemplate') === 'tblScheduler';
      },
    });
    

    And the template from your update/Michel Floyd's answer:

    {{#unless isChiefTemplate}}
      <button type="button" id="btnDisplayScheduleTemplate" name="btnDisplayScheduleTemplate">Display Schedule</button>
    {{/unless}}