Disable Wicket CheckGroup without disabling the rest of the form - wicket

I have a form with a CheckGroup and a PropertyListView. Each item in the list view has a Check belonging to the check group and a AjaxFallbackLink. When I disable the check group, the whole form gets disabled including the links. Similarly, when I set visible to false, the whole form is not visible.
Form form = new Form("form");
CheckGroup checkGroup = new CheckGroup("checkGroup", checkList) {
#Override
protected void onConfigure() {
super.onConfigure();
setEnabled(isAuthorized());
}
};
checkGroup.add(new CheckGroupSelector("groupSelector"));
form.add(checkGroup);
PropertyListView<MyList> tableList = new PropertyListView<MyList>("table", new PropertyModel(lists, "myList")){
#Override
protected void populateItem(ListItem<OfacCustomerMatchFile> item) {
item.add(new Check("check", item.getModel(), checkGroup);
item.add(new AjaxFallbackLink("itemLink") { ... });
}
};
form.add(tableList);

You have to override #isEnabledHierarchy() on your links:
public boolean isEnabledInHierarchy()
{
return true;
}
Watch out, this can be dangerous since you are circumventing Wicket's default authorization handling.

Related

GWT DataGrid: use of CheckboxCell-selection and standard line mode selection at the same time

I'm using a GWT DataGrid with a MultiSelectionModel.
The selections of the items of the grid should be achieved by
a) a CheckboxColumn with a CheckboxCell
and additionally at the same time by
b) the standard line mode selection-model (by clicking on the rest of the line).
With the CheckboxColumn the user should be enabled to multi-select different entries. But when clicking somewhere else on the datagrid-lines, a single-line-selection-policy should be done, that means, if a multiple-selection was done before using the checkboxes, this selection should be resetted and only the the clicked line should be selected afterwards.
This is what I have. Does anyone know how to enable CheckBox-Mode and line-selection-mode at the same time?
public class JobDataGrid extends DataGrid<Job>
{
private MultiSelectionModel<Job> selectionModel;
private Column<Job, Boolean> checkboxColumn;
private TextColumn<Job> idColumn;
private TextColumn<Job> titleColumn;
private TextColumn<Job> timestampColumn;
private TexTColumn<Job> ...
public JobDataGrid ()
{
super ();
checkboxColumn = new Column<Job, Boolean> (new CheckboxCell (true, false)) {
#Override
public Boolean getValue (Job job)
{
// Get the value from the selection model.
return selectionModel.isSelected (job);
}
};
checkboxColumn.setFieldUpdater (new FieldUpdater<Job, Boolean> () {
public void update (int index, Job job, Boolean value)
{
// Called when the user clicks on a checkbox.
selectionModel.setSelected (job, value);
}
});
// [...]
// [...]
// [...]
selectionModel = new MultiSelectionModel<Job> ();
setSelectionModel (selectionModel);
// setKeyboardSelectionPolicy (KeyboardSelectionPolicy.DISABLED);
// [...]
// [...]
// [...]
}
}
I've tried out all 4 variants
new CheckboxCell (false, false);
new CheckboxCell (true, false);
new CheckboxCell (false, true);
new CheckboxCell (true, true);
but none of them showed up what I need. And I've also played with
setSelectionModel (selectionModel, DefaultSelectionEventManager.<Job> createCheckboxManager ());
Maybe
createCustomManager(DefaultSelectionEventManager.EventTranslator<T> translator)
would help?
Thanx
Thomas
You can create your own "checkbox manager" and do what you want there.
table.setSelectionModel(selectModel, DefaultSelectionEventManager.<DocumentListItemDTO> createCustomManager(
new DefaultSelectionEventManager.CheckboxEventTranslator<DocumentListItemDTO>() {
#Override
public SelectAction translateSelectionEvent(CellPreviewEvent<DocumentListItemDTO> event) {
SelectAction action = super.translateSelectionEvent(event);
if (action.equals(SelectAction.IGNORE)) {
if (!event.getNativeEvent().getCtrlKey() && !event.getNativeEvent().getShiftKey())
selectionModel.clear();
return SelectAction.TOGGLE;
}
return action;
}
}));
Lista's answer showed up the right direction!
In order to show the usage of DefaultSelectionEventManager.CheckboxEventTranslator for which on the web only hardly can be found examples, here is a fully functional solution as requested:
setSelectionModel (selectionModel, DefaultSelectionEventManager.<Job> createCustomManager (
new DefaultSelectionEventManager.CheckboxEventTranslator<Job> () {
#Override
public SelectAction translateSelectionEvent (CellPreviewEvent<Job> event)
{
NativeEvent nativeEvent = event.getNativeEvent ();
// Determine if we clicked on a checkbox.
Element target = nativeEvent.getEventTarget ().cast ();
if ("input".equals (target.getTagName ().toLowerCase (Locale.ROOT)))
{
final InputElement input = target.cast ();
if ("checkbox".equals (input.getType ().toLowerCase (Locale.ROOT)))
{
// Synchronize the checkbox with the current selection state.
input.setChecked (event.getDisplay ().getSelectionModel ().isSelected (
event.getValue ()));
return SelectAction.TOGGLE;
}
}
else
{
if (BrowserEvents.CLICK.equals (nativeEvent.getType ()))
{
selectionModel.clear ();
return SelectAction.SELECT;
}
}
return SelectAction.IGNORE;
}
}));

How to enable content proposal in NatTable TextCellEditor?

I am currently looking for content assist feature in Nattable TextCellEditor.I have found the way to attach the ContentProposalAdapter and IContentProposalProvider by extending the Nattable TextCellEditor. but ,The selected value from the proposed list is not updating in the text control.
Snippet :
#Override
protected Text createEditorControl(final Composite parent, final int Style) {
this.textControl = super.createEditorControl(parent, style);
contentProposalAdapter =
new ContentProposalAdapter(this.textControl, new TextContentAdapter(), contentProposalProvider, keyStroke,
null);
contentProposalAdapter.addContentProposalListener(new IContentProposalListener() {
#Override
public void proposalAccepted(IContentProposal proposal) {
System.out.println(proposal.getContent());
}
});
}
The problem you have is the internal FocusListener that is triggered while selecting a value in the popup. To add the support you also need to override the internal FocusListener with a listener that doesn't fire if the content proposal popup is open.
An example would be to add a boolean flag that indicates that the popup is open and add a listener that sets the flag accordingly.
private boolean popupOpen = false;
...
contentProposalAdapter.addContentProposalListener(new IContentProposalListener2() {
#Override
public void proposalPopupClosed(ContentProposalAdapter adapter) {
this.popupOpen = false;
}
#Override
public void proposalPopupOpened(ContentProposalAdapter adapter) {
this.popupOpen = true;
}
});
And then implement and set a FocusListener in the constructor that takes care of that flag.
this.focusListener = new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
if (!TextCellEditor.this.popupOpen) {
if (!commit(MoveDirectionEnum.NONE, true)) {
if (e.widget instanceof Control && !e.widget.isDisposed()) {
((Control) e.widget).forceFocus();
}
} else {
if (!TextCellEditor.this.parent.isDisposed())
TextCellEditor.this.parent.forceFocus();
}
}
}
};
In case the value should be immediately committed after it is selected, you need to add a listener that performs the commit after selection.
contentProposalAdapter.addContentProposalListener(new IContentProposalListener() {
#Override
public void proposalAccepted(IContentProposal proposal) {
commit(MoveDirectionEnum.NONE);
}
});
Unfortunately the AbstractCellEditor#InlineFocusListener is private and can therefore not be extended.
Feel free to file an enhancement ticket for NatTable to introduce the ability to easily add content proposals to a text cell editor.
https://bugs.eclipse.org/bugs/enter_bug.cgi?product=NatTable

checkbox not getting unchecked in wicket

I have a checkgroup and on selecting a checkbox in the group I want to get the number of selected/checked check boxes.
By the below code, I am able to get the selected number of checkboxes but on unchecking or removing the selection, i see that its still selected.
Example : I have selected 2 now I get 2 string selected.
Now I unselect one checkbox, even now i get 2 strings selected. While I expect one string to be checked.
The code is given below:
final CheckGroup myGroup = new CheckGroup("group", new ArrayList()) {
#Override
protected Collection<String> convertValue(String[] values) throws ConversionException {
Collection<String> myCollection = super.convertValue(values);
checkedString.addAll(myCollection);
HashMap<Integer, String> myTempList = new HashMap<Integer, String>();
for (String myString : checkedString) {
myTempList.put(myString.getSystemId(), myString);
}
checkedString.clear();
for (Entry<Integer, String> myEntry : myTempList.entrySet()) {
checkedString.add(myEntry.getValue());
}
return checkedString;
}
#Override
protected void onSelectionChanged(Collection newSelection) {
newSelection = checkedString;
}
#Override
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
};
add(myForm);
myForm.add(myGroup);
Add a behavior to your component
sampleChckbox.add(new AjaxFormComponentUpdatingBehavior("onclick"){
#Override
protected void onUpdate(AjaxRequestTarget target) {
//perform your operation here
}
This method will fire an Ajax request on "onClick" event; which will update your backend logic at runtime
edit :
To be very specific to CheckGroup class use the AjaxFormChoiceComponentUpdatingBehavior
AjaxFormChoiceComponentUpdatingBehavior is the behavior to use with CheckGroups and RadioGroups. If you used an AjaxFormComponentUpdatingBehavior with the onchange event, you'd run into this bug with IE
. AjaxFormChoiceComponentUpdatingBehavior handles this properly, adding onclick event handlers to each of the Checks in the CheckGroup.
As a side note, what Igor stated in that mail, is that CheckBox can be replaced with AjaxCheckBox, not Check. AjaxCheckBox is nothing more than a convenience subclass of CheckBox with an AjaxFormComponentUpdatingBehavior("onclick"), as the sources show.

GWT Header CheckBox requires two clicks to fire setValue, after changing its value programatically

I have a GWT DataGrid, and a CheckBox in the Header to select/deselect all rows in the grid.
The code for the CheckBox Header is as follows:
private class CheckboxHeader extends Header<Boolean> implements HasValue<Boolean> {
private boolean checked;
private HandlerManager handlerManager;
/**
* An html string representation of a checked input box.
*/
private final SafeHtml INPUT_CHECKED = SafeHtmlUtils.fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\" checked/>");
/**
* An html string representation of an unchecked input box.
*/
private final SafeHtml INPUT_UNCHECKED = SafeHtmlUtils.fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\"/>");
#Override
public void render(Context context, SafeHtmlBuilder sb) {
if (Boolean.TRUE.equals(this.getValue())) {
sb.append(INPUT_CHECKED);
} else {
sb.append(INPUT_UNCHECKED);
}
};
public CheckboxHeader() {
super(new CheckboxCell(true, false));
checked = true;
}
// This method is invoked to pass the value to the CheckboxCell's render method
#Override
public Boolean getValue() {
return checked;
}
#Override
public void onBrowserEvent(Context context, Element elem, NativeEvent nativeEvent) {
int eventType = Event.as(nativeEvent).getTypeInt();
if (eventType == Event.ONCHANGE) {
nativeEvent.preventDefault();
// use value setter to easily fire change event to handlers
setValue(!checked, true);
}
}
#Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
return ensureHandlerManager().addHandler(ValueChangeEvent.getType(), handler);
}
#Override
public void fireEvent(GwtEvent<?> event) {
ensureHandlerManager().fireEvent(event);
}
#Override
public void setValue(Boolean value) {
setValue(value, true);
}
#Override
public void setValue(Boolean value, boolean fireEvents) {
checked = value;
if (fireEvents) {
ValueChangeEvent.fire(this, value);
}
}
private HandlerManager ensureHandlerManager() {
if (handlerManager == null) {
handlerManager = new HandlerManager(this);
}
return handlerManager;
}
}
So, I add the Header to the grid, and I add a ValueChangeHandler to it to do the actual selecting/deselecting of individual CheckBox cells in every row of the grid. This all works.
Every CheckBoxCell has a Field Updater, and on every update it loops through every item in the grid to see if they are all checked, and update the header check box. If at least one is unchecked, the header checkbox will be unchecked. I call setValue() on the header check box, and after that I call redrawHeaders() on the entire grid. This also works.
What doesn't work is - after changing the "state" of the header check box programatically, it takes two clicks for it to fire it's internal setValue again, and therefore trigger my handler. And what's even funnier - the first click does change the state of the check box, but it just doesn't fire the event.
Any help would be appreciated.
How are you constructing the CheckboxCells themselves? I ran into a similar issue with a column of checkboxes "eating" clicks, and the solution was to call CheckboxCell cell = new CheckboxCell(true,true) and then pass that cell into the constructor of the column.

GWT: how can i add/remove a button in a celltable on the go

I have this button cell in my CellTable
ButtonCell reListCell = new ButtonCell();
reListColumn = new Column<EmployerJobs, String>(reListCell) {
#Override
public String getValue(EmployerJobs object) {
return "ReList";
}
};
ctJobs.addColumn(reListColumn,
EmployerDashBoardConstants.EMPTYHEADERCOLUMN);
but i only want this cell to be appear if the below condition pass
public void getDateDiff(final EmployerJobs object) {
rpcService.getDateDiff(object.getJobValidDate(), new AsyncCallback<Boolean>() {
public void onFailure(Throwable caught) {
}
public void onSuccess(Boolean jobExpired) {
if(jobExpired) {
// HERE I WANT TO SHOW MY RELISTCELL, means if the job is expired only then
// there will be a button showing relist would be appear in that row ,for
// the jobs which are not expired NO button should appear..
}
}
});
}
how can i achieve this?
thanks
I agree with DTing.
Quering the backend for each cell/row is not really efficient.
I would rather put the info (jobExpired) into your EmployerJobs class and transfer the info when you request the list of your EmployerJobs to be displayed in your CellTable.
You can update the list periodically to account for changes (see the expenses sample on how to do that).
But to your initial question (hiding the cell). There are two solutions:
Use an ActionCell and override the render method.
ActionCell:
ActionCell<EmployerJobs> reListCell = new ActionCell<EmployerJobs>("ReList",
new ActionCell.Delegate<EmployerJobs>() {
#Override
public void execute(EmployerJobs object) {
// code to be executed
}
})
{
#Override
public void render(Cell.Context context,EmployerJobs value,SafeHtmlBuilder sb) {
if (value.isJobExpired()) // isJobExpired returns the field jobExpired.
super.render(context,value,sb);
}
};
reListColumn = new Column<EmployerJobs, EmployerJobs>(reListCell) {
#Override
public String getValue(EmployerJobs object) {
return object;
}
};
ctJobs.addColumn(reListColumn,
EmployerDashBoardConstants.EMPTYHEADERCOLUMN);
Use a ButtonCell and override the render method of your Column.
ButtonCell:
ButtonCell reListCell = new ButtonCell();
reListColumn = new Column<EmployerJobs, String>(reListCell) {
#Override
public String getValue(EmployerJobs object) {
return "ReList";
}
#Override
public void render(Cell.Context context,EmployerJobs object,SafeHtmlBuilder sb) {
if (value.isJobExpired()) // isJobExpired returns the field jobExpired.
super.render(context,value,sb);
}
};
ctJobs.addColumn(reListColumn,
EmployerDashBoardConstants.EMPTYHEADERCOLUMN);
Just tried Umit solution #2 ButtonCell. It works!
To link an specific action to the button, reListColumn.setFieldUpdater(new FieldUpdater....
would be needed
I tried ButtonCell solution too. But if you click in a cell who as no button then an error on client side occur:
com.google.gwt.core.client.JavaScriptException: (TypeError) #com.google.gwt.core.client.impl.Impl::apply(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)([JavaScript object(445), JavaScript object(240), JavaScript object(637)]): parent is null
So I added this to override the Event and avoid Event if I want:
#Override
public void onBrowserEvent(com.google.gwt.cell.client.Cell.Context context,
Element parent, YourObject object, NativeEvent event) {
if (object.isCompleted())
super.onBrowserEvent( context, parent, object, event);
}
I don't know if it's the better way to do it but it works.