6

I am trying to display 3 projects per row. My template looks like this: (UPDATED)

 <template name="projectList">
   {{breakTimeReset}}
   <div class=row>          
  {{#each projects}}

    {{> projectItem}}

        {{#if breakTime}}
        </div>
        <div class=row>
        {{/if}}

   {{/each}}
   </div>
</template>

As you can see for each project in the database I output projectItem. I want to output them so every 3 project are wrapped in a

This is my js helper

Template.projectList.helpers({
    projects: function() {
        return Projects.find();
    },
    breakTimeReset: function() {
        Template.projectList.doCount = 0;
    },
    breakTime: function () {
        count = Template.projectList.doCount + 1;
        console.log(count);
        Template.projectList.doCount = count;

        if (count % 3 == 0) {
            console.log("Started break");
            return true;
        }
        else
            return false;
    }
});

My question is how can I set it up so there are 3 projects per row, and then it knows to insert a new row div after every 3 projects? The way I have it currently setup leads to really funky results, as it is not reliable in that the new div will be inserted before the project.

Check out the results here: http://testprojectapp.meteor.com

You will see that the first row shows up ok but then I get some funky results after that. And if you check out the DOM through viewing page source you will see that the dont match my code which is weird.

Let me know if this is a confusing question. Thanks!

madth3
  • 7,275
  • 12
  • 50
  • 74
Nearpoint
  • 7,202
  • 13
  • 46
  • 74

3 Answers3

7

You can group your data before it gets rendered:

Template.projectList.helpers({
    projects: function () {
        all = Projects.find({}).fetch();
        chunks = [];
        size = 3
        while (all.length > 3) {
            chunks.push({ row: all.slice(0, 3)});
            all = all.slice(3);
        }
        chunks.push({row: all});
        return chunks;
    },
    breakTimeReset: function () {
        Template.projectList.doCount = 0;
    },
    breakTime: function () {
        count = Template.projectList.doCount + 1;
        console.log(count);
        Template.projectList.doCount = count;

        if (count % 3 == 0)
            return "</div><!-- why? --><div class='row'>"
        else
            return ""
    }
});

<template name="projectList">
  {{breakTimeReset}}
  {{#each projects}}
    {{> projectRow }}
  {{/each}}
</template>

<template name='projectRow'>
  <div class='row span12'>
    {{#each row }}
      {{> projectItem}}
    {{/each}}
  </div>
</template>

<template name="projectItem">
  <div class="span4">
    <h3><a href="{{projectPagePath this}}"> {{title}} </a></h3>
    <p> {{subtitle}} </p>
    <p> {{description}} </p>
    <p><img src="{{image}}"/></p>
    <p> {{openPositions}} </p>
  </div>
</template>

Sorry I missed so many times, nearpoint!

Jim Mack
  • 1,437
  • 11
  • 16
1

You can also do that by using plain CSS. The Foundation Framework has a grid system where you need to define the columns in the grid element, not in the child elements itself and someone adapted it to be used together with bootstrap. This means you can simply add more and more elements and the grid will layout them.

https://github.com/JohnnyTheTank/bootstrap-block-grid

<div class="block-grid-xs-2 block-grid-sm-3 block-grid-md-4">
    <div>
        Content 1
    </div>
    <div>
        Content 2
    </div>
    <div>
        Content 3
    </div>
    <div>
        Content 4
    </div>
    <div>
        Content 5
    </div>
    <div>
        Content 6
    </div>
</div>
Marian Klühspies
  • 15,824
  • 16
  • 93
  • 136
0

UPDATE: fails because template engine is helpful, and won't let you have tags spanning templates. It balances each one out, even if you try just injecting text. Nice if you need it, I'm not a fan.

Previous:

Oh, nearpoint stuck to his guns and I was wrong! Handlebars parses each template and 'fixes' it so there are an even number of tags. Edited to reflect this.

The template

<template name='sureties'>
{{breakTimeReset}}

{{#each allSureties }}

  {{name}}

  {{{breakTime}}}

{{/each}}
</template>

Some helper functions

Template.sureties.breakTimeReset = ->
  Template.sureties.docCount = 0
  ''
Template.sureties.breakTime = ->
  count = Template.sureties.docCount + 1 or 0
  console.log  count
  Template.sureties.docCount = count
  if count % 3 is 0
    return "</div><div class="">
  else
    return ""
Jim Mack
  • 1,437
  • 11
  • 16
  • I've been trying something like this and I can't get it to work. I updated my code above with what I have been trying to do. – Nearpoint Sep 08 '13 at 02:11
  • Try if ((count != 0) && (count % 3 == 2)) { but you have the problem of closing it properly (not double closing it). Which is why I prefer to think of the break as closing and opening. If you end up with an empty row, no problem. My code works as is, with only two functions. consider it. – Jim Mack Sep 08 '13 at 02:34
  • I am confused about some things in your template. I am assuming that the {{name}} variable in your code is equivalent to a project in mine. Firstly, the first {{name}} does not get into the , since you only call it after. Secondly, what do you mean by count = Template.sureties.docCount + 1 or 0. Why the 'or 0' part? Finally do you mean if count % 3 is 0 return true? Thanks I really appreciate your help, I am close I feel! – Nearpoint Sep 08 '13 at 02:40
  • So for the first {{name}} I guess you could just add a right at the top. So you can ignore that question. – Nearpoint Sep 08 '13 at 02:53
  • I updated my code to do it exactly how you showed in your template. I show this in my updated question. I also deployed it to a meteor test server here: http://testprojectapp.meteor.com It has weird results, I wonder why? Can you tell? I appreciate it! – Nearpoint Sep 08 '13 at 03:13
  • Very close. Where I suggested /close open you have open /close:
    Just switch it around.
    – Jim Mack Sep 08 '13 at 04:12
  • I am so confused, in my example code I close the div then open it: {{#if breakTime}}
    {{/if}} see my updated code in the question above, let me know if I am missing something
    – Nearpoint Sep 08 '13 at 04:38
  • In the browser source it looks like it is but my code says otherwise! What is going on, so strage – Nearpoint Sep 08 '13 at 04:44
  • Is it possible the browser is switching the divs back around? I cant think of why it looks like this but my code clearly shows
    – Nearpoint Sep 08 '13 at 04:47
  • No, this makes no sense. I agree what the code above says. The question is what does the deployed code do. Trick it out so it is text: < / div etc. See if it looks right then. – Jim Mack Sep 08 '13 at 05:12
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/37000/discussion-between-nearpoint-and-jim-mack) – Nearpoint Sep 08 '13 at 05:22
  • So I made it into text by putting spaces in it like you said. < / div>< div class=row >. When it is text it shows up correctly! But as soon as I remove the spaces from the divs it flips it back around!I will be in the chat room as well (link one comment above) – Nearpoint Sep 08 '13 at 05:52