Meteor-roles and events not firing?

I’ve installed and started using the meteor-roles package to control access to my app. I the main HTML file of my application I added the following code just after my {{> header}} call:

{{#if isInRole 'super-admin'}}
    .... my html code that calls other templates
{{/if}}

The if block works exactly as it should, however my javascript events (such as jquery) now refuse to fire (and yes, I’m logged in!)

Example of an event that no longer works:

// Get the Selected Project Filters
  $("#projectList").click(function() {
      var projectList = $("#projectList input:checkbox:checked").map(function() {
      return this.id;
    }).get();
    Session.set("projectList", projectList);
  });

Thoughts?

Where are you defining your javascript events? Also - I’m assuming you’re using Blaze; any reason why you aren’t using Blaze template event handling, instead of rolling your own? You might want to try that approach first.

They are defined in the file with the corresponding name as the template, but ending in “.js”. Yes, using Blaze and jquery. Honestly, can’t recall why I didn’t use Blaze template event handing… probably just because i’m a noob! :smile:

I’ll try Blaze events, just seemed odd that my IF block keeps jquery from working…

I converted some of my code over to use Blaze templates and that works. However, it seems that jquery does not, and I have some things that I used jquery for such as select all / none checkboxes as well as the following:

Session.set("sitesToShow", $('input[name=sitesToShow]:checked', '#sitesToShow').val());

I’m stumped as to why jquery wouldn’t be working anymore…

You might want to make sure you have the jquery package added explicitly: meteor add jquery

Yep, did that and also did a nano ./meteor/packages to be sure. Says it’s up to date. Again, it worked perfectly prior to using the Roles package and that IF block listed above.

Are you able to share your code somewhere? “If you share it, they will come.” (Field of Dreams reference - man I’m lame.)

Ok, here is the HTML and the JavaScript code.

Here’s the HTML:

<body>
{{> header}}

{{#if isInRole 'super-admin'}}

<!-- Begin Site Body -->
<div class="container-fluid">
<!-- Start Filters Panel -->
<div class="panel panel-primary col-xs-2" id="filterPanel">
<div>
<ul class="list-unstyled">
<li class="text-right">Total Sites: {{totalSites}}</li>
<li class="text-success text-right">Sites Complete: {{completeSites}}</li>
<li class="text-warning text-right">Site Issues: {{problemSites}}</li>
</ul>
</div>
<hr>
<form class="filterBy-form">
<div class="form-group">
<label for="nameField">Filter By:</label>
<input type="text" name="text" class="form-control" id="siteField" placeholder="Site Name or Number" />
</div>
<div class="form-group">
<input type="email" name="text" class="form-control" id="techField" placeholder="Tech Name" />
</div>
<div class="form-group">
<table class="table table-condensed" id="projectList">
<thead>Project:</thead>
{{> getProjects}}
</table>
</div>
<div class="form-group">
<table class="table table-condensed" id="clientList">
<thead>Client:</thead>
{{> getClients}}
</table>
</div>
</form>
<hr>
<form class="form" id="sitesToShow">
<label for="nameField">Show:</label>
<div class="radio">
<label class="all-sites">
<input type="radio" name="sitesToShow" id="allSites" value="allSites" checked> All Sites
</label>
</div>
<div class="radio">
<label class="problem-sites">
<input type="radio" name="sitesToShow" id="problemSitesOnly" value="problemSitesOnly"> All Problem Sites
</label>
</div>
<div class="radio">
<label class="unassigned-sites">
<input type="radio" name="sitesToShow" id="problemSitesOnly" value="unassignedProblemSites"> Unassigned Problem Sites
</label>
</div>
</form>
</div>
<!-- End Filters Panel -->
<div>
<a href="#" id="filterPanelIcon">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
</div>

<!-- Map Panel -->
<div class="col-lg-10 col-md-10 col-sm-10">
<div class="row">
<div class="panel panel-primary">
{{> map}}
</div>
</div>

<div class="row">
{{> siteList}} {{> handleSites}}
</div>
<!-- End Row -->
</div>

{{> footer}}
</div>

{{/if}}   <!-- End Role Check -->

<!-- End Container -->
</body>




<!-- Meteor Templates -->
<template name="getProjects">
{{#each sites}}
<div class="checkbox">
<label class="projectList">
<input type="checkbox" class="projectFilter" id="{{ project }}" checked="true">
<small>{{project}}</small>
</label>
</div>
{{/each}}
</template>


<template name="getClients">
{{#each sites}}
<div class="checkbox">
<label class="clientList">
<input type="checkbox" class="clientFilter" id="{{ client }}" checked="true">
<small>{{client}}</small>
</label>
</div>
{{/each}}
</template>

The JavaScript:

// Get the selected sites to handle
$(document).ready(function() {
  $("#handleSite").click(function() {
    var siteIDs = $("#siteList input:checkbox:checked").map(function() {
      return this.id;
    }).get();
    for (var i = 0; i < siteIDs.length; i++) {
      Sites.update({ _id: siteIDs[i] }, {$set: { assignedTo: "Gerald"}});
    }
    $("#theSitesSelectAll").prop( "checked", false );
  });

  // Work with My Problem sites
  $("#myProblemSites").click(function() {
    var mySiteIDs = $("#mySites input:checkbox:checked").map(function() {
      return this.id;
    }).get();
    for (var i = 0; i < mySiteIDs.length; i++) {
      Sites.update({ _id: mySiteIDs[i] }, {$set: { assignedTo: null }});
    }
    $("#mySiteSelectAll").prop( "checked", false );
  });

  // Get the Selected Project Filters
  $("#projectList").click(function() {
    console.log("click");
      var projectList = $("#projectList input:checkbox:checked").map(function() {
      return this.id;
    }).get();
    Session.set("projectList", projectList);
  });

  // Get the Selected Client Filters
  $("#clientList").click(function() {
      var clientList = $("#clientList input:checkbox:checked").map(function() {
      return this.id;
    }).get();
    Session.set("clientList", clientList);
  });

  $('#sitesToShow input').on('change', function() {
    Session.set("sitesToShow", $('input[name=sitesToShow]:checked', '#sitesToShow').val());

  });

  $("#filterPanelIcon").click(function() {
    $("#filterPanel").toggle("slow");
  });

  $(".siteDetails").click(function() {
    alert("Open Lightbox");
  });
 }); // End Document Ready


Template.getProjects.helpers({
  sites: function() {
    const projects = Template.instance().distinct.get();
    // turn our array of project values into an array of {project: project}
    return _.map(projects, project => {
      return {
        project
      }
    });
  }
});

Template.getClients.helpers({
  sites: function() {
    const clients = Template.instance().distinct.get();
    // turn our array of project values into an array of {project: project}
    return _.map(clients, client => {
      return {
        client
      }
    });
  }
});

Template.getProjects.onCreated(function() {
  this.distinct = new ReactiveVar();
  Meteor.call('getDistinctProjects', (error, result) => {
    if (error) {
      // do something
    } else {
      Session.set("projectList", result);
      this.distinct.set(result); // save result when we get it
    }
  });
});

Template.getClients.onCreated(function() {
  this.distinct = new ReactiveVar();
  Meteor.call('getDistinctClients', (error, result) => {
    if (error) {
      // do something
    } else {
      Session.set("clientList", result);
      this.distinct.set(result); // save result when we get it
    }
  });
});

Greatly appreciate some insight on this!

Again, please note that if I remove the IF block around the code, it does work correctly. Really strange…

Your code didn’t quite come through - can you try editing it to add 4 spaces in front (so the default code formatting kicks in), or sharing it via a https://gist.github.com?

Thanks, I edited the file and also created a snippet here:

https://bitbucket.org/snippets/SnakeHead/q8pe4

Okay - with Meteor when using Blaze you’ll want to think in terms of when is the template ready, not necessarily when is the DOM ready. You’re mixing a lot of jQuery based functionality with Blaze template related functionality, when a lot of this can (and should) be handled by the template itself. For example, the #handleSite click event should be an event defined on the handleSites template. The same goes for all of your jQuery defined click events - these can all be defined as template events. When using Blaze if you want to hold off until the template is ready (and ultimately the DOM), then look into using a templates onRendered function.

Ok, thanks. Will look into that. Just still seems odd to me that it all works fine if I get rid of the “{{#if isInRole ‘super-admin’}}” statement.

Have you confirmed that your user has the super-admin role? I would check this at the DB level:

meteor mongo
> db.users.find({_id: 'yourUserId'}).pretty()

Your user doc should have a roles property containing super-admin.

Well, the page loads the rest of the HTML correct after I log in, so I’d think so. The user (me) is created in the fixtures.js file. (I also did meteor reset to be sure the data is created)

 var geraldUserId = Accounts.createUser({
   username: "gbailey",
   email : "gerald.bailey@deploymentpro.com",
   password : "gerald2016",
   profile  : {
     //publicly visible fields like firstname goes here
   }
 });

Roles.addUsersToRoles(geraldUserId, 'super-admin', Roles.GLOBAL_GROUP)