Meteor Spacebars {{#if someCondition}} shows data

2019-03-01 06:12发布

问题:

I have tried this a couple different ways and they both behave the same way (see below for code). I'm using a spacebars if condition (and tried using a helper as well) to check if the user is logged in, then display login/sign up links if they aren't. If they are, hide them.

What I noticed is that on the initial page load (if they navigate back from a different site), the login/sign up links show quickly before hiding (if the user is still logged in). Is there a way to insure that no elements render in the view if the condition is false? It seems to me that it should check before the view starts rendering, then display the appropriate elements on the page.

Thanks for the help! -Chris

Solution to the flicker that I was experiencing: I was checking against the user, though the view was rendering quicker than the DB query. I added a guard expression (see below) and that seems to take care of the flicker.

isUserLoggedOut: function() {
  var user = Meteor.user();

  if(Meteor.user()) {
    return user && false;
  } else{
    return user && true;
  }
}

Attempt #1:

Template.headerTpl.helpers({
  isUserLoggedIn: function() {
    var user = Meteor.user();

    if(user) {
      return false;
    } else{
      return true;
    }
  }
});

<template name="headerTpl">
  {{#if isUserLoggedIn}}
  <li style="display:none;"><a href="{{pathFor 'userRegistrationFormTpl'}}" id="signup-js">Sign Up</a></li>
  <li><a href="{{pathFor 'userLoginFormTpl'}}" id="login-js">Login</a></li>
  {{/if}}
</template>

Attempt #2:

Template.headerTpl.helpers({
  isUserLoggedIn: function() {
    var user = Meteor.user();

    if(user) {
      return "hide";
    } else{
      return "show";
    }
  }
});

<template name="headerTpl">
  <li class={{isUserLoggedIn}}><a href="{{pathFor 'userRegistrationFormTpl'}}" id="signup-js">Sign Up</a></li>
  <li class={{isUserLoggedIn}}><a href="{{pathFor 'userLoginFormTpl'}}" id="login-js">Login</a></li>
</template>

Attempt #3:

{{#if currentUser}}
{{else}}
<li style="display:none;"><a href="{{pathFor 'userRegistrationFormTpl'}}" id="signup-js">Sign Up</a></li>
<li><a href="{{pathFor 'userLoginFormTpl'}}" id="login-js">Login</a></li>
{{/if}}

Attempt #4:

<template name="headerTpl">
  {{#if isUserLoggedOut}}
    {{> signInLinksTpl}}
  {{/if}}
</template>

<template name="signInLinksTpl">
  <li style="display:none;"><a href="{{pathFor 'userRegistrationFormTpl'}}" id="signup-js">Sign Up</a></li>
  <li><a href="{{pathFor 'userLoginFormTpl'}}" id="login-js">Login</a></li>
</template>

Template.headerTpl.helpers({
  isUserLoggedOut: function() {
    if(Meteor.user()) {
      return false;
    } else{
      return true;
    }
  }
});

回答1:

You need to subscribe to Meteor.users collection, template will be rendered after Meteor.user() is created, if you won't wait for subscription page will blink because at start there is nothing in Meteor.users collection.

You can use new Meteor functionality on template where you have login field

Template.login.onCreated(function () {
  var self = this;

  self.autorun(function () {
    self.subscribe("users");
  });
});

And in HTML

{{#if Template.subscriptionsReady}}
    <!--content-->
{{else}}
    Give me a second...
{{/if}}

Of course you need to create publish named 'users'



回答2:

Are you sure you're thinking about this correctly?

isUserLoggedIn: function() { // implies you're checking for the user
    var user = Meteor.user(); // if there's a user this returns true

    if(user) { // you're saying if there's a user ...
        return false; // return false
    } else{ // and if there isn't
    return true; // return true
    }
}

Basically you're saying "is the user logged in" and if yes "return false" which is making you double think. Instead, reverse your logic.

isUserLoggedOut: function() { // implies you're checking for the user
    var user = Meteor.user(); // if there's a user this returns true

    if(user) { // there is a user
        return false; // so isUserLoggedOut == false
    } else{ // and if there isn't a user
        return true; // isUserLoggedOut == true
    }
}

Now your template becomes easy

{{#if isUserLoggedOut}}
   {{>loggedOutTemplate}}
{{/if}}


回答3:

You can use instead, the currentUser helper from accounts package, like this.

{{#if currentUser}}
<!-- show content -->
{{else}}
 {{> login }} <!-- render login template -->
{{/if}}

Iron Router Option.

There is also a solution in the router level, using Router.onBeforeAction.

// lib/routes.js
// Create the function to check login.
   var requireLogin = function() {
       if (! Meteor.user()) {
          this.render('login');
        } else {
          this.next(); //using this.next the iron router will render the route named on the onBefore
      }
   }

   Router.onBeforeAction(requireLogin, {only: 'theRoute});

UPDATE

Template.headerTpl.helpers({
  isLogged:function(){
   if(Meteor.user()){
      return true;
    }else{
      return false;
    }
  }
})

<template name="headerTpl">
  {{#if isLogged}}
       <h1>Welcome User</h1>
     {{else}}
       <li style="display:none;"><a href="{{pathFor 'userRegistrationFormTpl'}}" id="signup-js">Sign Up</a></li>
       <li><a href="{{pathFor 'userLoginFormTpl'}}" id="login-js">Login</a></li>
  {{/if}}
</template>