简体   繁体   中英

Meteor session trying to trigger template render

currently i'm having trouble with meteor sessions and how my code triggers it to render a template. Currently I have a session that sets its ._id to whatever is clicked.

Template.sidebar.events({
/* on click of current sidecat class change to sidecat selected */
'click .sidecat': function (event) {
    Session.set("selected_project", this._id);
    }
});

And I have it add a css class if selected_player equals the div.

Template.sidebar.sidebarselected = function () {
   return Session.equals("selected_project", this._id) ? "sidebarselected" : '';
}

Now I render a template when there is sidebarselected and another class present. On click of the item it renders the template.

Template.sidebar.projectselected = function() {
var find = Session.get("selected_project");
var find2 = ($("#"+find).attr('class'));
/* if exists return true render the template */
if (find2 == 'project sidebarselected')
{
  return  true
}
/* else don't render it return null */
else {
  return null
}
};

Everything up until now works great. Now I have a Button that creates a new item in the list and makes it the selected item. This is when the trouble occurs. When I create a new Item the list item is rendered and given the class sidebarselected but it does not render the template which should be called. It does render the template when I click an item. But not when using the button to create a new list item. It becomes selected but does not render the template. Here is the code for that.

Template.sidebar.events({
/* add bar settings menu functions for clicks */
'click #newProject': function(event){ 
  var create = NewProject();
  Session.set("selected_project", create);
},

This is the NewProject Function

/* add a new project to the side bar */
function NewProject() {
id = Aprojects.insert({
  name: "New Project",
  type: "project"
});
doc = Aprojects.findOne({_id:id});
return doc._id;
}

Ok there is everything. Item is created when I click on button, class is added but template is not rendered. This is all of the javascript, if html is need let me know and I will provide it.

Let me add some details and html template stuff. But anyways what does work is

  • you can select a project in the list
  • when you select a project (by clicking on it), it's given a classname to indicate that it's selected
  • when you click "new project" you want to add an item to the list and immediately select it

That all works correctly. The problem is when clicking the new project button. It still selects the newly made project properly and gives it a class of selected. What doesn't happen is if it finds that the selectedbar class also has a class of project with it. It renders a separate template (projectpicked). Projectpicked shows up when items are clicked. Not when #newproject is clicked. Even through it ends up selected it does not show projectpicked template. Let me see if the code can do more of the talking.

<body>
{{> sidebar}}
</body>
<template name="sidebar">
{{#if aproject}}
  {{#each aproject}}
    <div class="sidecat {{sidebarselected}} project" id="{{divids}}">
    {{name}}
    </div>
  {{/each}}
{{/if}}
{{#if projectselected}}
{{> projectpicked}}
{{/if}}
</template>

<template name="projectpicked">
project was picked from sidebar
</template>

The reasoning behind the application logic and DOM structure combo is that I have other things besides projects like categories. I figured using session gets the id and then we figure out what class it is like project or category and display a different template based off of what class it is. Don't know if its the best way but it's what I came up with. Open to suggestions. If somethings not clear not me know and I'll try to explain it. Thanks for the help.

I would rewrite the projectselected helper to not depend on a HTML classname to execute its logic, but to depend on a Session value. You're using Session correctly in most of your code, but it seems weird to then couple your application logic to the DOM structure.

The way your code works at the moment (without seeing your HTML template - you should post that too!), it looks like you want it to do the following:

  • you can select a project in the list
  • when you select a project (by clicking on it), it's given a classname to indicate that it's selected
  • when you click "new project" you want to add an item to the list and immediately select it

Here's how I'd solve that scenario:

Your template

<body>
 {{> sidebar}}
</body>

<template name="sidebar">
  <ul>
    {{#each items}}
    <li class="{{selected}} project" id="id_{{_id}}">{{_id}}</li>
    {{/each}}
    {{> newproject}}
  </ul>
  {{> projectpicked}}
</template>

<template name="newproject">
    <li id="newproject">Create a new project</li>
</template>

<template name="projectpicked">
  {{#if projectpicked}}
    A project was picked!
  {{/if}}
</template>

Your javascript

// When clicking an item in the list, remember which one we just clicked
Template.sidebar.events({
  "click li": function() {
    Session.set("selected_project", this._id);
  }
});

// Add the selected class to the item that was remembered
// by the session when we clicked on it
Template.sidebar.selected = function() {
  return Session.equals("selected_project", this._id) ? "selected" : "";
}

Template.sidebar.items = function() {
  // or whatever code you have to return the list of items
  return Projects.find(); 
}

// when clicking the new project button, create the new project
// and remember the id, then store that as the selected value in the session.
Template.newproject.events({
  "click #newproject": function() {
    var newprojectId = newProject(); // do your thing
    Session.set("selected_project", newprojectId);
  }
});

Template.projectpicked.projectpicked = function() {
  return !Session.equals("selected_project", undefined);
}

The key here is to only set the selected_project Session value when you click on something. That happens twice; when you click an item to select it, and when you click the new project.

To get your template to draw the selected item, all you need to do in Meteor is describe when an item is selected: an item is selected when some session value matches its id. That's all.

I haven't tested this code and it's obviously incomplete, but hopefully this points you in the right direction for refactoring your code a bit.

Well, after getting rather frustrated and rewriting most of the code over again I found the problem. In my projectpicked template instead of using Session.get and then using it to find the class. In stead I just have a

if ($('.sidecat.project').hasClass('sidebarselected')) {
return true
}

While the original was:

if (find2 == 'project sidebarselected')
{
return  true
}

So I used some jquery instead of directly comparing variable find2 to a string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM