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

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>Foo</li>
{{else}}
<li>Sign in</li>
{{/if}}
<li>About</li>
</ul>
</div>
</nav>
<!-- dropdown1 structure -->
<ul id="dropdown1" class="dropdown-content">
<li class="signout">Sign out</li>
</ul>
</template>
header.js
Template.header.rendered = function () {
$(".dropdown-button").dropdown({
belowOrigin: true // Displays dropdown below the button
});
};
What could be the problem?

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>Foo</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.

Related

Prevent angular 2 from redirecting <a href="#"> to homepage

I have a sample login page which directs to a dashboard. The login page is set as the initial redirect page and this routes to the dashboard. The dashboard contains a dropdown menu with some links. Everytime a link is clicked it keeps redirecting to the login page. However, when the dashboard page is reloaded the dropdown menu works completely fine.
I am thinking of using the "event.preventDefault()" for the links but I hope there is a workaround.
Dashboard Menu - HTML
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li>
<i class="fa fa-calendar fa-fw"></i> Manage Events<span class="fa arrow"></span>
<ul class="nav nav-second-level collapse">
<li>
Lorem Ipsum
</li>
<li>
Lorem Ipsum
</li>
</ul>
<!-- /.nav-second-level -->
</li>
</ul>
</div>
<!-- /.sidebar-collapse -->
</div>
Edit: After getting some replies, I would like to clarify my main problem.The problem exists in the link being a null link and that Angular 2 takes it as a null link and causes it to redirect it. If I could find a workaround to tell Angular, don't take this link as a null link it will be ideal.
If you don't want any redirection when clicking on your link(s), check out these solutions:
Different methods to make a null link?
Or you can put <a> tag without href attribute.
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li>
<i class="fa fa-calendar fa-fw"></i> Manage Events<span class="fa arrow"></span>
<ul class="nav nav-second-level collapse">
<li>
<a [routerLink]="['ManageEvents/LoremIpsum']">Lorem Ipsum</a>
</li>
<li>
<a [routerLink]="['ManageEvents/LoremIpsum']>Lorem Ipsum</a>
</li>
</ul>
<!-- /.nav-second-level -->
</li>
</ul>
</div>
export const routes: Routes = [
{ path: 'ManageEvents/LoremIpsum', component: ManageEventsLoremIpsum }
];
This works for me!!
link
hope this helps link also working by this way
For me I used the routerLink and set it to empty:
<a [routerLink]="" (click)="onClickPage()">Click me</a>
try to remove href, setting cursor: pointer with css and handle click on th a element like <a (click)=yourFunction()></a>. it should work ;)
Just simply use <a href>Lorem Ipsum</a>.
I had a situation after parent received events from child component, it redirect to homepage. I solved the problem in parent
receiveMessage($event) { //do something this.router.navigateByUrl('/parent-route'); }
even the parent route are supposed to accept parameters.
For me it javascript:void(0); works. Angular 14
Last Page // HTML file

Materialize Dropdown weird behavior when using with React if-else syntax

I am using MaterializeCSS and React to render a simple dropdown based on whether the user is logged in or not.
The idea is that if the user is logged in, to show the dropdown menu and if they are not, to only show a logout link.
<nav className="transparent black-text" role="navigation">
<ul id="dropdown" className="dropdown-content">
<li>My Profile</li>
<li>My Documents</li>
<li className="divider"></li>
<li>
<a href="/#"> Logout
</a>
</li>
</ul>
<div className="nav-wrapper container">
<a className="brand-logo brand-logo-small" href="/">
<img alt="Logo" id="header-logo" src="../../images/favicon.png"/>
{'My Document'}
</a>
<ul className="right hide-on-med-and-down" id="nav-mobile">
<li>
{this.state.loggedIn == 'true'
? <a className="dropdown-button"
data-activates="dropdown"
data-beloworigin="true"
data-constrainwidth="false"
href="/#">{'User'}
<i className="material-icons right">arrow_drop_down</i>
</a>
: Login
}
</li>
</ul>
</div>
</nav>
In the above snippet, if the loggedIn flag equals true, I expect that the dropdown should be displayed, but it isn't.
However, when I add className="dropdown-button" data-activates="dropdown" attributes to the second <a> tag, the dropdown gets displayed.
Additionally, if I remove the className="dropdown-button" data-activates="dropdown" attributes from the first link, the dropdown is still displayed.
What could I be doing wrong here? Why is the dropdown on the first <a> tag only displayed when I set the attributes on the second <a> tag?
Thanks in advance.

Nav tabs not working as expected

Please bear with me as I'm extremely new to Meteor. I am attempting to dynamically create both tabs and their respective content within one template using the following code. The expected data does show up, but on my first tab (let's say the value of {{Name}} is "FirstTab") I see the {{Name}} for all of the items in my levels collection. However, when I click on the other tabs, I see only the expected {{Name}} values, even when I return to the "FirstTab" tab. Obviously, I'm iterating incorrectly somewhere...but I don't understand why it works when I click out of the first tab. How should I be implementing this?
<ul class="nav nav-tabs" role="tablist">
{{#each indexedArray levels}}
{{#if _isFirstIndex }}
<li role="presentation" class="active">{{Name}}</li>
{{ else }}
<li role="presentation" class="">{{Name}}</li>
{{/if}}
{{/each}}
</ul>
<div class="tab-content">
{{#each indexedArray levels}}
<div role="tabpanel" class="tab-pane active" id="{{removeSpaces Name}}">
<h2>{{Name}}</h2>
</div>
{{/each}}
</div>
Realized I could just add the same {{#if _isFirstIndex }} around the tabpanel div to make it work as expected. However, I agree with #MasterAM that this is definitely un-Meteor-like and I'll need to refactor following that advice.

Two clicks needed to load Modal and SideNav (Meteor with Materialize)

I have a strange problem with my Materialize navigation in Meteor. The weird thing is that when I click a link in the navigation, the sidebar or modal is only loaded on the SECOND click. Thus, I have to click the link once (where nothing happens) and then again for the element to appear. After that, the element loads on any click (only one click is required).
I have never had this problem, and I think it could be a Materialize problem. Before I count materialize out, though, I want to check with you guys and hear if I am possibly calling my JQuery functions wrong or something. Here is the code:
header.html:
<template name="header">
<nav>
{{> sideNav}}
<div class="nav-wrapper">
<span class="light"></span>hamok
<ul id="nav-mobile" class="left">
<li><i class="mdi-navigation-menu"></i></li>
<li><i class="mdi-action-search left"></i>Search</li>
</ul>
<ul id="nav-mobile" class="right">
{{#if currentUser}}
<li><a id="logout">Sign out</a></li>
{{else}}
<li><a class="modal-trigger-login" href="#loginModal">Account<i class="left mdi-action-account-circle"></i></a></li>
{{/if}}
</ul>
</div>
</nav>
{{> loginModal}}
</template>
<template name="loginModal">
<div id="loginModal" class="modal">
<div class="modal-content">
{{> atForm}}
</div>
</div>
</template>
<template name="sideNav">
<ul id="slide-out" class="side-nav">
<li>First Sidebar Link</li>
<li>Second Sidebar Link</li>
</ul>
</template>
header.js
Template['header'].helpers({
});
Template['header'].events({
'click .modal-trigger-login': function() {
$('.modal-trigger-login').leanModal();
},
'click #logout': function() {
Meteor.logout();
},
'click .button-collapse': function() {
$(document).ready(function(){
$(".button-collapse").sideNav();
});
}
});
Thank you guys for taking a look!
What leanModal does is initializing the jQuery plugin, so it should be called inside of your template onRendered function, not when clicking on the modal trigger button.
Template.header.onRendered(function(){
this.$(".modal-trigger-login").leanModal();
});
You can remove your click .modal-trigger-login event : you currently need 2 clicks simply because the first one will just initialize the plugin.
Likewise, your sideNav initialization call should be made in the onRendered lifecycle event :
Template.header.onRendered(function(){
this.$(".button-collapse").sideNav();
});

Meteor accounts-ui dropdown behavior when embedded in the navbar dropdown

I am trying to place the standard Meteor accounts-ui into a navbar dropdown with the cog icon as shown in the screenshot and code snippet below. However, two issues arise:
Before signing in, there is an odd extra whitespace on the right side. After signing in, it aligns fine.
After a single click on any of the elements in the dropdown, the dropdown immediately closes. This is fine when I click Sign in with Google or Sign in, but it should not do that when I click into the text input fields, Forgot password or Create account.
How can I address the above behaviors accordingly while still using the accounts-ui package? For instance, is there some sort of JS code I can use to override the behavior to fix #2? Thanks!
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<span class="glyphicon glyphicon-cog"></span>{{loginText}}
<ul class="dropdown-menu">
<li><b>{{> loginButtons align="right"}}</b></li>
</ul>
</li>
</ul>
</div>
</nav>
ian:accounts-ui-bootstrap-3 provides a Bootstrap dropdown out of the box. The code will look like:
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<ul class="nav navbar-nav navbar-right">
{{> loginButtons}}
</ul>
</div>
</nav>
But this does not display a cog-wheel. If you want to override the default dropdown link to a custom one, you need to override the template in the package. AFAIK, Meteor core doesn't have an easy way to do this, but you can use aldeed:template-extension to achieve this quite simply. First copy the template code from the accounts-ui-bootstrap-3 repo, then create a new template with similar content but different name:
<template name="my_loginButtonsLoggedInDropdown">
<li id="login-dropdown-list" class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown">
... custom content here ...
</a>
<div class="dropdown-menu col-sm-3">
{{#if inMessageOnlyFlow}}
{{> _loginButtonsMessages}}
{{else}}
{{#if inChangePasswordFlow}}
{{> _loginButtonsChangePassword}}
{{else}}
{{> _loginButtonsLoggedInDropdownActions}}
{{/if}}
{{/if}}
</div>
</li>
</template>
Then use
Template.my_loginButtonsLoggedInDropdown.replaces("_loginButtonsLoggedInDropdown")
It will replace the template, but still use the helpers and events from the original template.

Categories

Resources