【问题标题】:Populating Bootstrap grid with dynamic data using #each in Meteor在 Meteor 中使用 #each 使用动态数据填充 Bootstrap 网格
【发布时间】:2013-09-21 14:11:49
【问题描述】:

首先感谢您的帮助并原谅我幼稚的 Meteor 和 Bootstrap 技能。我遇到了与here 提出的问题类似的问题,该问题产生了一些建议但没有解决方案。我想使用#each 在 Meteor 模板中使用来自 MongoDB 的数据填充 BootStrap 网格。由于 BootStrap 网格有 12 列,我想每行显示 4 个“单元格”,我相信我需要 -

  1. 使用 .
  2. 创建一行
  3. 在...元素...内输出四个数据元素
  4. 用 . 关闭“行 div”。
  5. 使用 ... 创建下一行
  6. 冲洗并从第 2 步开始重复。

使用从数组/集合返回数据的 {{#each...}} 块执行第 2 步。

我的 Meteor 模板看起来像这样(我正在从优秀的“Discovering Meteor”一书中扩展一个示例)-

<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>

Helper 的 JavaScript 如下所示 -

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);
};

这一切似乎都有效,至少在计算#each 输出的元素方面,返回&lt;/div&gt;&lt;div class=row&gt; 以开始新行并重置计数器......但是......返回的 HTML 结束当前行并开始下一行似乎没有像我期望的那样由 Bootstrap(或 Meteor 或我的浏览器)处理。它似乎被重新排序为&lt;div class=row&gt;&lt;/div&gt;。在 FireFox 中查看 Inspector 的屏幕截图(代码输出 6 个元素,第一行 4 个,第二行 2 个)-

<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>

注意到跨度中间的&lt;div class=row&gt;...&lt;/div&gt; 了吗?看起来不对,它应该关闭前一个“行”DIV 并开始下一个。谁能建议修复我的代码或使用 Meteor 中的动态数据填充网格的替代方法?

【问题讨论】:

    标签: javascript twitter-bootstrap grid meteor


    【解决方案1】:

    问题在于尝试添加无效的 HTML (&lt;/div&gt;&lt;div class=row&gt;)。即使作为 DocumentFragment,它也是无效的(通常,Document 和 DocumentFragment 之间的区别在于 Document 只能有一个文档元素(根节点,例如 &lt;html&gt;),而 DocumentFragment 可以有多个文档元素) .

    因此,当 Spark 尝试处理您的字符串并将其填充到 DOM 中时,它会自动更正。它也超出了 Spark 的控制范围,浏览器 DOM 会这样做。

    您需要做的是将一个 each 嵌套在另一个 each 中。第一个将遍历行,第二个遍历该行的列。

    一些伪代码:

    {{#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
    };
    

    希望这足以让你继续前进。

    编辑:在第 3 步中(将计数除以每行所需的列数),您可能会将这个数字改为来自模板,因此您不会在代码和模板之间混合这些细节。例如:{{#each rows 4}}

    【讨论】:

    • 非常感谢 matb 和 Jim,非常感谢。这两种不同的方法都教会了我一些东西。我会给他们两个去。我认为从 JS 帮助程序返回的 HTML 是一个纯字符串(就好像我正在从 perl CGI 向浏览器打印一个字符串),但我看到给定 Spark 的情况并非如此。干杯,安迪
    【解决方案2】:

    您可以在呈现数据之前对其进行分组:

    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>
    

    【讨论】:

    • 谢谢吉姆,这是一个很好的解决方案,我会试试看。感谢您的帮助。
    • 很好的解决方案,我建议我在编辑我的解决方案时提出同样的建议:允许将size 作为参数传递给projects 助手,所以4不是在代码中硬编码,而是在模板中指定(因为您使用的是带有 span4 等的引导程序,所以在模板中最有意义)
    • 感谢修复,matb33
    【解决方案3】:

    不太复杂的解决方案是简单地使用基础网格系统的改编

    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>
    

    【讨论】:

      猜你喜欢
      • 2013-08-29
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 2020-09-16
      相关资源
      最近更新 更多