【问题标题】:this.findAll not working on sub-templatethis.findAll 不适用于子模板
【发布时间】:2014-06-06 11:56:03
【问题描述】:

当我尝试在选择器位于子模板中的模板上使用 this.findAll 时,findAll 什么也不返回。

这是 HTML:

<template name="products">
    {{#each productList}}
        {{> product }}
    {{/each}}
</template>
<template name="product">
    <div class="box">{{name}}</div>
</template>

这是 JS:

Template.products.helpers({
    productList: function() {
        var all = Products.find({}).fetch();
        return all;
    }
});
Template.products.rendered = function(){
    var boxes = this.findAll('.box');
    console.log(boxes.length);
}

box.length 的输出为 0。有什么想法可以获取“box”元素吗?

【问题讨论】:

    标签: meteor meteor-blaze


    【解决方案1】:

    根据findAll 的文档:

    只有模板内的元素及其子模板才能匹配选择器的部分内容。

    所以它应该适用于子模板。我用一组固定的产品尝试了这个,它起作用了,这意味着您只是看到调用rendered 和获取产品之间存在延迟。例如,如果你这样做:

    Template.products.events({
      'click .box': function (e, t) {
        var boxes = t.findAll('.box');
        console.log(boxes.length);
      }
    });
    

    然后,如果您单击其中一个框,您应该会看到记录到控制台的正确数字。简而言之,我认为测试可能只是无效的。如果您使用的是 Iron-router,您可以尝试为产品添加 waitOn - 这可以确保它们在渲染调用之前到达。

    【讨论】:

    • 查看实际页面,我确实观察到存在某种延迟。在产品出现在页面中之前,console.log 已经显示了输出。我确实使用 Iron-router,并且我使用 waitOn 来处理产品。加载所有产品后,我需要运行脚本。还有其他想法吗?
    • 这并不容易,因为在加载集合数据时,meteor 实际上并没有“完成”的概念。添加其他产品时会发生什么?如果答案是再次运行您的函数,那么我建议考虑使用product.rendered 而不是products.rendered 的方法。旁注 - 还值得一提的是,您始终可以在任一函数中使用 $('.box') 来获取页面上的所有框,尽管如果您有多个 products 模板实例,这可能没有意义。
    • 谢谢大卫!你给了我如何解决它的想法。一会儿我会公布答案。
    【解决方案2】:

    这是我在加载所有产品后运行脚本的操作。

    我已在所有产品中添加了 last_product 属性。

    Template.products.helpers({
        productList: function() {
            var all = Products.find({}).fetch();
            var total = all.length;
            var ctr = 0;
            all.forEach(function(doc){
                doc.last_product = false;
    
                ctr++;
                if(ctr == total)
                {
                    doc.last_product = true;
                }
                return doc;
            });
            return all;
        }
    });
    

    然后,我使用“Template.product”代替“Template.products”来检测是否呈现了最后一个产品。渲染最后一个产品后,运行脚本。

    Template.product.rendered = function(){
        if(this.data.last_product){
            var boxes = $('.pbox');
            console.log(boxes.length);
        }
    }
    

    boxes.length 现在具有正确的长度。

    感谢大卫的创意!

    【讨论】:

      【解决方案3】:

      这是正确答案。我已将此添加到我的 Iron-router 路由中:

      action : function () {
          if (this.ready()) {
              this.render();
          }
      }
      

      在我尝试解决其他问题时从https://stackoverflow.com/a/23576039/130237 找到答案。

      【讨论】:

        猜你喜欢
        • 2017-02-09
        • 1970-01-01
        • 2018-06-09
        • 2021-07-26
        • 2015-07-23
        • 2013-01-07
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多