Closed pekour closed 3 years ago
Hello,
I had the same need for a checkbox column and since wicket doesn't provide one out of the box, I created my own implementation:
See if it helps
public class CheckboxColumn extends AbstractColumn {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_WIDTH = 43;
public CheckboxColumn() {
super("", DEFAULT_WIDTH);
}
public CheckboxColumn(String title) {
super(title, DEFAULT_WIDTH);
}
public CheckboxColumn(String title, int width) {
super(title, width);
}
@Override
public String getAttributes() {
return "{ \"class\" : \"custom-checkbox\"}";
}
@Override
public String toString() {
StringBuilder result = new StringBuilder(super.toString());
result.append(", ");
BuilderUtils.append(result, "selectable", true);
return result.toString();
}
}
Now that I think about it you also need to add this ajax behavior to catch the checked event: This goes on your datatable behaviour and binds with the change event:
protected JQueryAjaxBehavior onCheckedAjaxBehavior(IJQueryAjaxAware source) {
return new JQueryAjaxBehavior(source) {
private static final long serialVersionUID = 1L;
@Override
protected CallbackParameter[] getCallbackParameters() {
return new CallbackParameter[] {
CallbackParameter.context("e"),
CallbackParameter.resolved("values", "this.selectedKeyNames()")
};
}
@Override
protected JQueryEvent newEvent() {
return new CheckedEvent();
}
};
}
And the event:
public class CheckedEvent extends JQueryEvent {
private final StringValue selectedLines;
public CheckedEvent() {
selectedLines = RequestCycleUtils.getQueryParameterValue("values");
}
public String getSelectedLines() {
return selectedLines.toString();
}
Thank you very much. It really gave be a column of checkboxes! I'm still not sure how to bind the behaviour to change event, but hope it is available somewhere in documentation
Hello,
It's a bit complicated. You need to bind a behavior like the following to your (customized) Datatable: This behavior acts for 3 types of events (but you only need one the change event).
public abstract class CustomDataTableBehavior extends DataTableBehavior {
private static final long serialVersionUID = 1L;
// Kendo UI Grid event names -- DO NOT CHANGE --
private static final String SORTING_EVENT_NAME = "sort";
private static final String COLUMN_RESIZE_EVENT_NAME = "columnResize";
private static final String ON_CHANGE_EVENT = "change";
private final JQueryAjaxBehavior onSortingAjaxBehavior;
private final JQueryAjaxBehavior onColumnResizeAjaxBehavior;
private final JQueryAjaxBehavior onCheckedAjaxBehavior;
private final CustomDataTableListener listener;
/**
*
* @param selector
* @param options
* @param columns
* @param listener
*/
public CustomDataTableBehavior(String selector, Options options, IModel<List<IColumn>> columns, CustomDataTableListener listener) {
super(selector, options, columns, listener);
this.listener = listener;
this.onSortingAjaxBehavior = onSortingAjaxBehavior(this);
this.onColumnResizeAjaxBehavior = onColumnResizeAjaxBehavior(this);
this.onCheckedAjaxBehavior = onCheckedAjaxBehavior(this);
}
@Override
public void onConfigure(Component component) {
super.onConfigure(component);
this.setOption(SORTING_EVENT_NAME, this.onSortingAjaxBehavior.getCallbackFunction());
this.setOption(COLUMN_RESIZE_EVENT_NAME, this.onColumnResizeAjaxBehavior.getCallbackFunction());
this.setOption(ON_CHANGE_EVENT, this.onCheckedAjaxBehavior.getCallbackFunction());
}
@Override
public void bind(Component component) {
super.bind(component);
component.add(this.onSortingAjaxBehavior);
component.add(this.onColumnResizeAjaxBehavior);
component.add(this.onCheckedAjaxBehavior);
}
@Override
public void onAjax(AjaxRequestTarget target, JQueryEvent event) {
if (event instanceof SortingEvent) {
SortingEvent e = (SortingEvent) event;
this.listener.onSorting(target, e.getColumnName(), e.getDirection());
} else if (event instanceof ColumnResizeEvent) {
ColumnResizeEvent e = (ColumnResizeEvent) event;
this.listener.columnResize(target, e.getColumnName(), e.getNewWidth(), e.getOldWidth());
} else if (event instanceof CheckedEvent) {
CheckedEvent e = (CheckedEvent) event;
this.listener.onChecked(target, e.getSelectedLines());
} else {
super.onAjax(target, event);
}
}
protected JQueryAjaxBehavior onSortingAjaxBehavior(IJQueryAjaxAware source) {
return new JQueryAjaxBehavior(source) {
private static final long serialVersionUID = 1L;
@Override
protected CallbackParameter[] getCallbackParameters() {
return new CallbackParameter[] {
CallbackParameter.context("e"),
CallbackParameter.resolved("columnName", "e.sort.field"),
CallbackParameter.resolved("direction", "e.sort.dir")
};
}
@Override
protected JQueryEvent newEvent() {
return new SortingEvent();
}
};
}
protected JQueryAjaxBehavior onColumnResizeAjaxBehavior(IJQueryAjaxAware source) {
return new JQueryAjaxBehavior(source) {
private static final long serialVersionUID = 1L;
@Override
protected CallbackParameter[] getCallbackParameters() {
return new CallbackParameter[] {
CallbackParameter.context("e"),
CallbackParameter.resolved("columnName", "e.column.field"),
CallbackParameter.resolved("newWidth", "e.newWidth"),
CallbackParameter.resolved("oldWidth", "e.oldWidth")
};
}
@Override
protected JQueryEvent newEvent() {
return new ColumnResizeEvent();
}
};
}
protected JQueryAjaxBehavior onCheckedAjaxBehavior(IJQueryAjaxAware source) {
return new JQueryAjaxBehavior(source) {
private static final long serialVersionUID = 1L;
@Override
protected CallbackParameter[] getCallbackParameters() {
return new CallbackParameter[] {
CallbackParameter.context("e"),
CallbackParameter.resolved("values", "this.selectedKeyNames()")
};
}
@Override
protected JQueryEvent newEvent() {
return new CheckedEvent();
}
};
}
}
Then in your datatable your need to Implement an IDataTableListener and 'listen' for the change event. This is the interface:
public interface CustomDataTableListener extends IDataTableListener {
void onSorting(AjaxRequestTarget target, String columnName, String direction);
void columnResize(AjaxRequestTarget target, String columnName, String newWidth, String oldWidth);
void onChecked(AjaxRequestTarget target, String selectedLines);
}
Hi Haritos, I had a quick look at your code, seems very good! Congrats! :)
Alexander, the way event binding works is described in the wiki section....
Sebastien, do you mean this Wiki section? https://github.com/sebfz1/wicket-jquery-ui/wiki
Hello Sebastien and thank you for the kind words! Perhaps wicket-kendo-ui can provide a checkbox column by default for anyone who needs it in the future. I will be happy to contribute to the code.
Yes, I meant this one... Unfortunately, it is not where I was thinking.... Strange. I will look asap...
Sebastian, do you mean this Wiki section? https://github.com/sebfz1/wicket-jquery-ui/wiki
Yes, absolutely! Thank you very much!
Hello Sebastien and thank you for the kind words! Perhaps wicket-kendo-ui
can provide a checkbox column by default for anyone who needs it in the future. I will be happy to contribute to the code.
That's great! One final piece of code is the following behavior that allows the 'checking' of the checkbox when clicking anywhere on the row. Only problem is that the table must have ID=dataTable for the JS to work, but the code can be optimized to work with any kendo table.
public class SelectRowOnClickDataBoundBehavior extends DataBoundBehavior {
private static final long serialVersionUID = 1L;
@Override
protected String getDataBoundCallback() {
return "function(e) { "+
" function checkboxClick(e) {" +
" if ($(e.target).hasClass('k-checkbox-label') || $(e.target).hasClass('k-button')) {" +
" return;" +
" }" +
" var row = $(e.target).closest('tr');" +
" var checkbox = $(row).find('.k-checkbox');" +
" checkbox.click();" +
" };"+
" var grid = jQuery('#dataTable').data('kendoGrid');" +
" var rows = grid.tbody.find(\"[role='row']\");" +
" rows.unbind('click');" +
" rows.on('click', checkboxClick);" +
"}";
}
}
Thank you, @haritos30. What is the proper approach to replacing the default DataTableBehaviour by a custom one? Should one override newWidgetBehavior method or what?
That's correct . You override the newWidgetBehavior method so that it returns your custom behaviour. Make sure your table also implements the CustomDataTableListener and pass this to the behaviour constructor. Eg:
...
@Override
public JQueryBehavior newWidgetBehavior(String selector) {
return new CustomDataTableBehavior(selector, this.options, this.getModel(), this) {
private static final long serialVersionUID = 1L;
@Override
protected long getRowCount() {
return /* your table */.this.getRowCount();
}
@Override
protected CharSequence getProviderUrl() {
return /* your table */.this.getCallbackUrl();
}
@Override
protected JQueryAjaxBehavior newCommandAjaxBehavior(IJQueryAjaxAware source, CommandButton button) {
return /* your table*/.this.newCommandAjaxBehavior(source, button);
}
}
}
That's great! One final piece of code is the following behavior that allows the 'checking' of the checkbox when clicking anywhere on the row.
How do I add properly this behaviour to the table? When I do simple table.add(new SelectRowOnClickDataBoundBehavior())
, I receive JS error in Wicket Ajax Debug Window error Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: TypeError: $w is undefined,
:
function() {var $w = jQuery('#datatable6f').data('kendoGrid'); $w.bind('dataBound', function(e) { function checkboxClick(e)....
that's because JS is looking for a table with id datatable6f (and can't find it) which looks like an ID generated by wicket. Did you set an ID in your table element in the HTML code and used this id in your JS code? eg something like this:
<div id="dataTable" style="margin-right: 1em;" wicket:id="DataTable">[datatable]</div>
Also you need to add your behavior during initialization so override method onInitialise()
and do it there.
Thanks for hint! Nope, I didn't set the id manually. more likely that I set the behaviour too late to the table (after initialization)
Hi @haritos30 , @sebfz1
I would need this feature as well. Would be cool to get this into the main branch. Can you guys get this wrapped up for a PR?
Hi Manfred,
Except if I missed something, I don't think I got the PR yet...
@haritos30 https://github.com/haritos30, will you be able to manage it? Otherwise I will dig into it...
On Mon, Jan 11, 2021, 18:19 Manfred Bergmann notifications@github.com wrote:
Hi @haritos30 https://github.com/haritos30 , @sebfz1 https://github.com/sebfz1
I would need this feature as well. Would be cool to get this into the main branch. Can you guys get this wrapped up for a PR?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sebfz1/wicket-jquery-ui/issues/327#issuecomment-757780184, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANDHGDTV2DAYCR6TBMUHATSZK7D7ANCNFSM4VEBRNKA .
Hi Sebastien.
I don't think I got the PR yet
Yes, I know. :)
@haritos30 could look into it?
Hi guys,
I will open a PR today, however we will probably need a wiki page with a working example to make life easier for the developers (done)
Pull request is ready.
Thanks! I will have a look asap!
Deployed 8.10.1-SNAPSHOT
, please give it a try and I will roll a release...
See https://github.com/sebfz1/wicket-jquery-ui/pull/328 for usage
Hello
I need rows in DataTable to be multi-selectable, ideally using checkboxes (with additional "Select All" checkbox on the top of checkbox column). What would be the best approach to implementing this feature? Perhaps, there are any easier-to-implement alternatives?
I'm still on 8.x version