Skip to content
Permalink
Fetching contributors…
Cannot retrieve contributors at this time
607 lines (564 sloc) 23.1 KB
title review notes details labels toc confluence tree_item_index history
HOWTO: Create a N-Level Select Widget - JSF UI
comment date status
2017-12-01
ok
Documentation page used on Nuxeo Studio. Check with NOS team before deleting or moving.
howto
excerpt level tool topics
Learn how to create a selection widget with 3 levels by contributing a "template widget" in Studio.
Advanced
Studio
Layout, Widget
content-review-lts2017
widget
layout
howto
studio
layout-widgets-component
excerpt
jsf-ui
true
ajs-parent-page-id ajs-parent-page-title ajs-space-key ajs-space-name canonical canonical_source page_id shortlink shortlink_source source_link
19235623
Layout & Widget How-To Index
NXDOC
Nuxeo Platform Developer Documentation
How+to+Create+a+N-Level+Select+Widget
6029528
2ABc
/display/NXDOC/How+to+Create+a+N-Level+Select+Widget
400
author date message version
Anahide Tchertchian
2015-05-04 12:06
26
author date message version
Anahide Tchertchian
2015-04-03 10:04
NXP-16605: templates update again (wrong version edited before...)
25
author date message version
Anahide Tchertchian
2015-04-03 09:58
NXP-16605: another template update for incmplete selection related bugs
24
author date message version
Anahide Tchertchian
2015-04-02 17:05
fix the "onchange" event to "change" (again...)
23
author date message version
Anahide Tchertchian
2015-03-25 21:37
fix the "onchange" event to "change"
22
author date message version
Anahide Tchertchian
2015-03-23 17:57
fix the "onchange" event to "change"
21
author date message version
Anahide Tchertchian
2015-03-06 10:26
NXP-16605: update templates to fix "Incomplete selections are not allowed" validation message issue
20
author date message version
Solen Guitter
2014-12-01 22:30
19
author date message version
Anahide Tchertchian
2014-11-28 17:41
18
author date message version
Anahide Tchertchian
2014-11-28 17:37
NXDOC-414: update samples for JSF2 migration
17
author date message version
Manon Lumeau
2014-09-12 15:39
16
author date message version
Manon Lumeau
2014-09-11 17:59
15
author date message version
Solen Guitter
2014-08-25 11:39
Remove 5.4 reference
14
author date message version
Solen Guitter
2014-08-25 10:31
13
author date message version
Solen Guitter
2013-09-02 14:54
12
author date message version
Anahide Tchertchian
2012-05-11 11:24
Migrated to Confluence 4.0
11
author date message version
Anahide Tchertchian
2012-05-11 11:24
fix size value on multiselect example
10
author date message version
Laurent Doguin
2012-03-02 17:32
9
author date message version
Laurent Doguin
2012-03-02 17:20
add template widget configuration screenshot
8
author date message version
Solen Guitter
2011-09-05 18:45
7
author date message version
Alain Escaffre
2011-05-25 20:11
6
author date message version
Alain Escaffre
2011-03-23 11:27
5
author date message version
Anahide Tchertchian
2011-03-03 19:17
4
author date message version
Anahide Tchertchian
2011-03-03 18:36
3
author date message version
Anahide Tchertchian
2011-03-03 18:16
2
author date message version
Alain Escaffre
2011-03-02 20:27
1

{{{multiexcerpt 'JSF-UI-required' page='generic-multi-excerpts'}}}

{{! excerpt}} In this page we provide samples to have a selection widget with 3 levels by contributing a "template widget" in Studio. Each sample code below is the sample for one widget that has a different behavior (described before the code). {{! /excerpt}}

To create and use a new widget:

  1. Copy-paste the sample of your choice in a file that you call, for instance, "3_level_select_widget.xhtml".

    {{#> callout type='tip' }}

    Of course you can modify the samples below to add other levels, or other behaviors. You just need to be familiar with facelets and JSF.

    {{/callout}}

  2. Upload this file in the Resources > Widgets section. The widget is created. You can now use it on layouts and forms.

  3. In the layout of the document type where you want to use the widget, drag and drop the Template widget from the Advanced Widgets category on the right.

  4. Edit the properties of the widget. Here are the properties specific to custom widgets that you need to fill in.

    • Template: choose the XHTML file you have just uploaded.
    • Fields: add one field and put the XPath of the field you want to update. For instance, "dc:coverage".
    • Custom properties configuration: in our sample, you can (should) add those three properties labels and put the value you need:
      • localize
      • required
      • directoryName (should be the name of the vocabulary that holds the values that are displayed).

![]({{file name='ConfigureTemplateWidget.png'}} ?w=450,border=true)

Widget Samples

Mono-Select 3-Level Widget

Sample example on 3 levels with widget property directoryName filled with the directory name (mono select):

<f:subview
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jstl/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:a4j="http://richfaces.org/a4j"
  xmlns:fn="http://java.sun.com/jsp/jstl/functions"
  xmlns:nxu="http://nuxeo.org/nxweb/util"
  xmlns:nxdir="http://nuxeo.org/nxdirectory"
  xmlns:nxl="http://nuxeo.org/nxforms/layout"
  xmlns:nxp="http://nuxeo.org/nxweb/pdf"
  id="#{widget.id}">
<c:if test="#{nxl:isLikeViewMode(widget.mode)}">

  <nxdir:chainSelect id="#{widget.id}_viewselect" size="3" value="#{field}"
    displayValueOnly="true" defaultRootKey="">
    <nxdir:chainSelectListbox index="0" size="0" directoryName="#{widget.properties['directoryName']}"
      localize="true" id="#{widget.id}_parent" displayObsoleteEntries="true" />
    <nxdir:chainSelectListbox index="1" size="0" directoryName="#{widget.properties['directoryName']}"
      localize="true" id="#{widget.id}_parent2" displayObsoleteEntries="true" />
    <nxdir:chainSelectListbox index="2" size="0" directoryName="#{widget.properties['directoryName']}"
      localize="true" id="#{widget.id}_child" displayObsoleteEntries="true" />
    <nxdir:chainSelectStatus display="value" id="#{widget.id}_status" />
  </nxdir:chainSelect>

</c:if>
<c:if test="#{widget.mode == 'edit'}">

  <nxdir:chainSelect size="3" value="#{field}"
    id="#{widget.id}_editselect" multiSelect="false"
    multiParentSelect="false"
    allowBranchSelection="#{widgetProperty_allowBranchSelection}"
    defaultRootKey="" required="#{widgetProperty_required}">
    <a4j:region id="#{widget.id}_region">
      <nxdir:chainSelectListbox index="0" size="1"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent" ordering="label">
        <f:ajax event="change"
          render="#{widget.id}_parent2 #{widget.id}_child #{widget.id}_message"
          execute="@this" />
      </nxdir:chainSelectListbox>
      <nxdir:chainSelectListbox index="1" size="1"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent2" ordering="label">
        <a4j:ajax event="change"
          render="#{widget.id}_child #{widget.id}_message"
          execute="@region" />
      </nxdir:chainSelectListbox>
    </a4j:region>
    <nxdir:chainSelectListbox size="1" index="2"
      directoryName="#{widget.properties['directoryName']}"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_child" ordering="label" />
  </nxdir:chainSelect>
  <h:message styleClass="errorMessage" for="#{widget.id}_editselect"
    id="#{widget.id}_message" />

</c:if>
</f:subview>

Multi-Select 3-Level Widget

Sample example on 3 levels with widget property directoryName filled with the directory name (multi select):

<f:subview
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jstl/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:a4j="http://richfaces.org/a4j"
  xmlns:fn="http://java.sun.com/jsp/jstl/functions"
  xmlns:nxu="http://nuxeo.org/nxweb/util"
  xmlns:nxdir="http://nuxeo.org/nxdirectory"
  xmlns:nxl="http://nuxeo.org/nxforms/layout"
  xmlns:nxp="http://nuxeo.org/nxweb/pdf"
  id="#{widget.id}">
<c:if test="#{nxl:isLikeViewMode(widget.mode)}">

  <nxdir:chainSelect id="#{widget.id}_viewselect" size="3"
    value="#{field}" displayValueOnly="true" multiSelect="true"
    defaultRootKey="">
    <nxdir:chainSelectListbox index="0" size="4"
    directoryName="#{widget.properties['directoryName']}"
    localize="#{widget.properties['localize']}"
    id="#{widget.id}_parent" />
    <nxdir:chainSelectListbox size="4"
      directoryName="#{widget.properties['directoryName']}" index="1"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_parent2" />
    <nxdir:chainSelectListbox size="4"
      directoryName="#{widget.properties['directoryName']}" index="2"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_child" />
    <nxdir:chainSelectStatus display="value" id="#{widget.id}_status" />
  </nxdir:chainSelect>

</c:if>
<c:if test="#{widget.mode == 'edit'}">

  <a4j:region id="#{widget.id}_region" renderRegionOnly="true">
    <nxdir:chainSelect size="3" value="#{field}"
      id="#{widget.id}_editselect" multiSelect="true"
      multiParentSelect="true"
      allowBranchSelection="#{widgetProperty_allowBranchSelection}"
      defaultRootKey="" required="#{widgetProperty_required}">
      <nxdir:chainSelectListbox index="0" size="4"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent" ordering="label">
        <a4j:ajax event="change"
          render="#{widget.id}_parent2 #{widget.id}_child #{widget.id}_message"
          execute="@this" />
      </nxdir:chainSelectListbox>
      <nxdir:chainSelectListbox index="1" size="4"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent2" ordering="label">
        <a4j:ajax event="change"
          render="#{widget.id}_child #{widget.id}_message"
          immediate="true" />
      </nxdir:chainSelectListbox>
      <nxdir:chainSelectListbox size="4" index="2"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_child" ordering="label" />
      <a4j:commandButton value="#{messages['command.add']}"
        styleClass="button" immediate="true"
        actionListener="#{chainSelectActions.add}"
        render="#{widget.id}_status #{widget.id}_message"
        id="#{widget.id}_add" />
      <br />
      <nxdir:chainSelectStatus display="value"
        entryCssStyle="background-color: #DDEEFF"
        label="#{messages['label.chainSelect.selection']}"
        id="#{widget.id}_status">
        <f:facet name="removeButton">
          <a4j:commandButton
            actionListener="#{chainSelectActions.delete}"
            execute="@this" render="#{widget.id}_status"
            image="/icons/toggle_minus.png"
            id="#{widget.id}_delete" />
        </f:facet>
      </nxdir:chainSelectStatus>
    </nxdir:chainSelect>
  </a4j:region>
  <h:message styleClass="errorMessage" for="#{widget.id}_editselect"
    id="#{widget.id}_message" />

</c:if>
</f:subview>

Complete Examples with CSV (Plain) and PDF Rendering

Mono-Select Widget

<f:subview
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jstl/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:a4j="http://richfaces.org/a4j"
  xmlns:fn="http://java.sun.com/jsp/jstl/functions"
  xmlns:nxu="http://nuxeo.org/nxweb/util"
  xmlns:nxdir="http://nuxeo.org/nxdirectory"
  xmlns:nxl="http://nuxeo.org/nxforms/layout"
  xmlns:nxp="http://nuxeo.org/nxweb/pdf"
  id="#{widget.id}">
<c:if test="#{nxl:isLikePlainMode(widget.mode)}">
<f:subview rendered="#{not empty field}"><nxdir:directoryEntryOutput
  directoryName="#{widget.properties['directoryName']}"
    value="#{fn:split(field, '/')[0]}"
    localize="#{widget.properties['localize']}" />/<nxdir:directoryEntryOutput
    directoryName="#{widget.properties['directoryName']}"
    value="#{fn:split(field, '/')[1]}"
    localize="#{widget.properties['localize']}" />/<nxdir:directoryEntryOutput
    directoryName="#{widget.properties['directoryName']}"
    value="#{field}"
    localize="#{widget.properties['localize']}"
    keySeparator="/" />
</f:subview>
</c:if>
<c:if test="#{widget.mode == 'pdf'}">
  <nxp:html>
   <nxdir:chainSelect id="#{widget.id}_viewselect" size="3" value="#{field}"
    displayValueOnly="true" defaultRootKey="">
     <nxdir:chainSelectListbox index="0" size="0" directoryName="#{widget.properties['directoryName']}"
       localize="true" id="#{widget.id}_parent" displayObsoleteEntries="true" />
     <nxdir:chainSelectListbox index="1" size="0" directoryName="#{widget.properties['directoryName']}"
       localize="true" id="#{widget.id}_parent2" displayObsoleteEntries="true" />
     <nxdir:chainSelectListbox index="2" size="0" directoryName="#{widget.properties['directoryName']}"
       localize="true" id="#{widget.id}_child" displayObsoleteEntries="true" />
     <nxdir:chainSelectStatus display="value" id="#{widget.id}_status" />
   </nxdir:chainSelect>
  </nxp:html>
</c:if>
<c:if test="#{nxl:isLikeViewMode(widget.mode)}">

  <nxdir:chainSelect id="#{widget.id}_viewselect" size="3" value="#{field}"
    displayValueOnly="true" defaultRootKey="">
    <nxdir:chainSelectListbox index="0" size="0" directoryName="#{widget.properties['directoryName']}"
      localize="true" id="#{widget.id}_parent" displayObsoleteEntries="true" />
    <nxdir:chainSelectListbox index="1" size="0" directoryName="#{widget.properties['directoryName']}"
      localize="true" id="#{widget.id}_parent2" displayObsoleteEntries="true" />
    <nxdir:chainSelectListbox index="2" size="0" directoryName="#{widget.properties['directoryName']}"
      localize="true" id="#{widget.id}_child" displayObsoleteEntries="true" />
    <nxdir:chainSelectStatus display="value" id="#{widget.id}_status" />
  </nxdir:chainSelect>

</c:if>
<c:if test="#{widget.mode == 'edit'}">

  <nxdir:chainSelect size="3" value="#{field}"
    id="#{widget.id}_editselect" multiSelect="false"
    multiParentSelect="false"
    allowBranchSelection="#{widgetProperty_allowBranchSelection}"
    defaultRootKey="" required="#{widgetProperty_required}">
    <a4j:region id="#{widget.id}_region">
      <nxdir:chainSelectListbox index="0" size="1"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent" ordering="label">
        <f:ajax event="change"
          render="#{widget.id}_parent2 #{widget.id}_child #{widget.id}_message"
          execute="@this" />
      </nxdir:chainSelectListbox>
      <nxdir:chainSelectListbox index="1" size="1"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent2" ordering="label">
        <a4j:ajax event="change"
          render="#{widget.id}_child #{widget.id}_message"
          execute="@region" />
      </nxdir:chainSelectListbox>
    </a4j:region>
    <nxdir:chainSelectListbox size="1" index="2"
      directoryName="#{widget.properties['directoryName']}"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_child" ordering="label" />
  </nxdir:chainSelect>
  <h:message styleClass="errorMessage" for="#{widget.id}_editselect"
    id="#{widget.id}_message" />

</c:if>
</f:subview>

Multi-Select Widget

<f:subview
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jstl/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:a4j="http://richfaces.org/a4j"
  xmlns:fn="http://java.sun.com/jsp/jstl/functions"
  xmlns:nxu="http://nuxeo.org/nxweb/util"
  xmlns:nxdir="http://nuxeo.org/nxdirectory"
  xmlns:nxl="http://nuxeo.org/nxforms/layout"
  xmlns:nxp="http://nuxeo.org/nxweb/pdf"
  id="#{widget.id}">
<c:if test="#{nxl:isLikePlainMode(widget.mode)}"><nxu:inputList
  value="#{field}" model="chainModel"><nxdir:directoryEntryOutput
  directoryName="#{widget.properties['directoryName']}"
    value="#{fn:split(chainModel.rowData, '/')[0]}"
    localize="#{widget.properties['localize']}" />/<nxdir:directoryEntryOutput
    directoryName="#{widget.properties['directoryName']}"
    value="#{fn:split(chainModel.rowData, '/')[1]}"
    localize="#{widget.properties['localize']}" />/<nxdir:directoryEntryOutput
    directoryName="#{widget.properties['directoryName']}"
    value="#{chainModel.rowData}"
    localize="#{widget.properties['localize']}"
    keySeparator="/" /><h:outputText
  rendered="#{chainModel.rowIndex != chainModel.rowCount -1}" value=", " /></nxu:inputList>
</c:if>
<c:if test="#{widget.mode == 'pdf'}">
  <nxp:html>
    <nxdir:chainSelect id="#{widget.id}_viewselect" size="3"
      value="#{field}" displayValueOnly="true" multiSelect="true"
      defaultRootKey="">
      <nxdir:chainSelectListbox index="0" size="4"
      directoryName="#{widget.properties['directoryName']}"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_parent" />
      <nxdir:chainSelectListbox size="4"
        directoryName="#{widget.properties['directoryName']}" index="1"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent2" />
      <nxdir:chainSelectListbox size="4"
        directoryName="#{widget.properties['directoryName']}" index="2"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_child" />
      <nxdir:chainSelectStatus display="value" id="#{widget.id}_status" />
    </nxdir:chainSelect>
    </nxp:html>
</c:if>
<c:if test="#{nxl:isLikeViewMode(widget.mode)}">

  <nxdir:chainSelect id="#{widget.id}_viewselect" size="3"
    value="#{field}" displayValueOnly="true" multiSelect="true"
    defaultRootKey="">
    <nxdir:chainSelectListbox index="0" size="4"
    directoryName="#{widget.properties['directoryName']}"
    localize="#{widget.properties['localize']}"
    id="#{widget.id}_parent" />
    <nxdir:chainSelectListbox size="4"
      directoryName="#{widget.properties['directoryName']}" index="1"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_parent2" />
    <nxdir:chainSelectListbox size="4"
      directoryName="#{widget.properties['directoryName']}" index="2"
      localize="#{widget.properties['localize']}"
      id="#{widget.id}_child" />
    <nxdir:chainSelectStatus display="value" id="#{widget.id}_status" />
  </nxdir:chainSelect>

</c:if>
<c:if test="#{widget.mode == 'edit'}">

  <a4j:region id="#{widget.id}_region" renderRegionOnly="true">
    <nxdir:chainSelect size="3" value="#{field}"
      id="#{widget.id}_editselect" multiSelect="true"
      multiParentSelect="true"
      allowBranchSelection="#{widgetProperty_allowBranchSelection}"
      defaultRootKey="" required="#{widgetProperty_required}">
      <nxdir:chainSelectListbox index="0" size="4"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent" ordering="label">
        <a4j:ajax event="change"
          render="#{widget.id}_parent2 #{widget.id}_child #{widget.id}_message"
          execute="@this" />
      </nxdir:chainSelectListbox>
      <nxdir:chainSelectListbox index="1" size="4"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_parent2" ordering="label">
        <a4j:ajax event="change"
          render="#{widget.id}_child #{widget.id}_message"
          immediate="true" />
      </nxdir:chainSelectListbox>
      <nxdir:chainSelectListbox size="4" index="2"
        directoryName="#{widget.properties['directoryName']}"
        localize="#{widget.properties['localize']}"
        id="#{widget.id}_child" ordering="label" />
      <a4j:commandButton value="#{messages['command.add']}"
        styleClass="button" immediate="true"
        actionListener="#{chainSelectActions.add}"
        render="#{widget.id}_status #{widget.id}_message"
        id="#{widget.id}_add" />
      <br />
      <nxdir:chainSelectStatus display="value"
        entryCssStyle="backgroundcolor: #DDEEFF"
        label="#{messages['label.chainSelect.selection']}"
        id="#{widget.id}_status">
        <f:facet name="removeButton">
          <a4j:commandButton
            actionListener="#{chainSelectActions.delete}"
            execute="@this" render="#{widget.id}_status"
            image="/icons/toggle_minus.png"
            id="#{widget.id}_delete" />
        </f:facet>
      </nxdir:chainSelectStatus>
    </nxdir:chainSelect>
  </a4j:region>
  <h:message styleClass="errorMessage" for="#{widget.id}_editselect"
    id="#{widget.id}_message" />

</c:if>
</f:subview>
{{#> panel heading='Related How-Tos'}}
  • [How to Set a Default Date on a Field at Document Creation]({{page page='how-to-set-a-default-date-on-a-field-at-document-creation'}})
  • [Customize the Versioning and Comment Widget]({{page page='how-to-customize-the-versioning-and-comment-widget-on-document-edit-form'}})
  • [How to Add a JSF Form Validation]({{page page='how-to-add-a-jsf-form-validation'}})
  • [How-To Index]({{page page='how-to-index'}})

{{/panel}}

{{#> panel heading='Related Documentation'}}

  • [JSF UI Framework]({{page page='jsf-ui-framework'}})
  • [Form Layouts in Nuxeo Studio]({{page space='studio' page='form-layouts'}})
  • [Layout and Widgets]({{page page='layouts-and-widgets-forms-listings-grids'}})
  • [JSF UI Limitations]({{page page='jsf-ui-limitations'}})
  • [Widget Definitions]({{page page='widget-definitions'}})

{{/panel}}

You can’t perform that action at this time.