最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Populating Bootstrap grid with dynamic data using #each in Meteor - Stack Overflow

programmeradmin1浏览0评论

Firstly thanks for your help and forgive my infant Meteor and Bootstrap skills. I am having a similar problem to the question raised here that has generate some suggestions but no solution. I want to populate a BootStrap grid using data from MongoDB in a Meteor template using #each. Since the BootStrap grid has 12 columns and I want to display 4 'cells' per row I believe I need to -

  1. Create a row using .
  2. Output four data elements inside ...element...
  3. Close the 'row div' with .
  4. Create the next row using ...
  5. Rinse and repeat from Step 2.

Step 2 is performed using a {{#each...}} block returning data from an array/collection.

My Meteor Template looks like this (I'm extending an example from the excellent 'Discovering Meteor' book) -

<template name="postsList"> 
<div class="posts">
   <div class='row-fluid' style="margin-left:1%">
      {{breakInit}}
      {{#each posts}}
         <div class="span3">
           {{> postItem}}
         </div>
         {{breakNow}}
      {{/each}}
   </div>
</div> 
</template>

The JavaScript for the Helpers look like this -

Template.postsList.breakInit = function() {
Template.postsList.docCount = 0 ;
};

Template.postsList.breakNow = function() {
count=Template.postsList.docCount + 1 ;
result="";
if ( count == 4 ) {
    count = 0 ;
    Template.postsList.docCount = count ;
    result="</div><div class=row>" ;
};
Template.postsList.docCount = count ;
return new Handlebars.SafeString(result);
};

This all appears to work, at least in terms of counting the elements output by the #each, returning the </div><div class=row> to start a new row and resetting the counter... However... the returned HTML to end the current row and start the next does not appear to be handled by Bootstrap (or Meteor or my browser) as I expect it to. It appears to be re-ordered as <div class=row></div>. See this screen-cap from Inspector in FireFox (code outputs 6 elements, 4 in first row, 2 in second) -

<div id="main" class="row-fluid">
  <div class="posts">
    <div class="row">
      <div class="span3"> … </div>
      <div class="span3"> … </div>
      <div class="span3"> … </div>
      <div class="span3"> … </div>
      <div class="row"> … </div>  <-- The problem...
      <div class="span3"> … </div>
      <div class="span3"> … </div>
    </div>
  </div>
</div>

Notice the <div class=row>...</div> in the middle of the spans? Doesn't look right, it should be closing the previous 'row' DIV and starting the next one. Can anyone suggest either a fix for my code or an alternative method for popluating a grid using dynamic data in Meteor?

Firstly thanks for your help and forgive my infant Meteor and Bootstrap skills. I am having a similar problem to the question raised here that has generate some suggestions but no solution. I want to populate a BootStrap grid using data from MongoDB in a Meteor template using #each. Since the BootStrap grid has 12 columns and I want to display 4 'cells' per row I believe I need to -

  1. Create a row using .
  2. Output four data elements inside ...element...
  3. Close the 'row div' with .
  4. Create the next row using ...
  5. Rinse and repeat from Step 2.

Step 2 is performed using a {{#each...}} block returning data from an array/collection.

My Meteor Template looks like this (I'm extending an example from the excellent 'Discovering Meteor' book) -

<template name="postsList"> 
<div class="posts">
   <div class='row-fluid' style="margin-left:1%">
      {{breakInit}}
      {{#each posts}}
         <div class="span3">
           {{> postItem}}
         </div>
         {{breakNow}}
      {{/each}}
   </div>
</div> 
</template>

The JavaScript for the Helpers look like this -

Template.postsList.breakInit = function() {
Template.postsList.docCount = 0 ;
};

Template.postsList.breakNow = function() {
count=Template.postsList.docCount + 1 ;
result="";
if ( count == 4 ) {
    count = 0 ;
    Template.postsList.docCount = count ;
    result="</div><div class=row>" ;
};
Template.postsList.docCount = count ;
return new Handlebars.SafeString(result);
};

This all appears to work, at least in terms of counting the elements output by the #each, returning the </div><div class=row> to start a new row and resetting the counter... However... the returned HTML to end the current row and start the next does not appear to be handled by Bootstrap (or Meteor or my browser) as I expect it to. It appears to be re-ordered as <div class=row></div>. See this screen-cap from Inspector in FireFox (code outputs 6 elements, 4 in first row, 2 in second) -

<div id="main" class="row-fluid">
  <div class="posts">
    <div class="row">
      <div class="span3"> … </div>
      <div class="span3"> … </div>
      <div class="span3"> … </div>
      <div class="span3"> … </div>
      <div class="row"> … </div>  <-- The problem...
      <div class="span3"> … </div>
      <div class="span3"> … </div>
    </div>
  </div>
</div>

Notice the <div class=row>...</div> in the middle of the spans? Doesn't look right, it should be closing the previous 'row' DIV and starting the next one. Can anyone suggest either a fix for my code or an alternative method for popluating a grid using dynamic data in Meteor?

Share Improve this question edited May 23, 2017 at 10:30 CommunityBot 11 silver badge asked Sep 17, 2013 at 8:21 AndyAndy 631 silver badge3 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

You can group your data before it gets rendered:

Template.projectList.helpers({
    projects: function () {
        all = Projects.find({}).fetch();
        chunks = [];
        size = 4;
        while (all.length > size) {
            chunks.push({ row: all.slice(0, size)});
            all = all.slice(size);
        }
        chunks.push({row: all});
        return chunks;
    }
});

<template name="projectList">
  {{#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>

The trouble lies in trying to add invalid HTML (</div><div class=row>). Even as a DocumentFragment, it's not valid (in general, difference between a Document and DocumentFragment is that a Document can only have a single document element (root node, like <html> for example), whereas a DocumentFragment can have multiple document elements).

So, when Spark tries to process your string and stuff it in the DOM, it gets automatically corrected. It's beyond Spark's control too, the browser DOM does that.

What you'll need to do is do an each nested within another each. The first will iterate over rows, the second over the columns for that row.

Some pseudo-code:

{{#each rows}}
    <div class="row-fluid">
        {{#each posts row}}
            <div class="span3">
                {{> postItem}}
            </div>
        {{/each}}
    </div>
{{/each}}

Template.postsList.rows = function () {
    // 1. Get cursor of posts (cursor = posts.find({...});
    // 2. Get count from cursor (count = cursor.count());
    // 3. Divide count by desired columns per row, then Math.ceil it (I think!)
    // 4. Return an array of objects each containing a "row" key, with some various values (current row probably, count, etc)
};

Template.postsList.posts = function (row) {
    // Return a cursor of posts that is offset and limited (see meteor docs) based on values found in the row object
};

Hope that's enough to get you going.

EDIT: In step 3 (divide count by desired columns per row), you could potentially have this number e from the template instead so you're not mixing those details between code and templates. For example: {{#each rows 4}}.

The less plicated solution is simply using an adaption of the Foundation Grid System

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

It follows a better approach, where you define the column count once and all elements will follow that rule and layout dynamically.

<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>
发布评论

评论列表(0)

  1. 暂无评论