Search code examples
meteormeteor-blaze

Meteor dynamic content without routing


What is best practice to change content on a page without creating a route?

BlazeLayout.render('mainLayout', { top: 'header', menu: 'menu', main: 'dashboard', bottom: 'footer' });

How can i hide/show template components inside the dashboard without creating a new route? Should this be done in helpers using some sort of if/else logic in the html and using helper for on button click? Let's say i want to show different content inside dashboard template based on button clicks (href).

Please provide a best practice and good solution that is easy with lots of components.


Solution

  • How can i hide/show template components inside the dashboard without creating a new route? Should this be done in helpers using some sort of if/else logic in the html and using helper for on button click?

    You can do that but you should be aware of some points to keep your code clean and modular:

    • Try to wrap parts of your dashboard into own templates to keep the code clean
    • Use ReactiveDict in favor of many ReactiveVar instances
    • Wrap recurring parts in templates, too to reduce duplicate code
    • Register recurring helpers globally or in the most upper template of your Dashboard
    • Subscribe on the parent template to data that is shared across all parts of the dashboard and subscribe to local data in the respective components
    • Use autorun and subscription.ready() and display a loading indicator until the subscription is ready. Don't wait to have everything loaded before rendering as this may reduce the UX dramatically.

    Let's say i want to show different content inside dashboard template based on button clicks (href).

    You can attach a data attribute to the button, that has a specific id of the target to be toggled:

    <template name="dashboardComponent">
      <a href class="toggleButton" data-target="targetId">My Link</a>
    </template>
    

    You can then read this id and toggle it's state in your ReactiveDict:

    Template.dashboardComponent.events({
      'click .toggleButton'(event, templateInstance) {
        event.preventDefault();
    
        // get the value of 'data-target'
        const targetId = $(event.currentTarget).attr('data-target');
    
        // get the current toggle state of target by targetId
        const toggleState = templateInstance.state.get( targetId );
    
        // toggle the state of target by targetId
        templateInstance.state.set( targetId, !toggleState );
      }
    });
    

    In your template you can then ask to render by simple if / else:

    <template name="dashboardComponent">
      <a href class="toggleButton" data-target="targetId">My Link</a>
      {{#if visible 'targetId'}}
        <div>target is visible</div>
      {{/if}}
    </template>
    

    And your helper is returning the state:

    Template.dashboardComponent.helpers({
      visible(targetName) {
        return Template.instance().state.get(targetName);
      }
    });
    

    There could be the problem of sharing the state between parent and child templates and I suggest you to avoid Session where possible. However as beginner it is a lot easier to first use Session and then work towards a more decoupled (parameterized templates) solution step by step.

    Please provide a best practice and good solution that is easy with lots of components.

    This is a high demand and it is your competency to work towards both! However here is a short peek into this:

    • Best practice is what works for you plus can work for others in other use cases. Try to share your work with others to see where it will fail for their use case.

    • Using routes has the advantage, that you can use query parameters to save the current view state in the url. That adds the advantage, that on reloading the page or sharing via link, the page state can be fully restored.

    • easy with lots of components is a contradiction and I don't know if you expect some magical puff that solves this complexity for you. As a software engineer it is your competency to abstract the complexity into smaller pieces until you can solve the problem within certain boundaries.