Column Chooser"
m |
m (correct highlight (via JWB)) |
||
(130 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{Template:Smalltalk_Author| | {{Template:Smalltalk_Author| | ||
|author=Sam Chuang, Engineer, Potix Corporation | |author=Sam Chuang, Engineer, Potix Corporation | ||
− | |date= | + | |date=June 18, 2013 |
|version=ZK 6.5 and later | |version=ZK 6.5 and later | ||
}} | }} | ||
− | |||
== Introduction == | == Introduction == | ||
− | + | By default, in a ZK Grid or Listbox, you can click the arrow on the header menu to select the columns to hide or to display. When there are a lot of columns, a Columnchooser can be very convenient for arranging these columns. Columnchooser is a popup component that shows a dialog of columns, grouped by column visibility. <br/><br/> | |
+ | Columnchooser's dialog box is done easily by putting up two listboxes and a few buttons: | ||
− | [[File:Column_Chooser_Firstlook_Default.png]] | + | [[File:Column_Chooser_Firstlook_Default.png]] <br/> |
− | + | * Left Listbox: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Drag_Hidden_Column_to_Visible_Column hidden columns that support drag and drop] | |
− | Columnchooser is | + | * Right Listbox: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Drag_Visible_Column_to_Hidden_Column visible columns that support drag and drop] |
+ | * Add button: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Add_to_Visible_Column change selected hidden column to visible] | ||
+ | * Remove button: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Remove_Visible_Column change selected visible column to hidden] | ||
+ | * Move Up button: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Move_Visible_Column_Up move selected visible column up] | ||
+ | * Move Down button: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Move_Visible_Column_Down move selected visible column down] | ||
+ | * OK button: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#OK confirm changes] | ||
+ | * Cancel button: [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Cancel cancel changes] | ||
+ | <br/> | ||
+ | Columnchooser is designed to work with any tabular components, which means you can easily integrate it with [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Grid_with_Columnchooser_Demo Grid] and [http://books.zkoss.org/wiki/Small_Talks/2013/June/Column_Chooser#Listbox_with_Columnchooser_Demo_.28MVC.29 Listbox]. | ||
+ | Another important feature of Columnchooser is that it's based on ZK MVVM which means that the UI (dialog) it can be easily customizable without touching ViewModel's code. <br/> | ||
[[File:Column_Chooser_Firstlook_Custom.png]] | [[File:Column_Chooser_Firstlook_Custom.png]] | ||
− | == | + | == How it Works == |
===Button=== | ===Button=== | ||
====OK==== | ====OK==== | ||
− | The OK button is used | + | The OK button is used for confirming modified changes. If user doesn't click '''OK''', the modification will be lost and reverted back to previous state. |
− | + | Demonstration: | |
* Original view | * Original view | ||
[[File:Column_Chooser_OK_BUTTON_1.png]] | [[File:Column_Chooser_OK_BUTTON_1.png]] | ||
− | * After modification, | + | * After modification, '''OK''' to confirm. |
[[File:Column_Chooser_OK_BUTTON_2.png]] | [[File:Column_Chooser_OK_BUTTON_2.png]] | ||
* Result | * Result | ||
Line 28: | Line 37: | ||
====Cancel==== | ====Cancel==== | ||
− | + | '''Cancel''' is used to revert to previous state. | |
− | + | Demonstration: | |
* Original view | * Original view | ||
[[File:Column_Chooser_Cancel_BUTTON_1.png]] | [[File:Column_Chooser_Cancel_BUTTON_1.png]] | ||
− | * After modification, click '''Cancel''' button to revert | + | * After modification, click '''Cancel''' button to revert and not save your changes |
[[File:Column_Chooser_Cancel_BUTTON_2.png]] | [[File:Column_Chooser_Cancel_BUTTON_2.png]] | ||
* Result | * Result | ||
Line 39: | Line 48: | ||
====Add to Visible Column==== | ====Add to Visible Column==== | ||
− | + | '''Add''' button is used to move a hidden column to become a visible column | |
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Select a column, then click | + | * Select a column, then click '''Add''' |
[[File:Column_Chooser_Add_BUTTON_2.png]] | [[File:Column_Chooser_Add_BUTTON_2.png]] | ||
− | * Click OK | + | * Click '''OK''' to confirm |
[[File:Column_Chooser_Add_BUTTON_3.png]] | [[File:Column_Chooser_Add_BUTTON_3.png]] | ||
* Result | * Result | ||
Line 52: | Line 61: | ||
====Remove Visible Column==== | ====Remove Visible Column==== | ||
− | + | '''Remove''' button is used to move a visible column to become a hidden column | |
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Select a visible column, then click | + | * Select a visible column, then click '''Remove''' |
[[File:Column_Chooser_Remove_BUTTON_2.png]] | [[File:Column_Chooser_Remove_BUTTON_2.png]] | ||
− | * Click OK | + | * Click '''OK''' to confirm |
[[File:Column_Chooser_Remove_BUTTON_3.png]] | [[File:Column_Chooser_Remove_BUTTON_3.png]] | ||
* Result | * Result | ||
Line 65: | Line 74: | ||
====Move Visible Column Up==== | ====Move Visible Column Up==== | ||
− | + | '''Move Up''' button is used to change column order, move selected column upwards. | |
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Select a visible column, then click | + | * Select a visible column, then click ''Move Up''' |
[[File:Column_Chooser_MoveUp_BUTTON_2.png]] | [[File:Column_Chooser_MoveUp_BUTTON_2.png]] | ||
− | * Click OK | + | * Click '''OK''' to confirm |
[[File:Column_Chooser_MoveUp_BUTTON_3.png]] | [[File:Column_Chooser_MoveUp_BUTTON_3.png]] | ||
* Result | * Result | ||
[[File:Column_Chooser_MoveUp_BUTTON_4.png]] | [[File:Column_Chooser_MoveUp_BUTTON_4.png]] | ||
+ | |||
====Move Visible Column Down==== | ====Move Visible Column Down==== | ||
− | + | '''Move Down''' button is used to change column order, move selected column down. | |
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Select a visible column, then click | + | * Select a visible column, then click '''Move Down''' |
[[File:Column_Chooser_MoveDown_BUTTON_2.png]] | [[File:Column_Chooser_MoveDown_BUTTON_2.png]] | ||
− | * Click OK | + | * Click '''OK''' to confirm |
[[File:Column_Chooser_MoveDown_BUTTON_3.png]] | [[File:Column_Chooser_MoveDown_BUTTON_3.png]] | ||
* Result | * Result | ||
− | [[File: | + | [[File:Column_Chooser_MoveUp_BUTTON_4.png]] |
===Drag & Drop=== | ===Drag & Drop=== | ||
====Drag Hidden Column to Visible Column==== | ====Drag Hidden Column to Visible Column==== | ||
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Drag hidden column | + | * Drag the hidden column and drop it to the visible column area |
[[File:Column_Chooser_Drag_to_Visible_2.png]] | [[File:Column_Chooser_Drag_to_Visible_2.png]] | ||
− | * Click OK | + | * Click '''OK''' to confirm |
[[File:Column_Chooser_Drag_to_Visible_3.png]] | [[File:Column_Chooser_Drag_to_Visible_3.png]] | ||
* Result | * Result | ||
Line 104: | Line 114: | ||
====Drag Visible Column to Hidden Column==== | ====Drag Visible Column to Hidden Column==== | ||
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Drag visible column | + | * Drag a visible column and drop it to the hidden column area |
− | [[File: | + | [[File:Column_Chooser_Drag_to_Hidden _2.png]] |
− | * Click OK | + | * Click '''OK''' to confirm |
− | [[File: | + | [[File:Column_Chooser_Drag_to_Hidden_3.png]] |
* Result | * Result | ||
− | [[File: | + | [[File:Column_Chooser_Drag_to_Hidden_4.png]] |
====Drag Column and Drop on Any Column==== | ====Drag Column and Drop on Any Column==== | ||
− | + | Demonstration: | |
* Original view | * Original view | ||
− | [[File: | + | [[File:Column_Chooser_OK_BUTTON_1.png]] |
− | * Drag visible column | + | * Drag visible column and drop it to the '''Birth''' column |
[[File:Column_Chooser_Drag_and_Drop_2.png]] | [[File:Column_Chooser_Drag_and_Drop_2.png]] | ||
− | * Click OK | + | * Click '''OK''' to confirm |
[[File:Column_Chooser_Drag_and_Drop_3.png]] | [[File:Column_Chooser_Drag_and_Drop_3.png]] | ||
* Result | * Result | ||
Line 127: | Line 137: | ||
==Usage== | ==Usage== | ||
+ | ===Specify Visible Columns and Hidden Columns=== | ||
+ | Invoke ''Columnchooser.setVisibleColumns(List<String> columns)'' and ''Columnchooser.setHiddenColumns(List<String> columns)'' to setup the columns. <br/> | ||
+ | |||
+ | ZUL | ||
+ | <source lang="xml" highlight="2,3"> | ||
+ | <columnchooser | ||
+ | visibleColumns="@load(vm.visibleColumnLabels)" | ||
+ | hiddenColumns="@load(vm.hiddenColumnLabels)" /> | ||
+ | </source> | ||
+ | |||
+ | Java | ||
+ | <source lang="java" highlight="1,5"> | ||
+ | public ArrayList<String> getVisibleColumnLabels() { | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | public ArrayList<String> getHiddenColumnLabels() { | ||
+ | ... | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ===Open Dialog=== | ||
+ | ''Columnchooser''' is a popup component, invoke ''Columnchooser.open(Component ref, String position)'' to open a dialog. | ||
+ | |||
===Event=== | ===Event=== | ||
+ | When user makes a change and confirms the change, ''Columnchooser'' will fire a '''ColumnVisibilityChangeEvent''' event named '''onColumnVisibilityChange''' | ||
+ | |||
+ | ZUL | ||
+ | <source lang="xml" highlight="4,5,6"> | ||
+ | <columnchooser | ||
+ | visibleColumns="@load(vm.visibleColumnLabels)" | ||
+ | hiddenColumns="@load(vm.hiddenColumnLabels)" | ||
+ | onColumnVisibilityChange="@command('doColumnVisibilityChange', | ||
+ | visibleColumns=event.visibleColumns, | ||
+ | hiddenColumns=event.hiddenColumns)"></columnchooser> | ||
+ | </source> | ||
+ | |||
+ | Java | ||
+ | <source lang="java" highlight="2,3,4"> | ||
+ | @Command | ||
+ | public void doColumnVisibilityChange( | ||
+ | @BindingParam("visibleColumns") List<String> visibleColumns, | ||
+ | @BindingParam("hiddenColumns") List<String> hiddenColumns) { | ||
+ | ... | ||
+ | } | ||
+ | </source> | ||
+ | |||
===Template=== | ===Template=== | ||
====Default==== | ====Default==== | ||
− | ====Custom==== | + | The ''Columnchooser'' contains a default implementation: |
+ | [https://github.com/samchuang/zkcolumnchooser/blob/master/src/main/resources/web/zul/columnchooser.zul columnchooser.zul] | ||
+ | <source lang="xml" highlight="4,9,18"> | ||
+ | <zk xmlns:n="native"> | ||
+ | <vlayout | ||
+ | apply="org.zkoss.bind.BindComposer" | ||
+ | viewModel="@id('vm') @init('org.zkoss.addon.columnchooser.impl.ColumnchooserViewModel')"> | ||
+ | <n:span>Choose the fields to display.</n:span> | ||
+ | <hlayout> | ||
+ | <vlayout> | ||
+ | Available fields: | ||
+ | <listbox model="@load(vm.hiddenColumns)" width="150px" | ||
+ | height="200px" droppable="true" selectedItem="@bind(vm.selectedHiddenColumn)" | ||
+ | onDrop="@command('dropToHiddenColumns', column=event.dragged.value)"> | ||
+ | ... | ||
+ | </listbox> | ||
+ | </vlayout> | ||
+ | ... | ||
+ | <vlayout> | ||
+ | Displayed Columns: | ||
+ | <listbox model="@load(vm.visibleColumns)" width="150px" | ||
+ | height="200px" droppable="true" selectedItem="@bind(vm.selectedVisibleColumn)" | ||
+ | onDrop="@command('dropToVisibleColumns', column=event.dragged.value)"> | ||
+ | ... | ||
+ | </listbox> | ||
+ | </vlayout> | ||
+ | </hlayout> | ||
+ | <hbox pack="end" width="100%" spacing="5px"> | ||
+ | <button onClick="@command('ok')" label="OK" mold="trendy" width="75px"></button> | ||
+ | <button onClick="@command('cancel')" label="Cancel" mold="trendy" width="75px"></button> | ||
+ | </hbox> | ||
+ | </vlayout> | ||
+ | </zk> | ||
+ | </source> | ||
+ | |||
+ | The default implementation groups columns by column visibility into two listboxes. | ||
+ | |||
+ | ====Custom Template==== | ||
+ | =====Config template per instance===== | ||
+ | As the component is based on MVVM, developer can easily change the view by ''Columnchooser.setTemplate(String uri)'' | ||
+ | |||
+ | ZUL | ||
+ | <source lang="xml" highlight="1"> | ||
+ | <columnchooser template="/customColumnChooser.zul" | ||
+ | visibleColumns="@load(vm.visibleColumnLabels)" | ||
+ | hiddenColumns="@load(vm.hiddenColumnLabels)" | ||
+ | onColumnVisibilityChange="@command('doColumnVisibilityChange', | ||
+ | visibleColumns=event.visibleColumns, | ||
+ | hiddenColumns=event.hiddenColumns)"></columnchooser> | ||
+ | </source> | ||
+ | |||
+ | [https://github.com/samchuang/zkcolumnchooser/blob/master/src/test/webapp/customColumnChooser.zul customColumnChooser.zul] | ||
+ | <source lang="xml" highlight="2"> | ||
+ | <zk xmlns:n="native"> | ||
+ | <window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.zkoss.addon.columnchooser.impl.ColumnchooserViewModel')" | ||
+ | title="Edit Columns" border="normal" mode="highlighted" position="center"> | ||
+ | <vlayout spacing="5px"> | ||
+ | <label>Choose the fields to display.</label> | ||
+ | <hlayout spacing="10px"> | ||
+ | <vlayout> | ||
+ | Available fields: | ||
+ | <listbox model="@load(vm.hiddenColumns)" width="150px" | ||
+ | height="200px" droppable="true" selectedItem="@bind(vm.selectedHiddenColumn)" | ||
+ | onDrop="@command('dropToHiddenColumns', column=event.dragged.value)"> | ||
+ | ... | ||
+ | </listbox> | ||
+ | </vlayout> | ||
+ | ... | ||
+ | <vlayout> | ||
+ | Displayed Columns: | ||
+ | <listbox model="@load(vm.visibleColumns)" width="150px" | ||
+ | height="200px" droppable="true" selectedItem="@bind(vm.selectedVisibleColumn)" | ||
+ | onDrop="@command('dropToVisibleColumns', column=event.dragged.value)"> | ||
+ | ... | ||
+ | </listbox> | ||
+ | </vlayout> | ||
+ | </hlayout> | ||
+ | <hbox pack="end" width="100%" spacing="5px"> | ||
+ | <button onClick="@command('ok')" label="OK" mold="trendy" width="75px"></button> | ||
+ | <button onClick="@command('cancel')" label="Cancel" mold="trendy" width="75px"></button> | ||
+ | </hbox> | ||
+ | </vlayout> | ||
+ | </window> | ||
+ | </zk> | ||
+ | </source> | ||
+ | |||
+ | =====Config template globally===== | ||
+ | Change the template view globally by using library property '''org.zkoss.addon.columnchooser.template''' in zk.xml | ||
+ | |||
+ | <source lang="xml" highlight="2"> | ||
+ | <library-property> | ||
+ | <name>org.zkoss.addon.columnchooser.template</name> | ||
+ | <value>/customColumnChooser.zul</value> | ||
+ | </library-property> | ||
+ | </source> | ||
+ | |||
===View Model=== | ===View Model=== | ||
+ | The default template contains a default [https://github.com/samchuang/zkcolumnchooser/blob/master/src/main/java/org/zkoss/addon/columnchooser/impl/ColumnchooserViewModel.java ColumnchooserViewModel] that implements from [https://github.com/samchuang/zkcolumnchooser/blob/master/src/main/java/org/zkoss/addon/columnchooser/Columnchooser.java Columnchooser.ViewModel] | ||
− | ==Grid with Columnchooser Demo== | + | Develper can use customized ViewModel base on [https://github.com/samchuang/zkcolumnchooser/blob/master/src/main/java/org/zkoss/addon/columnchooser/impl/ColumnchooserViewModel.java ColumnchooserViewModel] |
− | === | + | |
− | === | + | ==Use Columnchooser in Grid and Listbox== |
+ | Columnchooser supports both MVC and MVVM and can be easily integrated into ''Grid'' and ''Listbox''. In this section I will provide two simple examples to demonstrate how you can use ''Columnchooser'' with Grid in the MVVM way, and how you can use ''Columnchooser'' with ''Listbox'' in the MVC way. | ||
+ | |||
+ | ===Grid with Columnchooser Demo (MVVM)=== | ||
+ | |||
+ | [https://github.com/samchuang/zkcolumnchooser/blob/master/src/test/webapp/index.zul index.zul] | ||
+ | <source lang="xml" highlight="6,7,8,9,10,11,15,16,17,18,19,20,21,25,26,27,30,31,32,35,39,44"> | ||
+ | <zk> | ||
+ | <window apply="org.zkoss.bind.BindComposer" border="normal" | ||
+ | viewModel="@id('vm') @init('demo.ProfileViewModel')" hflex="1" vflex="1"> | ||
+ | <caption label="Column Chooser"> | ||
+ | <!-- default column chooser --> | ||
+ | <columnchooser id="columnchooser" | ||
+ | visibleColumns="@load(vm.visibleColumnLabels)" | ||
+ | hiddenColumns="@load(vm.hiddenColumnLabels)" | ||
+ | onColumnVisibilityChange="@command('doColumnVisibilityChange', | ||
+ | visibleColumns=event.visibleColumns, | ||
+ | hiddenColumns=event.hiddenColumns)"></columnchooser> | ||
+ | <combobutton label="Column Chooser" | ||
+ | onClick="@command('openDefaultColumnChooser', ref=self)"> | ||
+ | <!-- custom column chooser --> | ||
+ | <columnchooser | ||
+ | template="/customColumnChooser.zul" | ||
+ | visibleColumns="@load(vm.visibleColumnLabels)" | ||
+ | hiddenColumns="@load(vm.hiddenColumnLabels)" | ||
+ | onColumnVisibilityChange="@command('doColumnVisibilityChange', | ||
+ | visibleColumns=event.visibleColumns, | ||
+ | hiddenColumns=event.hiddenColumns)"></columnchooser> | ||
+ | </combobutton> | ||
+ | </caption> | ||
+ | <grid model="@load(vm.profiles)" height="500px"> | ||
+ | <columns children="@load(vm.visibleColumns)"> | ||
+ | <template name="children" var="columnInfo"> | ||
+ | <column label="@load(columnInfo.label)"></column> | ||
+ | </template> | ||
+ | </columns> | ||
+ | <template name="model" var="profile"> | ||
+ | <row children="@init(vm.visibleColumns) @template(each.templateName)"> | ||
+ | <template name="label" var="columnInfo"> | ||
+ | <label value="@load(profile[columnInfo.value])"></label> | ||
+ | </template> | ||
+ | <template name="birth" var="columnInfo"> | ||
+ | <datebox value="@load(profile[columnInfo.value])" | ||
+ | onChange="@command('setBirth', profile=profile, birth=event.target.value)"></datebox> | ||
+ | </template> | ||
+ | <template name="married" var="columnInfo"> | ||
+ | <checkbox checked="@load(profile[columnInfo.value])" | ||
+ | onCheck="@command('setMarried', profile=profile, married=event.checked)" | ||
+ | label="Married"></checkbox> | ||
+ | </template> | ||
+ | <template name="skills" var="columnInfo"> | ||
+ | <chosenbox model="@load(vm.allSkills)" | ||
+ | onSelect="@command('setSkills', profile=profile, skills=event.selectedObjects)" | ||
+ | selectedObjects="@load(profile[columnInfo.value])" hflex="true"> | ||
+ | <template name="model" var="item"> | ||
+ | <label value="@load(item)"></label> | ||
+ | </template> | ||
+ | </chosenbox> | ||
+ | </template> | ||
+ | </row> | ||
+ | </template> | ||
+ | </grid> | ||
+ | </window> | ||
+ | </zk> | ||
+ | </source> | ||
+ | * Line 7, 8: setup columns | ||
+ | * Line 16: customize columnchooser dialog | ||
+ | * Line 25 ~ 27: grid headers | ||
+ | * Line 30, 31, 32, 35, 39, 44: row content | ||
+ | |||
+ | [https://github.com/samchuang/zkcolumnchooser/blob/master/src/test/java/demo/ProfileViewModel.java ProfileViewModel.java] | ||
+ | <source lang="java" highlight="9,10,11,12,24,35,43,50"> | ||
+ | public class ProfileViewModel { | ||
+ | ... | ||
+ | @Wire | ||
+ | Columnchooser columnchooser; | ||
+ | |||
+ | @Init | ||
+ | public void init() { | ||
+ | _columns = new ArrayList<ColumnInfo>(); | ||
+ | _columns.add(new ColumnInfo("name", "Name", true, "label")); | ||
+ | _columns.add(new ColumnInfo("birth", "Birth", true, "birth")); | ||
+ | _columns.add(new ColumnInfo("married", "Marital status", false, "married")); | ||
+ | _columns.add(new ColumnInfo("skills", "Professional Skill", false, "skills")); | ||
+ | |||
+ | _data = provideData(); | ||
+ | } | ||
+ | |||
+ | @AfterCompose | ||
+ | public void afterCompose(@ContextParam(ContextType.VIEW) Component view) { | ||
+ | Selectors.wireComponents(view, this, false); | ||
+ | } | ||
+ | |||
+ | @Command | ||
+ | public void openDefaultColumnChooser(@BindingParam("ref") Component ref) { | ||
+ | columnchooser.open(ref, "after_end"); | ||
+ | } | ||
+ | |||
+ | public List<Profile> getProfiles() { | ||
+ | return _data; | ||
+ | } | ||
+ | |||
+ | public ArrayList<ColumnInfo> getVisibleColumns() { | ||
+ | return getColumns(Filter.VISIBLE); | ||
+ | } | ||
+ | |||
+ | public ArrayList<String> getVisibleColumnLabels() { | ||
+ | return transform(getVisibleColumns(), Transformer.TO_LABEL); | ||
+ | } | ||
+ | |||
+ | public ArrayList<ColumnInfo> getHiddenColumns() { | ||
+ | return getColumns(Filter.HIDDEN); | ||
+ | } | ||
+ | |||
+ | public ArrayList<String> getHiddenColumnLabels() { | ||
+ | return transform(getHiddenColumns(), Transformer.TO_LABEL); | ||
+ | } | ||
+ | |||
+ | @Command | ||
+ | @NotifyChange({"visibleColumns", "hiddenColumnLabels", | ||
+ | "profiles", "visibleColumnLabels", "hiddenColumnLabels"}) | ||
+ | public void doColumnVisibilityChange(@BindingParam("visibleColumns") List<String> visibleColumns, | ||
+ | @BindingParam("hiddenColumns") List<String> hiddenColumns) { | ||
+ | ... | ||
+ | } | ||
+ | ... | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | *Line 9 ~12: all columns of the grid | ||
+ | *Line 24: open columnchooser dialog | ||
+ | *Line 35, 43: column labels | ||
+ | *Line 50: columnchooser onColumnVisibilityChange event | ||
+ | |||
+ | ===Listbox with Columnchooser Demo (MVC)=== | ||
+ | |||
+ | [https://github.com/samchuang/zkcolumnchooser/blob/master/src/test/webapp/columnchooser-mvc.zul columnchooser-mvc.zul] | ||
+ | <source lang="xml" highlight="4"> | ||
+ | <zk> | ||
+ | <window title="Columnchooser with MVC" border="normal" apply="demo.ProfileCtrl"> | ||
+ | <button id="button" label="Column Chooser"></button> | ||
+ | <columnchooser id="columnchooser"></columnchooser> | ||
+ | <listbox id="listbox"> | ||
+ | <listhead id="listhead"> | ||
+ | </listhead> | ||
+ | </listbox> | ||
+ | </window> | ||
+ | </zk> | ||
+ | </source> | ||
+ | |||
+ | [https://github.com/samchuang/zkcolumnchooser/blob/master/src/test/java/demo/ProfileCtrl.java ProfileCtrl.java] | ||
+ | <source lang="xml" highlight="7, 21, 22, 28, 31,32,33,34,36,37,38,39,40,42"> | ||
+ | public class ProfileCtrl extends SelectorComposer<Component> { | ||
+ | |||
+ | @Wire | ||
+ | Button button; | ||
+ | |||
+ | @Wire | ||
+ | Columnchooser columnchooser; | ||
+ | |||
+ | @Wire | ||
+ | Listbox listbox; | ||
+ | |||
+ | List<Profile> profiles = Profiles.provideData(); | ||
+ | |||
+ | List<String> visibleColumns; | ||
+ | |||
+ | List<String> hiddenColumns; | ||
+ | @Override | ||
+ | public void doAfterCompose(Component comp) throws Exception { | ||
+ | super.doAfterCompose(comp); | ||
+ | ... | ||
+ | columnchooser.setVisibleColumns(visibleColumns); | ||
+ | columnchooser.setHiddenColumns(hiddenColumns); | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | @Listen("onClick=#button") | ||
+ | public void openColumnChooser() { | ||
+ | columnchooser.open(button, "end_before"); | ||
+ | } | ||
+ | |||
+ | @Listen("onColumnVisibilityChange=#columnchooser") | ||
+ | public void doColumnVisibilityChange(ColumnVisibilityChangeEvent event) { | ||
+ | visibleColumns = event.getVisibleColumns(); | ||
+ | hiddenColumns = event.getHiddenColumns(); | ||
+ | |||
+ | Listhead listhead = listbox.getListhead(); | ||
+ | listhead.getChildren().clear(); | ||
+ | for (String visibleColumn : visibleColumns) { | ||
+ | listhead.appendChild(new Listheader(visibleColumn)); | ||
+ | } | ||
+ | |||
+ | listbox.setModel(new ListModelList<Profile>(profiles)); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | * Line 21, 22: setup visible columns and hidden columns | ||
+ | * Line 28: open columnchooser dialog | ||
+ | * Line 31 ~ 34: reset columns | ||
+ | * Line 36 ~ 40: redraw listbox headers | ||
+ | * Line 42: redraw listbox | ||
==Summary== | ==Summary== | ||
+ | |||
+ | In this smalltalk I have demonstrated how developers can easily create a ''Columnchooser'' component by putting up basic ZK components and how they can easily integrate this component with Grid, Listbox and any other tabular components.<br/> | ||
+ | |||
+ | ''Columnchooser'' is implemented in the MVVM way allowing application developers to customize the View extremely easily without changing the ViewModel. On the other hand it supports both MVC and MVVM so you can apply it in whatever pattern you prefer for your application. | ||
==Download== | ==Download== | ||
+ | You can get the complete source of the example used in this smalltalk from its [https://github.com/samchuang/zkcolumnchooser github] or download the Columnchooser binary file [https://dl.dropboxusercontent.com/u/12117053/columnchooser-bin-0.6.0-2013-08-15.zip here] | ||
+ | |||
{{Template:CommentedSmalltalk_Footer| | {{Template:CommentedSmalltalk_Footer| | ||
|name=Potix Corporation | |name=Potix Corporation | ||
}} | }} |
Latest revision as of 04:20, 20 January 2022
Sam Chuang, Engineer, Potix Corporation
June 18, 2013
ZK 6.5 and later
Introduction
By default, in a ZK Grid or Listbox, you can click the arrow on the header menu to select the columns to hide or to display. When there are a lot of columns, a Columnchooser can be very convenient for arranging these columns. Columnchooser is a popup component that shows a dialog of columns, grouped by column visibility.
Columnchooser's dialog box is done easily by putting up two listboxes and a few buttons:
- Left Listbox: hidden columns that support drag and drop
- Right Listbox: visible columns that support drag and drop
- Add button: change selected hidden column to visible
- Remove button: change selected visible column to hidden
- Move Up button: move selected visible column up
- Move Down button: move selected visible column down
- OK button: confirm changes
- Cancel button: cancel changes
Columnchooser is designed to work with any tabular components, which means you can easily integrate it with Grid and Listbox.
Another important feature of Columnchooser is that it's based on ZK MVVM which means that the UI (dialog) it can be easily customizable without touching ViewModel's code.
How it Works
Button
OK
The OK button is used for confirming modified changes. If user doesn't click OK, the modification will be lost and reverted back to previous state.
Demonstration:
- Original view
- After modification, OK to confirm.
- Result
Cancel
Cancel is used to revert to previous state.
Demonstration:
- Original view
- After modification, click Cancel button to revert and not save your changes
- Result
Add to Visible Column
Add button is used to move a hidden column to become a visible column
Demonstration:
- Original view
- Select a column, then click Add
- Click OK to confirm
- Result
Remove Visible Column
Remove button is used to move a visible column to become a hidden column
Demonstration:
- Original view
- Select a visible column, then click Remove
- Click OK to confirm
- Result
Move Visible Column Up
Move Up button is used to change column order, move selected column upwards.
Demonstration:
- Original view
- Select a visible column, then click Move Up'
- Click OK to confirm
- Result
Move Visible Column Down
Move Down button is used to change column order, move selected column down.
Demonstration:
- Original view
- Select a visible column, then click Move Down
- Click OK to confirm
- Result
Drag & Drop
Drag Hidden Column to Visible Column
Demonstration:
- Original view
- Drag the hidden column and drop it to the visible column area
- Click OK to confirm
- Result
Drag Visible Column to Hidden Column
Demonstration:
- Original view
- Drag a visible column and drop it to the hidden column area
- Click OK to confirm
- Result
Drag Column and Drop on Any Column
Demonstration:
- Original view
- Drag visible column and drop it to the Birth column
- Click OK to confirm
- Result
Usage
Specify Visible Columns and Hidden Columns
Invoke Columnchooser.setVisibleColumns(List<String> columns) and Columnchooser.setHiddenColumns(List<String> columns) to setup the columns.
ZUL
<columnchooser
visibleColumns="@load(vm.visibleColumnLabels)"
hiddenColumns="@load(vm.hiddenColumnLabels)" />
Java
public ArrayList<String> getVisibleColumnLabels() {
...
}
public ArrayList<String> getHiddenColumnLabels() {
...
}
Open Dialog
Columnchooser' is a popup component, invoke Columnchooser.open(Component ref, String position) to open a dialog.
Event
When user makes a change and confirms the change, Columnchooser will fire a ColumnVisibilityChangeEvent event named onColumnVisibilityChange
ZUL
<columnchooser
visibleColumns="@load(vm.visibleColumnLabels)"
hiddenColumns="@load(vm.hiddenColumnLabels)"
onColumnVisibilityChange="@command('doColumnVisibilityChange',
visibleColumns=event.visibleColumns,
hiddenColumns=event.hiddenColumns)"></columnchooser>
Java
@Command
public void doColumnVisibilityChange(
@BindingParam("visibleColumns") List<String> visibleColumns,
@BindingParam("hiddenColumns") List<String> hiddenColumns) {
...
}
Template
Default
The Columnchooser contains a default implementation: columnchooser.zul
<zk xmlns:n="native">
<vlayout
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('org.zkoss.addon.columnchooser.impl.ColumnchooserViewModel')">
<n:span>Choose the fields to display.</n:span>
<hlayout>
<vlayout>
Available fields:
<listbox model="@load(vm.hiddenColumns)" width="150px"
height="200px" droppable="true" selectedItem="@bind(vm.selectedHiddenColumn)"
onDrop="@command('dropToHiddenColumns', column=event.dragged.value)">
...
</listbox>
</vlayout>
...
<vlayout>
Displayed Columns:
<listbox model="@load(vm.visibleColumns)" width="150px"
height="200px" droppable="true" selectedItem="@bind(vm.selectedVisibleColumn)"
onDrop="@command('dropToVisibleColumns', column=event.dragged.value)">
...
</listbox>
</vlayout>
</hlayout>
<hbox pack="end" width="100%" spacing="5px">
<button onClick="@command('ok')" label="OK" mold="trendy" width="75px"></button>
<button onClick="@command('cancel')" label="Cancel" mold="trendy" width="75px"></button>
</hbox>
</vlayout>
</zk>
The default implementation groups columns by column visibility into two listboxes.
Custom Template
Config template per instance
As the component is based on MVVM, developer can easily change the view by Columnchooser.setTemplate(String uri)
ZUL
<columnchooser template="/customColumnChooser.zul"
visibleColumns="@load(vm.visibleColumnLabels)"
hiddenColumns="@load(vm.hiddenColumnLabels)"
onColumnVisibilityChange="@command('doColumnVisibilityChange',
visibleColumns=event.visibleColumns,
hiddenColumns=event.hiddenColumns)"></columnchooser>
<zk xmlns:n="native">
<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.zkoss.addon.columnchooser.impl.ColumnchooserViewModel')"
title="Edit Columns" border="normal" mode="highlighted" position="center">
<vlayout spacing="5px">
<label>Choose the fields to display.</label>
<hlayout spacing="10px">
<vlayout>
Available fields:
<listbox model="@load(vm.hiddenColumns)" width="150px"
height="200px" droppable="true" selectedItem="@bind(vm.selectedHiddenColumn)"
onDrop="@command('dropToHiddenColumns', column=event.dragged.value)">
...
</listbox>
</vlayout>
...
<vlayout>
Displayed Columns:
<listbox model="@load(vm.visibleColumns)" width="150px"
height="200px" droppable="true" selectedItem="@bind(vm.selectedVisibleColumn)"
onDrop="@command('dropToVisibleColumns', column=event.dragged.value)">
...
</listbox>
</vlayout>
</hlayout>
<hbox pack="end" width="100%" spacing="5px">
<button onClick="@command('ok')" label="OK" mold="trendy" width="75px"></button>
<button onClick="@command('cancel')" label="Cancel" mold="trendy" width="75px"></button>
</hbox>
</vlayout>
</window>
</zk>
Config template globally
Change the template view globally by using library property org.zkoss.addon.columnchooser.template in zk.xml
<library-property>
<name>org.zkoss.addon.columnchooser.template</name>
<value>/customColumnChooser.zul</value>
</library-property>
View Model
The default template contains a default ColumnchooserViewModel that implements from Columnchooser.ViewModel
Develper can use customized ViewModel base on ColumnchooserViewModel
Use Columnchooser in Grid and Listbox
Columnchooser supports both MVC and MVVM and can be easily integrated into Grid and Listbox. In this section I will provide two simple examples to demonstrate how you can use Columnchooser with Grid in the MVVM way, and how you can use Columnchooser with Listbox in the MVC way.
Grid with Columnchooser Demo (MVVM)
<zk>
<window apply="org.zkoss.bind.BindComposer" border="normal"
viewModel="@id('vm') @init('demo.ProfileViewModel')" hflex="1" vflex="1">
<caption label="Column Chooser">
<!-- default column chooser -->
<columnchooser id="columnchooser"
visibleColumns="@load(vm.visibleColumnLabels)"
hiddenColumns="@load(vm.hiddenColumnLabels)"
onColumnVisibilityChange="@command('doColumnVisibilityChange',
visibleColumns=event.visibleColumns,
hiddenColumns=event.hiddenColumns)"></columnchooser>
<combobutton label="Column Chooser"
onClick="@command('openDefaultColumnChooser', ref=self)">
<!-- custom column chooser -->
<columnchooser
template="/customColumnChooser.zul"
visibleColumns="@load(vm.visibleColumnLabels)"
hiddenColumns="@load(vm.hiddenColumnLabels)"
onColumnVisibilityChange="@command('doColumnVisibilityChange',
visibleColumns=event.visibleColumns,
hiddenColumns=event.hiddenColumns)"></columnchooser>
</combobutton>
</caption>
<grid model="@load(vm.profiles)" height="500px">
<columns children="@load(vm.visibleColumns)">
<template name="children" var="columnInfo">
<column label="@load(columnInfo.label)"></column>
</template>
</columns>
<template name="model" var="profile">
<row children="@init(vm.visibleColumns) @template(each.templateName)">
<template name="label" var="columnInfo">
<label value="@load(profile[columnInfo.value])"></label>
</template>
<template name="birth" var="columnInfo">
<datebox value="@load(profile[columnInfo.value])"
onChange="@command('setBirth', profile=profile, birth=event.target.value)"></datebox>
</template>
<template name="married" var="columnInfo">
<checkbox checked="@load(profile[columnInfo.value])"
onCheck="@command('setMarried', profile=profile, married=event.checked)"
label="Married"></checkbox>
</template>
<template name="skills" var="columnInfo">
<chosenbox model="@load(vm.allSkills)"
onSelect="@command('setSkills', profile=profile, skills=event.selectedObjects)"
selectedObjects="@load(profile[columnInfo.value])" hflex="true">
<template name="model" var="item">
<label value="@load(item)"></label>
</template>
</chosenbox>
</template>
</row>
</template>
</grid>
</window>
</zk>
- Line 7, 8: setup columns
- Line 16: customize columnchooser dialog
- Line 25 ~ 27: grid headers
- Line 30, 31, 32, 35, 39, 44: row content
public class ProfileViewModel {
...
@Wire
Columnchooser columnchooser;
@Init
public void init() {
_columns = new ArrayList<ColumnInfo>();
_columns.add(new ColumnInfo("name", "Name", true, "label"));
_columns.add(new ColumnInfo("birth", "Birth", true, "birth"));
_columns.add(new ColumnInfo("married", "Marital status", false, "married"));
_columns.add(new ColumnInfo("skills", "Professional Skill", false, "skills"));
_data = provideData();
}
@AfterCompose
public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
Selectors.wireComponents(view, this, false);
}
@Command
public void openDefaultColumnChooser(@BindingParam("ref") Component ref) {
columnchooser.open(ref, "after_end");
}
public List<Profile> getProfiles() {
return _data;
}
public ArrayList<ColumnInfo> getVisibleColumns() {
return getColumns(Filter.VISIBLE);
}
public ArrayList<String> getVisibleColumnLabels() {
return transform(getVisibleColumns(), Transformer.TO_LABEL);
}
public ArrayList<ColumnInfo> getHiddenColumns() {
return getColumns(Filter.HIDDEN);
}
public ArrayList<String> getHiddenColumnLabels() {
return transform(getHiddenColumns(), Transformer.TO_LABEL);
}
@Command
@NotifyChange({"visibleColumns", "hiddenColumnLabels",
"profiles", "visibleColumnLabels", "hiddenColumnLabels"})
public void doColumnVisibilityChange(@BindingParam("visibleColumns") List<String> visibleColumns,
@BindingParam("hiddenColumns") List<String> hiddenColumns) {
...
}
...
}
- Line 9 ~12: all columns of the grid
- Line 24: open columnchooser dialog
- Line 35, 43: column labels
- Line 50: columnchooser onColumnVisibilityChange event
Listbox with Columnchooser Demo (MVC)
<zk>
<window title="Columnchooser with MVC" border="normal" apply="demo.ProfileCtrl">
<button id="button" label="Column Chooser"></button>
<columnchooser id="columnchooser"></columnchooser>
<listbox id="listbox">
<listhead id="listhead">
</listhead>
</listbox>
</window>
</zk>
public class ProfileCtrl extends SelectorComposer<Component> {
@Wire
Button button;
@Wire
Columnchooser columnchooser;
@Wire
Listbox listbox;
List<Profile> profiles = Profiles.provideData();
List<String> visibleColumns;
List<String> hiddenColumns;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
...
columnchooser.setVisibleColumns(visibleColumns);
columnchooser.setHiddenColumns(hiddenColumns);
...
}
@Listen("onClick=#button")
public void openColumnChooser() {
columnchooser.open(button, "end_before");
}
@Listen("onColumnVisibilityChange=#columnchooser")
public void doColumnVisibilityChange(ColumnVisibilityChangeEvent event) {
visibleColumns = event.getVisibleColumns();
hiddenColumns = event.getHiddenColumns();
Listhead listhead = listbox.getListhead();
listhead.getChildren().clear();
for (String visibleColumn : visibleColumns) {
listhead.appendChild(new Listheader(visibleColumn));
}
listbox.setModel(new ListModelList<Profile>(profiles));
}
}
- Line 21, 22: setup visible columns and hidden columns
- Line 28: open columnchooser dialog
- Line 31 ~ 34: reset columns
- Line 36 ~ 40: redraw listbox headers
- Line 42: redraw listbox
Summary
In this smalltalk I have demonstrated how developers can easily create a Columnchooser component by putting up basic ZK components and how they can easily integrate this component with Grid, Listbox and any other tabular components.
Columnchooser is implemented in the MVVM way allowing application developers to customize the View extremely easily without changing the ViewModel. On the other hand it supports both MVC and MVVM so you can apply it in whatever pattern you prefer for your application.
Download
You can get the complete source of the example used in this smalltalk from its github or download the Columnchooser binary file here
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |