有条件地在Polymer </content>中包装<content>插入点

时间:2015-02-04 19:41:40

标签: polymer web-component

我正在尝试制作一个Polymer元素,它是一个简单的盒子或容器,有3个主要元素:标题,正文和页脚。页眉和页脚是可选的,但如果它们在那里,我想把它们放在它们周围。

我的问题是如何在<content>插入点周围放置一个包装元素,只有当select属性与某些内容匹配时才会出现?

我的代码是这样的(不起作用):

<polymer-element name="example-card" attributes="">
    <template>
        <paper-shadow z="1">
            <div vertical layout>
                <div class="card card-header" hidden?="{{!$.header}}">
                    <content id="header" select=".header"></content>
                </div>
                <div class="card card-body">
                    <content id="body" select=":not(.footer)"></content>
                </div>
                <div class="card card-footer" hidden?="{{!$.footer}}">
                    <content id="footer" select=".footer"></content>
                </div>
            </div>
        </paper-shadow>
    </template>
    <script>
        Polymer({});
    </script>
</polymer-element>

预期使用 - 此示例中没有页脚:

<example-card>
    <div class="header">Header...</div>
    <div>Body...</div>
</example-card>

我要么隐藏包装div,如果没有选择它的内容,要么将它放在<template if="...">中以完全摆脱轻型DOM。上面的hidden?表达式无效。

我尝试了一些不同的事情但没有成功,包括:

hidden?="{{!$.footer.getDistributedNodes().length}}"

是否有任何方法可以有条件地包装插入点,具体取决于它们的选择是否匹配?也许我说这一切都错了。谢谢!

编辑:感谢Fuzzical Logic的帮助,这就是我修改后的版本,它使用lodash进行集合过滤,只选择直接子项的页眉和页脚类:

<polymer-element name="example-card" attributes="">
    <template>
        <paper-shadow z="1">
            <div vertical layout>
                <template if="{{showheader}}">
                    <div class="card card-header">
                        <content id="header" select=".header"></content>
                    </div>
                </template>
                <div class="card card-body">
                    <content select=":not(.footer)"></content>
                </div>
                <template if="{{showfooter}}">
                    <div class="card card-footer">
                        <content id="footer" select=".footer"></content>
                    </div>
                </template>
            </div>
        </paper-shadow>
    </template>
    <script>
    Polymer({

        domReady: function () {
            // Doesn't work in IE11...
            // this.showheader = this.querySelector(':scope > .header');
            // this.showfooter = this.querySelector(':scope > .footer');

            this.showheader = _.filter(this.children, function(e) { return e.className === "header"; }).length;
            this.showfooter = _.filter(this.children, function(e) { return e.className === "footer"; }).length;
        },
        publish: {
            showheader: {
                value: false,
                reflect: true
            },
            showfooter: {
                value: false,
                reflect: true
            }
        }

    });
    </script>
</polymer-element>

1 个答案:

答案 0 :(得分:2)

问题不在于hidden?无效。 $.header始终使用id === "header"(即this.$.header)解析为标头。这意味着它将永远是真实的。解决此问题的最简单方法是在domReady事件中设置检查子项的属性。

Polymer('example-card', {

    ... other element code ...

    domReady: function() {
        this.showheader = this.querySelector('.header');
        this.showfooter = this.querySelector('.footer');
    },
    publish: {
        showheader: {
            value: false,
            reflect: true
        },
        showfooter: {
            value: false,
            reflect: true
        }
    },

    ... other element code ...

});

为了使其正常工作,请按如下方式调整元素:

<div class="card card-header" hidden?="{{!showheader}}">
    <content id="header" select=".header"></content>
</div>
<div class="card card-footer" hidden?="{{!showfooter}}">
    <content id="footer" select=".footer"></content>
</div>

重要提示

以上domReady代码仅仅是一个示例,并不完整,可以从.header开始在树中找到任何content。执行此操作的正确方法是仅检查children