Orbeon Xforms: фильтрация элементов на основе флажка

У меня возникают проблемы с фильтрацией элементов с помощью Orbeon XForms. Ситуация в том, что у меня есть флажок, привязанный к экземпляру, экземпляр определяется как:

<xf:instance id="Include-model">
    <data>
        <value type="xs:string">true</value>
    </data>
</xf:instance>

и флажок объявлен как:

<xf:select ref="instance('Include-model')/value" selection="closed" appearance="full" >
    <xf:item>
        <xf:label>Include all</xf:label>
        <xf:value>true</xf:value>
    </xf:item>
</xf:select>

Таким образом, флажок изначально установлен.

Теперь у меня есть список элементов в другом экземпляре, определяемом как:

<xf:instance id="items-model">
    <Items>
        <Item>
           <value>1</value>
           <status>Show</status>    
        </Item>
        <Item>
           <value>2</value>
           <status>Show</status>    
        </Item>
        <Item>
           <value>3</value>
           <status>Hide</status>    
        </Item>
    </Items>
</xf:instance>

и связанная привязка:

<xforms:bind id="items-bind" nodeset="instance('items-model')Items/Item">

Эти элементы отображаются в повторителе

<xforms:repeat bind="items-bind" appearance="xxforms:internal">
    .....

Мне нужно иметь возможность фильтровать элементы в зависимости от состояния флажка. Если он отмечен, то привязка должна включать все элементы, если она не отмечена, привязка должна содержать только элементы, для которых в качестве значений указано «Показать» в элементе состояния.

Пожалуйста, помогите и спасите мне то немногое, что у меня осталось.

ТИА


person Faithypop    schedule 28.09.2012    source источник


Ответы (1)


Во-первых, давайте избавимся от нескольких проблем:

<xforms:bind id="items-bind" nodeset="instance('items-model')Items/Item">

не является правильным выражением XPath. Вместо этого используйте:

<xforms:bind id="items-bind" nodeset="instance('items-model')/Item">

Это указывает на все предметы. Это потому, что instance('items-model') уже указывает на корневой элемент экземпляра, поэтому instance('items-model') указывает на элемент Items.

Во-вторых, незначительная вещь: вы, вероятно, не хотите, чтобы appearance="xxforms:internal" повторялось. Это расширение используется для того, чтобы указать механизму XForms не генерировать HTML-разметку для данного элемента управления XForms. Он не поддерживается на xforms:repeat, но все равно лучше загромождать им код.

Третье, тоже незначительное: вам, вероятно, не нужна аннотация type="xs:string", так как по умолчанию значения считаются строками.

Наконец, я бы не стал использовать для экземпляров идентификаторы, оканчивающиеся на -model. Вместо этого я бы использовал -instance. Еще одна незначительная вещь, но она может немного сбивать с толку. Так что давайте вместо этого назовем их «основной экземпляр» и «элемент-экземпляр».

При этом ключевым моментом является написание выражения XPath для фильтрации элементов. Теперь одна проблема заключается в том, что ваша привязка указывает на все элементы. Поэтому, если вы ссылаетесь на свою привязку с атрибутом bind, который просто ссылается на привязку по идентификатору, вы не можете фильтровать.

Одним из решений является использование функции расширения Orbeon xxf:bind(), которая позволяет ссылаться на привязки из выражений XPath:

xxf:bind('items-bind')[instance('main-instance')/value = 'true' or status = 'Show']

Затем ваш повтор становится:

<xf:repeat ref="xxf:bind('items-bind')[instance('main-instance')/value = 'true' or status = 'Show']">

Вот полный пример, который работает:

<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
        xmlns:xf="http://www.w3.org/2002/xforms"
        xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
        xmlns:ev="http://www.w3.org/2001/xml-events"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xh:head>
        <xf:model>
            <xf:instance id="main-instance">
                <data>
                    <value>true</value>
                </data>
            </xf:instance>
            <xf:instance id="items-instance">
                <Items>
                    <Item>
                        <value>1</value>
                        <status>Show</status>
                    </Item>
                    <Item>
                        <value>2</value>
                        <status>Show</status>
                    </Item>
                    <Item>
                        <value>3</value>
                        <status>Hide</status>
                    </Item>
                </Items>
            </xf:instance>
            <xf:bind id="items-bind" nodeset="instance('items-instance')/Item"/>
        </xf:model>
    </xh:head>
    <xh:body>
        <xf:select ref="instance('main-instance')/value" appearance="full">
            <xf:item>
                <xf:label>Include all</xf:label>
                <xf:value>true</xf:value>
            </xf:item>
        </xf:select>
        <xf:repeat ref="xxf:bind('items-bind')[instance('main-instance')/value = 'true' or status = 'Show']">
            <xh:div>
                <xf:output value="concat('Value: ', value, ', status: ', status)"/>
            </xh:div>
        </xf:repeat>
    </xh:body>
</xh:html>
person ebruchez    schedule 30.09.2012
comment
Работает как абсолютный шарм! Спасибо за очень подробный отзыв, очень признателен. - person Faithypop; 01.10.2012