Условный перенос точек вставки ‹content› в Polymer

Я пытаюсь создать элемент Polymer, представляющий собой простую коробку или контейнер с тремя основными элементами: заголовком, телом и нижним колонтитулом. Верхний и нижний колонтитулы были бы необязательными, но если они есть, я хочу поместить их вокруг.

Мой вопрос заключается в том, как поместить элемент-оболочку вокруг точки вставки <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>

person Preston Landers    schedule 04.02.2015    source источник


Ответы (1)


Проблема не в том, что 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.

person Fuzzical Logic    schedule 04.02.2015
comment
Спасибо, это очень полезно. Очевидно, что под «не работает» я имел в виду, что мое выражение было недействительным, а не то, что hidden? было нарушено. В итоге я использовал domReady, который искал только детей. - person Preston Landers; 05.02.2015