Inconsistant link behaviour

(I’ve found the source of the issue, but that just creates a new issue, see my first reply to this OP)

I’m seeing some inconstant behaviour from internal links in my Meteor app and was wondering if there’s some method to the madness.

On a certain page I have two sets of links. One is a nav list in a header element. The other is a sidebar menu, also marked up as a nav list.

Both use the pathFor syntax for defining the links, i.e {{ pathFor 'AccountSettings' }}

When a user clicks any of the links on the sidebar menu the page change is as smooth as butter. It’s quick and the new template is loaded in.

When a user clicks any of the links in the header menu it seems to involve a hard-refresh - the page fully reloads, top to bottom - it’s quite jarring.

This issue appears to be browser independent.

Here’s a gif demonstrating the issue, however you’ll have to pay close attention I’m afraid due to the framerate. It’s most noticeable at the end, where I click back and forth between two pages smoothly, then select ‘Settings’ from the header menu and you see the whole page reload. But you see it near the beginning as well when I initially select the ‘Settings’ link, the avatar in the top right flashes white as it completely reloads.

(Ignore the styling, the gif’s compression removes the tab background occasionally!)

EDIT: I found this SO Prevent Meteor/Iron Router from reloading when changing Routes - Stack Overflow that indicates it may be something to do with the template structure and the {{> yield}}. I don’t think my setup meets the requirements outlined in the SO to cause the issue, but I’ll let others be the judge:

master.html:

<template name="DashboardMaster">
  {{> DashboardHeader}} <!-- This is the header with the dropdown menu links -->
  {{> yield}} <!-- This is where the page content lives, i.e the following template -->
</template>

settings.html:

<template name="BriefSettings">
  <div id="settings" class="center">
    {{> SettingsNav }} <!-- The sidebar menu that doesn't cause reloads -->

Hopefully the extra info is helpful. However I’m not sure how else I’d structure it to ensure all link clicks provide a smooth transition, without avoiding yield altogether.

Edit 2: Even if I include the DashboardHeader directly in the BriefSettings template I still see the same behaviour. Identical links, both existing in the same template, yet one causes a page refresh, the other doesn’t :confused:

Ahah, I’ve kind of worked out what’s causing it.

I have a event.stopPropagation(); on the click event that opens that header dropdown menu (to counter a document-wide click event that closes that menu should a user ‘click away’ from it). Removing that seems to fix the issue.

So… any ideas how I’d handle that situation differently? Without the event.stopPropagation(); on that event then the menu just closes itself immediately as it counts as a click on the document:

$(document).on('click', function(){
  $('#user nav').removeClass('open');
  $('#user nav').velocity('transition.slideUpOut', {
    delay: 100,
    duration: 200
  });
})

Template.DashboardHeader.events({
  "click #user": function (event) {
    event.stopPropagation(); // Causing the issue!

However it seems that with it links within that menu cause the page to refresh.

The docs suggest return false;

Returning false from a handler is the same as calling both stopImmediatePropagation and preventDefault on the event.

Thanks @robfallows - sorry for the extremely late reply - I haven’t touched this project since my original post!

I tried working return false into the click event, however this seems to stop the links from working.

i.e.

"click #user": function (event) {
  // Some logic to change the state of the menu
  return false;
}, 

Prevents the links within #user from triggering.

Ok so I ended up resolving this with an extra condition:

$(document).on('click', function(event){
  var trigger = $(event.target).attr('id');
  if( trigger != 'user' && trigger != 'user-img' ) // <- New condition
  {
    $('#user nav').removeClass('open');
    $('#user nav').velocity('transition.slideUpOut', {
      delay: 100,
      duration: 200
    });
  }
})

This does the same job as the stopPropagation in the meteor event but without the unintended consequences!

Thanks for this. I ran into the same issue and this was super helpful.