Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
349 views
in Technique[技术] by (71.8m points)

javascript - Materialize: dropdown in "if" statement doesn't work

I tried to implement a dropdown list that is only visible when the user is signed in. The dropdown list works when outside the "if" statement but not inside. The buttons "Foo" and dropdown button are shown, however it doesn't "dropdown".

header.html

<!-- Header -->
<template name="header">
<nav>
    <div class="nav-wrapper">
        <a  class="brand-logo" href="{{pathFor 'home'}}">Logo</a>
        <ul id="nav-mobile" class="right hide-on-med-and-down">
            {{#if currentUser}}
                <!-- dropdown1 trigger -->
                <li>
                    <a class="dropdown-button" href="#!" data-activates="dropdown1">
                        <i class="mdi-navigation-more-vert"></i>
                    </a>
                </li>

                <li><a href="#">Foo</a></li>
            {{else}}
                <li><a href="{{pathFor 'signin'}}">Sign in</a></li>
            {{/if}}

            <li><a href="{{pathFor 'about'}}">About</a></li>
        </ul>
    </div>
</nav>

<!-- dropdown1 structure -->
<ul id="dropdown1" class="dropdown-content">
    <li class="signout"><a href="#!">Sign out</a></li>
</ul>
</template>

header.js

Template.header.rendered = function () {
    $(".dropdown-button").dropdown({
        belowOrigin: true // Displays dropdown below the button
    });
};

What could be the problem?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When your Template.header.onRendered lifecycle event is first fired, the dropdown HTML elements are not yet inserted into the DOM because the condition {{#if currentUser}} is not yet met (it takes a small amount of time before being actually logged in a Meteor app, that's why Meteor.user being reactive is handy !).

This is why your jQuery dropdown initialization fails : the DOM is not yet ready ! The solution is quite simple thoug : refactor your Spacebars code to put the dropdown markup in its own separate template :

<template name="dropdown">
  <li>
    <a class="dropdown-button" href="#!" data-activates="dropdown1">
      <i class="mdi-navigation-more-vert"></i>
    </a>
  </li>
  <li><a href="#">Foo</a></li>
</template>

Then insert the child template inside your header template :

{{#if currentUser}}
  {{> dropdown}}
{{else}}
  {{! ... }}
{{/if}}

This way the dropdown will have its own onRendered lifecycle event that will get triggered only after the user is logged in, and at this time the dropdown DOM will be ready.

Template.dropdown.onRendered(function(){
  this.$(".dropdown-button").dropdown({
    belowOrigin: true // Displays dropdown below the button
  });
});

Sometimes refactoring your code into smaller subtasks is not just a matter of style, but it makes things work the way intended.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...