Vaadin Flow: Best practise for hiding fields / change labels in FormLayout - label

What is the best practise for following code snippet...
public class Panel {
private final TextField textField1 = new TextField();
private final TextField textField2 = new TextField();
private final TextArea textArea1 = new TextArea();
private final TextArea textArea2 = new TextArea();
... many other fields
private final Checkbox cb1 = new Checkbox();
private final Checkbox cb2 = new Checkbox();
public Component getContent() {
FormLayout layout = new FormLayout();
layout.addFormItem(textField1, "label for textfield 1");
layout.addFormItem(textField2, "label for textfield 2");
...
layout.addFormItem(cb1, "label for checkbox 1");
layout.addFormItem(cb2, "label for checkbox 2");
return layout;
}
public void updateFields(boolean predicate) {
textField1.setVisible(predicate);
textField2.setVisible(!predicate);
textArea1.setLabel(predicate ? "label A" : "label B");
...
cb1.setVisible(predicate);
cb2.setVisible(!predicate);
}
}
It looks not very practically to save all form-item-references from "FormLayout#addFormItem" to update the visibility state of the fields...
It is also not very practical to separate the labels from the fields.. In Vaadin8 it was simply possible to save the label at the field and it was used for the FormLayout...
Did I miss a point?!?
Is there a better Opportunity to get the advantages of a FormLayout but with the "original" Labels of the fields?!
edit:
https://github.com/vaadin/flow-components/issues/3352

Related

Why doesn't the sort on my TableView in JavaFX work

guys,
my Program has a lot of TableViews. In all tables except one sorting is working. I can't find my mistake in that single TableViews. When clicking the header it seems like its sorting but not refreshing the view. If I change the tab and go back, the TableView is sorted. If a row is selected and I click on the header the selected color is sorted on the right spot but not the table data.
I have my ObservableList and TableView:
private ObservableList<ProjectViewModel> projectViewModelList = null;
// some more TableColumns
#FXML
TableColumn<ProjectViewModel, String> TableColumnToolchainStepphase;
#FXML
TableView<ProjectViewModel> TableViewToolchain;
my initialize:
#FXML
public void initialize(){
//...
initializeLists();
//...
initTableViewToolchain();
initTableColumns();
//...
}
private void initializeLists(){
projectViewModelList = FXCollections.observableArrayList();
}
private void initTableViewToolchain(){
TableViewToolchain.setItems( projectViewModelList );
}
private void initTableColumns(){
TableColumnToolchainStepphase
.setCellValueFactory( new Callback<CellDataFeatures<ProjectViewModel, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call( CellDataFeatures<ProjectViewModel, String> param ){
String string = param.getValue().getStepphaseString();
return new ReadOnlyStringWrapper( string );
}
} );
}
my table population:
private void setProjectViewModelList( Collection<ProjectViewModel> projectViewModelCollection ){
projectViewModelList.clear();
projectViewModelList.setAll( projectViewModelCollection );
}
Where did i go wrong?
I did a workaround i force the sort and refresh on mouseclick:
TableViewToolchain.setOnMouseClicked( ( MouseEvent event ) ->{
TableViewToolchain.sort();
TableViewToolchain.refresh();
} );
So when clicking on those coulmns the sort happens as intended.

javafx textfield value to label in other view

I got an asignment from school where i have to read in two names in one view, then we have to press a button that goes to another view and then the two names have to come in a label there. i have been trying to do this for some time but for some reason i can't figure it out.
Here is my code on the first view
public class Startview extends GridPane {
private TextField txtplayer1;
private TextField txtplayer2;
private Button play;
this.txtplayer1 = new TextField();
this.txtplayer2 = new TextField();
this.add(txtplayer1,2,1);
this.add(txtplayer2, 2, 2);
this.add(play, 2, 3);
public Button getplay() {
return play;
}
this is the code on my presenter where i write the actions
private void eventHandlers() {
view.getplay().setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Gameview gameview = new Gameview();
Gamepresenter presenter3 = new Gamepresenter(model, gameview);
view.getScene().setRoot(gameview);
gameview.getScene().getWindow().sizeToScene();
gameview.getScene().getWindow().centerOnScreen();
}
});
and the gameview where the labels are on(which is also on a gridpane)
private Label name1;
private Label name2;
public Label getname1() {
return Name1;
}
public Label getName2() {
return Name2;
}
all help or tips are appreciated
Just like #James_D said, just use the functions in your model. In your startview use the setName from your player-class and in gameview use the getName from your player class.

wicket manipulating DefaultDataTable

I was creating a web application in wicket and had created a table which shows the user some information. Now I wanted to manipulate this table so if the cell contained "N" the background color would be RED and if it contained "Y" the background color would be GREEN. At the moment I was having trouble to determine what is actually inside the cell. I create my table by the following:
dataTable = new DefaultDataTable<TableModalInt, String>("table", columns,
new TableModalProvider(), 100000){
#SuppressWarnings("rawtypes")
#Override
protected Item newCellItem(String id, int index, IModel model) {
Item item = super.newCellItem(id, index, model);
if (id == "3"){
item.add(AttributeModifier.replace("align", "center"));
}
return item;
}
};
I am capable of determining the cell which I wanna now check what is being displayed to the user. Any help on how i can do this? to change the color i know I'll have to add item.add(AttributeModifier.replace("bgcolor", "red")); but don't know how to tell whats inside the cell
You should do your checks in the IColumn implementation.
https://github.com/apache/wicket/blob/24e9db6c8af85043ce36e4d25a0e8a2d8dc2f49e/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/data/table/PropertyColumn.java#L94 populates the Item with a Label. You need to add a AttributeModifier to the Label.
You can also achieve your goal with pure JavaScript and/or CSS at the client side.
Item is extending list item, so you can try .getModelObject and validate it if it is "X" or "Y"
http://wicket.apache.org/apidocs/1.5/org/apache/wicket/markup/repeater/Item.html
http://wicket.apache.org/apidocs/1.5/org/apache/wicket/markup/html/list/ListItem.html#getModelObject()
This example extracts the cell value when a cell is clicked in a Wicket DataView. The model for this DataView is a Map with String keys and Integer values: Map<String,Integer>.
The PropertyColumn list is created using with column headers ("ALPHA", "BETA", "GAMMA") and property expressions: "alpha", "beta", "gamma". PropertyColumn uses the expressions to retrieve the values from the map.
The DataView is created with the list of PropertyColumns and a DataProvider. DataView uses the DataProvider to populate the PropertyColumn when the table is rendered and reacts to clicks to expose the cell values.
Cells are exposed by overriding the newCellItem(String,int,IModel) method and calling the super-class method to get the cell. This example adds a behavior to react to "onclick" events. Within the event, the cell's first child component should be the Label used to display the cell value.
The innermost model of the cell Label is the PropertyModel from the PropertyColumn.
innerModel.getPropertyExpression(): Our data map key (String).
innerModel.getObject(): The data value (Integer).
innerModel.getInnermostModelOrObject(): The list item (Map<String,Integer>).
Wicket DataView: Extract Cell Value
public class MessageLogStatus
extends WebPage
{
/** Represents serialVersionUID. */
private static final long serialVersionUID = 20150701L;
private static final Logger log = LoggerFactory.getLogger(MessageLogStatus.class);
static final String A = "alpha";
static final String B = "beta";
static final String C = "gamma";
public MessageLogStatus()
{
super();
final List<String> keys = Arrays.asList(A, B, C);
final List<Map<String,Integer>> data = Arrays.asList
(
map(A, 1).put(B, 11).put(C, 21).toMap(),
map(A, 2).put(B, 12).put(C, 22).toMap(),
map(A, 3).put(B, 13).put(C, 23).toMap(),
map(A, 4).put(B, 14).put(C, 24).toMap(),
map(A, 5).put(B, 15).put(C, 25).toMap(),
map(A, 6).put(B, 16).put(C, 26).toMap(),
map(A, 7).put(B, 17).put(C, 27).toMap(),
map(A, 8).put(B, 18).put(C, 28).toMap(),
map(A, 9).put(B, 19).put(C, 29).toMap()
);
// Using a DefaultDataTable
ISortableDataProvider<Map<String,Integer>,String> dataProvider = new SortableDataProvider<Map<String,Integer>,String>()
{
private static final long serialVersionUID = MessageLogStatus.serialVersionUID;
public Iterator<Map<String,Integer>> iterator(long first, long count)
{
int start = Math.max(0, (int) first);
int end = Math.min(data.size(), start + (int) count);
return data.subList(start, end).iterator();
}
public long size()
{
return data.size();
}
public IModel<Map<String,Integer>> model(Map<String,Integer> object)
{
return new CompoundPropertyModel<Map<String,Integer>>(object);
}
};
List<PropertyColumn<Map<String,Integer>,String>> columns = new ArrayList<PropertyColumn<Map<String,Integer>,String>>();
for (String key : keys)
{
columns.add
(
new PropertyColumn<Map<String,Integer>, String>(Model.of(key.toUpperCase()), key)
{
private static final long serialVersionUID = MessageLogStatus.serialVersionUID;
#Override
public void populateItem(Item<ICellPopulator<Map<String, Integer>>> item, String componentId,
IModel<Map<String, Integer>> rowModel)
{
super.populateItem(item, componentId, rowModel);
Map<String, Integer> entity = rowModel.getObject();
String px = getPropertyExpression();
PropertyModel<Object> propModel = new PropertyModel<Object>(rowModel, px);
log.info("Add Label to Cell: PropEx="+px+", Value="+propModel.getObject()+", entity="+entity);
}
}
);
}
//
// Wicket: <table wicket:id="dataTable"></table>
//
DataTable<Map<String,Integer>,String> dataTable =
new DataTable<Map<String,Integer>,String>("dataTable", columns, dataProvider, 5)
{
private static final long serialVersionUID = MessageLogStatus.serialVersionUID;
#Override
protected Item<IColumn<Map<String, Integer>, String>> newCellItem(final String id, final int index,
final IModel<IColumn<Map<String, Integer>, String>> model)
{
final Item<IColumn<Map<String,Integer>, String>> cell = super.newCellItem(id, index, model);
cell.add
(
new AjaxEventBehavior("onclick")
{
private static final long serialVersionUID = MessageLogStatus.serialVersionUID;
#SuppressWarnings("unchecked")
#Override
protected void onEvent(AjaxRequestTarget target)
{
if ( (cell.size() > 0) && (cell.get(0) instanceof Label) )
{
Label cellLabel = (Label) cell.get(0);
PropertyModel<Integer> cellLabelModel = (PropertyModel<Integer>) cellLabel.getInnermostModel();
String property = cellLabelModel.getPropertyExpression();
Integer value = cellLabelModel.getObject();
Map<String, Integer> entity = (Map<String,Integer>) cellLabelModel.getInnermostModelOrObject();
log.info("OnClick: Index="+index+", PropEx="+property+", Value="+value+", Entity="+entity);
}
}
}
);
return cell;
}
};
dataTable.addBottomToolbar(new NavigationToolbar(dataTable));
dataTable.addTopToolbar(new HeadersToolbar<String>(dataTable, null));
add(dataTable);
}
// Make building the data structure a little more fun :)
private MapBuilder<String, Integer> map(String key, Integer value)
{
return new MapBuilder<String, Integer>().put(key, value);
}
private static class MapBuilder<K, V>
{
Map<K, V> map = new HashMap<K, V>();
MapBuilder<K, V> put(K key, V value)
{
map.put(key, value);
return this;
}
Map<K, V> toMap()
{
return map;
}
}
}
Output
OnClick: Index=0, PropEx=alpha, Value=5, Entity={gamma=25, alpha=5, beta=15}
OnClick: Index=1, PropEx=beta, Value=15, Entity={gamma=25, alpha=5, beta=15}
OnClick: Index=2, PropEx=gamma, Value=25, Entity={gamma=25, alpha=5, beta=15}

Using one event handler for multiple actions

I was doing some homework today and I've accomplished all of the goals of the assignment, which I'm sure will get me full points.
In an earlier class, however, we used the same Event Handler for more than one action (in this example, you either type a color in the text field, or click a button to change the background color of the box).
I can't figure out how I would do that in this case... do I have to choose a Type in the constructor? If the first parameter could be a button or a textfield then I think that would help.
I'm just trying to figure out how to apply DRY (Don't Repeat Yourself), where ever I can.
public class ColorChooserApplication extends Application
{
#Override
public void start(Stage stage)
{
// Create all UI components
VBox backgroundBox = new VBox(10);
backgroundBox.setPadding(new Insets(10));
HBox topBox = new HBox(10);
HBox bottomBox = new HBox(10);
TextField colorPrompt = new TextField();
colorPrompt.setOnAction(new ColorHandler(colorPrompt, backgroundBox));
Button redButton = new Button("Red");
redButton.setOnAction(new ButtonHandler(redButton, backgroundBox));
Button whiteButton = new Button("White");
whiteButton.setOnAction(new ButtonHandler(whiteButton, backgroundBox));
Button blueButton = new Button("Blue");
blueButton.setOnAction(new ButtonHandler(blueButton, backgroundBox));
// Assemble
topBox.getChildren().add(colorPrompt);
bottomBox.getChildren().addAll(redButton, whiteButton, blueButton);
backgroundBox.getChildren().addAll(topBox, bottomBox);
backgroundBox.setAlignment(Pos.CENTER);
topBox.setAlignment(Pos.CENTER);
bottomBox.setAlignment(Pos.CENTER);
// Set scene and show
stage.setScene(new Scene(backgroundBox));
stage.show();
}
class ColorHandler implements EventHandler<ActionEvent>
{
TextField colorTf;
VBox bgVbox;
public ColorHandler(TextField colorTf, VBox bgVbox)
{
this.colorTf = colorTf;
this.bgVbox = bgVbox;
}
#Override
public void handle(ActionEvent event)
{
String color = colorTf.getText();
bgVbox.setStyle("-fx-background-color:" + color);
}
}
class ButtonHandler implements EventHandler<ActionEvent>
{
Button colorButton;
VBox bgVbox;
public ButtonHandler(Button colorButton, VBox bgVbox)
{
this.colorButton = colorButton;
this.bgVbox = bgVbox;
}
#Override
public void handle(ActionEvent event)
{
String color = colorButton.getText();
bgVbox.setStyle("-fx-background-color:" + color);
}
}
public static void main(String[] args)
{
launch(args);
}
}
If you're using Java 8, you can do
class ColorHandler implements EventHandler<ActionEvent> {
Supplier<String> colorSupplier ;
VBox bgVbox ;
public ColorHandler(Supplier<String> colorSupplier, VBox bgVbox) {
this.colorSupplier = colorSupplier ;
this.bgVbox = bgVbox ;
}
#Override
public void handle(ActionEvent event) {
String color = colorSupplier.get();
bgVbox.setStyle("-fx-background-color: "+color);
}
}
and then
colorPrompt.setOnAction(new ColorHandler(colorPrompt::getText, backgroundBox));
redButton.setOnAction(new ColorHandler(redButton::getText, backgroundBox));
Note that all you need to provide for the first parameter is some function that returns the correct string for use in the css. So you can do things like
whiteButton.setOnAction(new ColorHandler(() -> "#ffffff", backgroundBox));
blueButton.setOnAction(new ColorHandler(() -> "cornflowerblue", backgroundBox));
etc.

wicket 6.0.0-beta2 Updating content of DataTable when submitting a form with AjaxButton

I want to change the content of a DataTable depending on the content of a form (think of it as a searchbar functionality). I used to do that in wicket 1.5.x but I can not seem to make it work in wicket 6.0.0-beta2. It does not seem to enter in the onSubmit method of the AjaxButton. Everything else works just fine, every components render correctly and the dataTable is filled with the correct data when the page load, but when I click the button, nothing happens.
Any help would be greatly appreciated. Here is what my code look like :
The dataTable :
public SubscriberPage(PageParameters parameters) {
super(parameters);
add(new SearchForm("searchForm"));
List<IColumn<Subscriber, String>> columns = new ArrayList<IColumn<Subscriber, String>>();
columns.add(new PropertyColumn<Subscriber, String>(new Model<String>("Telephone Number"),
"tn",
"tn"));
[...]
columns.add(new PropertyColumn<Subscriber, String>(new Model<String>("Initialized MB"),
"initializedMB"));
table = new AjaxFallbackDefaultDataTable<Subscriber, String>("table",
columns,
subscriberDataProvider,
40);
table.setOutputMarkupId(true);
add(table);
}
and here is the form with the AjaxButton:
private class SearchForm extends Form<String> {
private static final long serialVersionUID = 1L;
private String tnModel;
private Label tnLabel = new Label("tnLabel", "Telephone Number :");
private TextField<String> tn;
public SearchForm(String id) {
super(id);
tn = new TextField<String>("tnTextField", new PropertyModel<String>(this, "tnModel"));
tn.setOutputMarkupId(true);
add(tnLabel);
add(tn);
AjaxButton lSearchButton = new AjaxButton("searchButton") {
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
SubscriberFilter filter = new SubscriberFilter();
target.add(table);
if (!(tn.getValue() == null) && !tn.getValue().isEmpty()) {
filter.setTn(tn.getValue());
}
// giving the new filter to the dataProvider
subscriberDataProvider.setFilterState(filter);
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
// TODO Implement onError(..)
throw new UnsupportedOperationException("Not yet implemented.");
}
};
lSearchButton.setOutputMarkupId(true);
this.setDefaultButton(lSearchButton);
add(lSearchButton);
}
}
The components that you want to refresh need to be added in a container. When you submit, the container needs to be added to target. This way your components will be refreshed. Something like:
WebMarkupContainer outputContainer = new WebMarkupContainer("searchResult");
outputContainer.setOutputMarkupId(true);
outputContainer.add(table);
add(outputContainer);
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
//change table ..... stuff ..... ...
//refresh container
target.add(outputContainer);
}
<div wicket:id="searchResult"></div>

Resources