play.data.Form - How best to fill default form values - java

Trying to add a filter form to a standard crud 'list' page.
// set filter defaults
ImageFilter defaultFilter = new ImageFilter();
defaultFilter.setYear(currentYear);
defaultFilter.setColor(user.getFavouriteColor());
// get filter for view
Form<ImageFilter> form = Form.form(ImageFilter.class).fill(defaultFilter).bindFromRequest();
ImageFilter filter = form.get()
bindFromRequest() alone gets a form with the filters a user specified, but on first load the fields have no selected value
fill(defaultFilter) alone does provide a form with the default filters selected
chained in this way the behaviour is just identical to the behaviour of the one called last.
What is the appropriate way to set the defaults?
Ideally, on the index page:
the default filter selection when not given any parameters
if requested with ?year=2010&color=blue those filters show on the form
if requested with ?year=2010 the form shows 2010 and the user's favourite color

Check if default values are present then go with the flow.
If not present, add set it in filter or render on UI using querystring params.

You can achieve what you want by splitting your code into two actions.
In the first one you fill a form with the default filter and display it to a user.
public static Result show() {
ImageFilter defaultFilter = new ImageFilter();
defaultFilter.setYear(currentYear);
defaultFilter.setColor(user.getFavouriteColor());
Form<ImageFilter> form = Form.form(ImageFilter.class).fill(defaultFilter);
return ok(index.render(form));
}
In the second action you simply bind form values from the request. If user changes some values form will be filled with them along with unchanged ones set as the defaults.
public static Result handle() {
Form<ImageFilter> form = Form.form(ImageFilter.class).bindFromRequest();
ImageFilter filter = form.get();
return ok("TODO handle form");
}
Edit
If you want to fill missing fields with the defaults after user input without showing them in the view before submit I'm afraid you'll have to do it manually after binding.

Related

Webix load combo get all values into array

I'm loading some data into a hidden Webix combo box via URL with two parameters. After loading, I want to store all values from the combo box into an array. But this doesn't work. If it is possible to load data from URL to an array without loading it first into a combo, how does this work? I use Spring ResourceMapping annotation in the controller.
You can use a webix DataCollection which work as any webix data component but without any graphical representation :
var store = new webix.DataCollection({ url:"data.php" });
Another solution is to manually do ajax request :
webix.ajax().get('data.php', function(txt, data) { console.log(data.json()); });

How to use Nebula NatTable's PreserveSelectionModel?

I am developing an RCP Application, and am using Nebula's NatTable for that.
When it comes to selection, I am failing to understand how I am supposed to use it.
What I want is:
I want to have entire Rows selected. I was able do that using the RowOnlySelectionConfiguration and the RowOnlySelectionBindings.
If I select a row, I want the selection to stay there and not be cleared when some data in that row gets updated. How do I do that?
If a row is selected, and the position of the element in that row changes (e.g. one of the previous elements is removed, and the position changes to index - 1), I want the selection to change the position with the element, so that the same element is selected after the change. How do I do that?
I have seen that the documentation talks about a PreserveSelectionModel that can be used for that:
If you used the PreserveSelectionStructuralChangeEventHandler workaround in previous versions for not clearing the selection on structural changes, you will notice that this workaround will not work anymore. If you still need that behavior, you are now able to achieve the same by configuring and setting a SelectionModel instance like this:
SelectionModel model = new SelectionModel(selectionLayer);
// configure to not clear the selection on structural changes
model.setClearSelectionOnChange(false);
selectionLayer.setSelectionModel(model);
If you expect that the selection should update and move with structural changes (e.g. sorting), try to use the PreserveSelectionModel.
https://www.eclipse.org/nattable/nandn/nandn_120.php
So I guess I have to use the PreserveSelectionModel? But there I can't call setClearSelectionOnChange(false). Does it do that by default?
And how do I use the PreserveSelectionModel? What do I pass in the constructor?
I implement my own BodyLayerStack, in a class called TableBodyLayerStack, where I tried this in the constructor:
public TableBodyLayerStack(IUniqueIndexLayer underlyingLayer) {
super(underlyingLayer);
columnReorderLayer = new ColumnReorderLayer(underlyingLayer);
columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
selectionLayer = new SelectionLayer(columnHideShowLayer, null, true, false);
PreserveSelectionModel<?> selectionModel = new PreserveSelectionModel<>(
selectionLayer, null, null);
selectionLayer.setSelectionModel(selectionModel);
selectionLayer.registerEventHandler(new SelectEventHandler(selectionLayer));
viewportLayer = new ViewportLayer(selectionLayer);
setUnderlyingLayer(viewportLayer);
registerCommandHandler(new CopyDataCommandHandler(selectionLayer));
}
Then, in the contructor of my implementation of the GridLayer, I do this:
// ...
bodyLayer = new TableBodyLayerStack(eventLayer);
// register different selection move command handler that always moves by row
bodyLayer.getSelectionLayer().addConfiguration(new RowOnlySelectionConfiguration<T>());
// register selection bindings that will perform row selections instead of cell selections
// registering the bindings on a layer that is above the SelectionLayer will consume the
// commands before they are handled by the SelectionLayer
bodyLayer.addConfiguration(new RowOnlySelectionBindings());
// ...
But this is giving me NullPointerExceptions in the PreserveSelectionModel.
Error while painting table: null
java.lang.NullPointerException
at org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel.getRowPositionByRowObject(PreserveSelectionModel.java:520)
at org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel.createMarkerPoint(PreserveSelectionModel.java:559)
at org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel.getSelectionAnchor(PreserveSelectionModel.java:531)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.getSelectionAnchor(SelectionLayer.java:276)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.getConfigLabelsByPosition(SelectionLayer.java:415)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:316)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getConfigLabelsByPosition(AbstractIndexLayerTransform.java:318)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getConfigLabelsByPosition(CompositeLayer.java:553)
at org.eclipse.nebula.widgets.nattable.layer.cell.AbstractLayerCell.getConfigLabels(AbstractLayerCell.java:48)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayer.getCellPainter(AbstractLayer.java:354)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getCellPainter(AbstractIndexLayerTransform.java:340)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getCellPainter(AbstractIndexLayerTransform.java:340)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getCellPainter(CompositeLayer.java:586)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:171)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:81)
at org.eclipse.nebula.widgets.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:106)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayerPainter.paintLayer(SelectionLayerPainter.java:95)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:913)
at org.eclipse.nebula.widgets.nattable.painter.layer.NatLayerPainter.paintLayer(NatLayerPainter.java:43)
at org.eclipse.nebula.widgets.nattable.NatTable.paintNatTable(NatTable.java:408)
at org.eclipse.nebula.widgets.nattable.NatTable.paintControl(NatTable.java:403)
...
I guess it is because I pass null values in the constructor of my PreserveSelectionModel. But how do I use it instead? What do I have to pass as arguments for the constructor? Where do I get the values from?
Any help is appreciated.
you are on the wrong track to achieve your goals. First I will answer your questions:
So I guess I have to use the PreserveSelectionModel?
No, the PreserveSelectionModel is intended to preserve the selection for cell selections. You want to preserve the selection for whole rows. So you need to use the RowSelectionModel.
But there I can't call setClearSelectionOnChange(false). Does it do that by default?
Yes
But this is giving me NullPointerExceptions in the PreserveSelectionModel. I guess it is because I pass null values in the constructor of my PreserveSelectionModel.
Yes
What do I have to pass as arguments for the constructor? Where do I get the values from?
The second parameter is IRowDataProvider<T>, so it is the IDataProvider for the body.
The third parameter is IRowIdAccessor<T>. You need to create an implementation that provides an unique id, so a row can be identified without knowing the position or index in the underlying collection.
So what you need to do is something like this:
selectionLayer.setSelectionModel(new RowSelectionModel<Person>(
selectionLayer, bodyDataProvider, new IRowIdAccessor<Person>() {
#Override
public Serializable getRowId(Person rowObject) {
return rowObject.getId();
}
}));
But of course you need to provide the IDataProvider and also the IRowIdAccessor to your TableBodyLayerStack if you want to keep it generic.
Also note that you don't have to call SelectionLayer#registerEventHandler() yourself! This is done internally by calling SelectionLayer#setSelectionModel().
You can find several examples in the NatTable Examples Application at https://www.eclipse.org/nattable/ (the Try it! button on the right side).
For your question the Tutorial Examples -> Layers -> Selection -> RowSelectionExample seems to be the one to look at.

How to change colour of row when is selected in wicket

i follow this example but I want to change it. I want to select row when you click wherever on the certain row not just to some value so I add AjaxEventBehavior. Problem is that player is selected but colour of row is still same. What is wrong ?
listItem.add(new AjaxEventBehavior("onclick") {
private static final long serialVersionUID = 1L;
#Override
protected void onEvent(final AjaxRequestTarget target) {
selectedPlayer = player;
HighlitableDataItem<Player> hitem = (HighlitableDataItem<Player>) listItem;
hitem.toggleHighlite();
}
});
As #jordeu already pointed out in his comment, you've got to add hitem to the AjaxRequestTarget:
target.addComponent(hitem);
Adding the component to the AjaxRequestTarget will send back to the XML response the markup of the component, with all the changes you've possibily made to it server-side, and with updated models (this is useful for dynamic models). Remember to invoke setOutputMarkupId(true) on the components you want to add to the request target. Wicket needs the markup id (HTML id attribute) to know where in the DOM to replace the markup sent in the XML response. Or, in words of the javadoc:
A component whose markup needs to be updated should be added to this
target via AjaxRequestTarget#addComponent(Component) method. Its body
will be rendered and added to the envelope when the target is
processed, and refreshed on the client side when the ajax response is
received.
It is important that the component whose markup needs to be updated
contains an id attribute in the generated markup that is equal to the
value retrieved from Component#getMarkupId(). This can be accomplished
by either setting the id attribute in the html template, or using an
attribute modifier that will add the attribute with value
Component#getMarkupId() to the tag ( such as MarkupIdSetter )
Also, take into account that using Ajax to just style an element can be kind of an overkill. If no server interaction is required, you might consider styling the element client-side with Javascript/jQuery if available.
The most efficient way is to render javaScript into your table. Doing so you avoid roundtrips to the server, which would be overkill in this simple just-for-styling case.
You acheive it with overriding DataTable#newRowItem and adding AttributeAppender to the RowItem :
//override this method of the DataTable class
#Override
protected Item<T> newRowItem(String id, int index, final IModel<T> model) {
Item<T> rowItem = new Item<T>(id, index, model);
item.add(new AttributeAppender("onclick", "$(this).addClass('selected').siblings().removeClass('selected')",
" "));
return rowItem;
}
Define your selection styling under 'selected' selector in your css stylesheet.

Filter tree in Vaadin

I want to hide leafs from vaadin tree according to text in some editbox (on text change).
ie if text in editbox is "ab" i want to show only leafs with text starting with "ab".
and if text is empty, i want to show all leafs.
How can i make that?
You will have to filter the data container which is attached to the tree.
A new Filter API was introduced in version 6.6.0 which allows you to create custom Filters. I haven't tried the new API yet, but in your case it should work like this:
textField.addListener(new FieldEvents.TextChangeListener() {
void textChange(FieldEvents.TextChangeEvent event) {
// Remove existing filter (if any).
// This is OK if you don't use any other filters, otherwise you'll have to store the previous filter and use removeContainerFilter(filter)
dataContainer.removeAllContainerFilters();
// Create a new filter which ignores case and only matches String prefix
SimpleStringFilter filter = new SimpleStringFilter(propertyId, event.getText(), true, true);
// Add the new filter
dataContainer.addContainerFilter(filter);
}
});
in which textField is your "editbox", dataContainer is the data container which is attached to your tree and properyId is the property id of the container field which contains the text you want to filter.
Note that the above code is untested because I currently can't access the appropriate development tools.

how to make a <html:multibox> checked by default

I'm new to Struts 1 so may be its already a resolved question.
The situation is: I have a list of <html:multibox> tag, which are rendered into html-checkbox element when the page loads. I want the checkboxes to be checked by default (without using javascript/jquery).
You would set the fields in your Form if you want them selected. For multiple checkboxes with all the same name but different values, your Form should have a String[] property that holds all the selected values. Just populate that with the values you want selected by default. This could be something as simple as:
public void reset(ActionMapping mapping, HttpServletRequest request) {
if(multiboxField == null) {
multiboxField = new String[2];
multiboxField[0] = "optionOne";
multiboxField[1] = "optionTwo";
}
}
The best way to do this is with a *formname*SetupAction.java class.
Set your struts-config.xml to redirect people who click on your page to this SetupAction. Import your form class, populate your String[] with whatever values you want default-checked, and action-forward them back to your page. This also allows you to dynamically populate them, based on DB data or session variables or whatever you want.

Categories