Vaadin Flow grid add an empty row - java

How can someone add a new empty line (perhaps at the bottom or at the top of the grid) programmatically.
At a later state the user enters data, or after some actions save all the rows perhaps in the database.

Technically it should be rather simple, especially if you use ListDataProvider for the Grid, here simplified example:
Grid<Bean> grid = new Grid<>(Bean.class);
ListDataProvider<Bean> dp = new ListDataProvider<>(getData());
grid.setDataProvider(dp);
add(grid);
Button button = new Button("Add row");
button.addClickListener(event -> {
Bean bean = new Bean();
dp.getItems().add(bean);
dp.refreshAll();
grid.getEditor().editItem(bean);
});
add(button);

You using ListDataProvider set fof dataprovider of grid.
Bean object Override hashCode method.
for Example :
#Transient
private long sId;
public ConstructorMethod () {
sId = System.currentTimeMillis();
}
#Override
public int hashCode() {
if (isNew())
return (int) (super.hashCode()+sId);
else
return super.hashCode();
}
New a bean object and add to ListDataProvider of grid
BeanClass item = new BeanClass();
(ListDataProvider<BeanClass>)grid.getDataProvider().getItems().add(item);
(ListDataProvider<BeanClass>)grid.getDataProvider().refreshAll();

Related

How to make only some columns editable in a Vaadin Grid?

Vaadin Grid allows to be defined as editable with
grid.setEditorEnabled(true);
This makes all visible columns editable. However I don't want the user to edit an specific column, but seems like the editable is an all or nothing.
The next best solution I have found is to define an editor field with a disabled editor, which almost does the trick but the user is still able to select the text and move the cursor (but the field is not editable anymore).
Grid.Column nameColumn = grid.getColumn("fullName");
nameColumn.setHeaderCaption("Full Name");
nameColumn.setEditorField(getNoEditableTextField());
...
private Field<?> getNoEditableTextField() {
TextField noEditableTextFiled = new TextField();
noEditableTextFiled.setEnabled(false);
return noEditableTextFiled;
}
I believe Label cannot be used because it's not a Field.
Is there a better option to achieve this?
edit: as aakath said, there is a way of achieving this not enabling the column to be edited, but in doing so the cell value disappears when you edit the row, which is not desirable.
Did you try calling setEditable(false) method on the column? I believe it should make the field non-editable when the item editor is active.
grid.getColumn("fullName").setEditable(false);
my solution is below. i have just finished. it was not tested too much. but it may give you some ideas.
ati
getColumn(columnName).setEditable(true).setEditorField(getNoEditableField(columnName));
...
private Field<?> getNoEditableField(final String columnName) {
CustomField<Label> result = new CustomField() {
#Override
protected Component getContent() {
Label result = (Label) super.getContent();
Object editedItemId = getEditedItemId();
String value = DEFAULT_VALUE;
if (editedItemId != null) {
value = CustomizableGrid.this.toString(getContainerDataSource().getItem(editedItemId).getItemProperty(columnName).getValue());
}
result.setValue(value);
return result;
}
#Override
protected Component initContent() {
Label result = new Label(DEFAULT_VALUE, ContentMode.HTML);
result.setDescription(getColumnDescription(columnName));
result.setStyleName("immutablegridcellstyle");
return result;
}
#Override
public Class getType() {
return Label.class;
}
};
result.setConverter(new Converter<Label, Object>() {
//converter for your data
});
return result;
}
I had the same problem and didn't want that clicking on id column opens editor. I solved it with adding an ItemClickListener as below. It works fine for me.
grid.addItemClickListener((ItemClickListener<GridBean>) event -> grid.getEditor().setEnabled(!event.getColumn().getCaption().equals("Id")));
Also byc clicking on specific columns Grid is not editable any more.
There is one tricky way to do it! I've just found out it.
So, first of all you need to use grid with container, instead of direct rows adding:
BeanItemContainer<MyBean> container = new BeanItemContainer<>(MyBean.class);
setContainerDataSource(container);
Then remove fields setters from MyBean, except setters for fields what you have to edit.
I think the same can be achieved by making the grid an editable one by grid.setEditorEnabled(true); and disabling editing option for other columns like grid.getColumn(columnName).setEditable(false);. But I am not sure of any demerits of this method. Any suggestion is always appreciated.
Its simple just go to Vaadin Documentation what did from it is below:
you can see here I gave a specified column Name
grid = new Grid<>();
lst = new ArrayList<>();
provider = new ListDataProvider<>(lst);
lst.add(new Company(1, "Java"));
grid.setDataProvider(provider);
grid.addColumn(Company::getSerialNo).setCaption("Sr.no");
TextField tf = new TextField();
grid.getEditor().setEnabled(true);
HorizontalLayout hlyt = new HorizontalLayout();
grid.addColumn(Company::getName).setEditorComponent(tf, Company::setName).setCaption("Name").setExpandRatio(2);
hlyt.addComponent(grid);
I use the following approach to get a read-only field, the trick is override the setEnabled method to get a disabled textfield. If you trace the source code in Vaadin Grid, no matter what field you pass to a Grid, it will always call the field.setEnabled(true).
myGrid.getColumn(propertyId).setEditorField(new ReadOnlyField());
And
public class ReadOnlyField extends TextField
{
public ReadOnlyField()
{
super();
this.setReadOnly(true);
}
#Override
public void setEnabled(boolean enabled)
{
// always set to disabled state
super.setEnabled(false);
}
}

JFace LabelProvider: How can I know the header/name of a column within a LabelProvider?

this is the normal way for defining what to write in a Column using LabelProvider
#Override
public String getColumnText(final Object element, final int iColumn) {
switch (iColumn) {
case 0:
..
case 1:
..
default:
...
}
}// getColumText()
which means I am given the id of the column.
How can I get teh "header" of the column given the id within the LabelProvider?
something like
String str = xxx.getColumnName( iColumn );
I don't find it.
This is an example of using ColumnLabelProvider. This uses the TableColumnLayout which is set on a Composite which just contains the TableViewer, this allows the layout to adjust column sizes if the control is resized.
final Composite tableComp = new Composite(parent, SWT.NONE);
tableComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final TableColumnLayout layout = new TableColumnLayout();
tableComp.setLayout(layout);
TableViewer viewer = new TableViewer(tableComp, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
Table table = viewer.getTable();
col = new TableViewerColumn(_viewer, SWT.LEAD);
col.setLabelProvider(new NameColumnLabelProvider());
col.getColumn().setText(Messages.title_filename);
layout.setColumnData(col.getColumn(), new ColumnWeightData(70));
col = new TableViewerColumn(_viewer, SWT.TRAIL);
col.setLabelProvider(new DurationColumnLabelProvider());
col.getColumn().setText(Messages.title_duration);
layout.setColumnData(col.getColumn(), new ColumnWeightData(30));
private static class NameColumnLabelProvider extends ColumnLabelProvider
{
#Override
public String getText(final Object element)
{
// return name column label
}
}
private static class DurationColumnLabelProvider extends ColumnLabelProvider
{
#Override
public String getText(final Object element)
{
// return duration column label
}
}
Well, funny I never read your answer greg :( thanks a lot anyways :)
However, what you propose requires you know before hand what are the columns. What I did creates columns dinamically which are added to the treeview.
What I finally did:
-Externally manage a map of id/label
Goods:
-Simple: Independent of Eclipse/JFace, easy to understand, portable.
Bads:
- Well, whenever I dinamicall y add a column, I have to add it in the map, and same with removing. But once done, it is clear (other methods which my add columns in the future (no need in principle because I didn it general), must consider to register them within the map.
-It would have been nice that it were encapsulated within JFace.
Step 1:
make ur own labelprovider with private attribute "TableViewer referencedTableViewer".
build constructor using this attribute.
now u can reference to tableviewer in getColumnText-method:
#Override
public String getColumnText(Object element, int columnIndex) {
String columnTitle = referencedTableViewer.getTable()
.getColumn(columnIndex).getText();
...
Step 2:
build TableViewer, instantiate labelprovider with reference to TableViewer

Java - JCheckBox Filters Against a List

I have a List, that included JPA Entity objects of a certain type. Their reference String values are displayed in a JList for the user to see.
I want my user to be able to select filters as JCheckBoxes in the UI such as 'only from Client x', or 'only of Type x' and dynamically filter the Entity List.
I had thought to just keep a copy of static List completeList; and static List filteredList; and then just run individual filter methods each time a new filter is selected in the UI to update filteredList, which would work fine until you have to un-select a single filter and leave the others selected (at which point it all falls apart).
Every situation I think through fall apart at one point or another, usually when trying to select multiple filters of from one Menu.
An example of my thought pattern that checks all the filters to determine what needs to go in the new JList;
public static void filterList(){
List filteredList = new ArrayList<Job>(StoredDataClass.completeList);
if(clientSmithsCheckBox.isSelected()){
for(Job job : filteredList){
if(!job.getClient.equals(clientSmithsCheckBox.getText())){
filteredList.remove(job);
}
}
}
....... // Check other filters here etc.
if(clientBobAndCoCheckBox.isSelected()){
for(Job job : filteredList){
if(!job.getClient.equals(clientBobAndCoCheckBox.getText())){
filteredList.remove(job);
}
}
}
Even if clientBobAndCoCheckBox is selected, no jobs with that client will show in the final list, because we already removed them all because another client was already selected. Now, we could add to the list instead but we would face similar problems of having add stuff that shouldn't be there etc.
This is obviously possible, because this type of filtering system is common practice (example, excel). Although this is more of a design question, how can I achieve this?
Here's a short (and raw!) example of how you could organize your logic. It's in the context of SwingX (which supports sorting/filtering of a JList just the same way as a JTable) because I'm lazy - but you can apply it to your own environment easily.
Think of your criteria as a collection of filters which can be on or off, and then combine them with OR (if one or more is selected) or turn off if none is selected. The sole "trick" is to evaluate all of the checkboxes' states wheneven one of them is changed:
final JXList list = new JXList(new DefaultComboBoxModel(Locale.getAvailableLocales()));
list.setAutoCreateRowSorter(true);
final List<RowFilter> filters = new ArrayList<>();
filters.add(new MyRowFilter("de"));
filters.add(new MyRowFilter("ar"));
final List<JCheckBox> boxes = new ArrayList<>();
ActionListener l = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
List<RowFilter<Object, Object>> orCandidates = new ArrayList<>();
for (int i = 0; i < boxes.size(); i++) {
if (boxes.get(i).isSelected())
orCandidates.add(filters.get(i));
}
RowFilter<Object, Object> or = orCandidates.isEmpty() ? null :
RowFilter.orFilter(orCandidates);
list.setRowFilter(or);
}
};
JCheckBox first = new JCheckBox("de");
first.addActionListener(l);
boxes.add(first);
JCheckBox second = new JCheckBox("ar");
second.addActionListener(l);
boxes.add(second);
JComponent content = new JPanel();
content.add(new JScrollPane(list));
for (JCheckBox box : boxes) {
content.add(box);
}
showInFrame(content, "filters");
// just for completeness, the custom RowFilter
public static class MyRowFilter extends RowFilter {
private String text;
public MyRowFilter(String text) {
this.text = text;
}
#Override
public boolean include(Entry entry) {
Locale locale = (Locale) entry.getValue(0);
return locale.getLanguage().contains(text);
}
}

How to disable a tab in a GXT 3 tabpanel

I have a GXT 3 TabPanel and would like to disable one or more tabs in response to an event.
There does not seem to be a way to do this.
PlainTabPanel panel = new PlainTabPanel();
TabItemConfig config = new TabItemConfig("Disabled");
Label disabled = new Label("This tab should be disabled");
config.setEnabled(false); // here what you need
panel.add(disabled, config);
I figured this out a while back and forgot to post the answer. Here's a way to do this that works reliably :
public class SimpleTabPanel extends com.sencha.gxt.widget.core.client.PlainTabPanel
implements TabPanel {
Tab currentActiveTab;
private Map<SimpleTab,TabItemConfig> tabConfigs = new HashMap<SimpleTab,TabItemConfig>();
// a map sorted by priority used to keep the expected tab order
SortedMap<TabData, SimpleTab> tabsConfig = new TreeMap<TabData, SimpleTab>(
new Comparator<TabData>() {
#Override
public int compare(TabData o1, TabData o2) {
return Float.compare(o1.getPriority(), o2.getPriority());
}
});
#Override
public Tab addTab(TabData tabData, String historyToken) {
SimpleTab newTab = createNewTab(tabData);
tabsConfig.put(tabData, newTab);
newTab.setTargetHistoryToken(historyToken);
return newTab;
}
private void disableTab(SimpleTab tab, TabData key){
// get and save tab's config.
TabItemConfig tic = getConfig(tab);
tabConfigs.put(tab, tic);
// put new one on tab to disable it.
tic = new TabItemConfig(key.getLabel());
tic.setEnabled(false);
update(tab, tic);
}
public void enableAllTabs(){
for(TabData key : tabsConfig.keySet()){
SimpleTab tab = tabsConfig.get(key);
TabItemConfig tic = tabConfigs.get(tab);
if(tic!=null){
tic.setEnabled(true);
update(tab, tic);
}
}
}
}
I had the same issue happening in my project.
The way I solved it is really simple and I hope that it answers your need.
public void enableTab(IsWidget item, Boolean enable) {
TabItemConfig config = tabPanel.getConfig(item.asWidget());
config.setEnabled(enable);
tabPanel.update(item.asWidget(), config);
}
I call that method every time I need to change a tab state.

ActionListener does not work to move data from on JList to the Other JList by the button

My program is based on a API. I got a JList with and a model that has a some names. And a selectListener to get the seleted item and a button to send that item to the other window which has another Here is my first list:
First List (window) and send the items to the other list.
final DefaultListModel<String> Names = new DefaultListModel<String>();
final JList<MyAPI> Places = new JList(Names);
private JList<MyAPI> locList;
private DefaultListModel<MyAPI> favourites;
public AddLocation(JList<MyAPI> locList, DefaultListModel<MyAPI> favourites){
this.locList = locList;
this.favourites = favourites;
}
addThis.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Object chose = Places.getSelectedValue();
favourites.addElement((MyAPI) chose); // error in this line
}
});
And this is the other window that selected items should be added to here:
final DefaultListModel<MyAPI> favourites;
final JList<MyAPI> locList;
favourites = new DefaultListModel<MyAPI>();
locList = new JList<MyAPI>(favourites);
So now both windows loads and the first list loads with its names in it. but when I press the button add this, it gives error and points to this line:
favourites.addElement((MyAPI) chose);
How can I solve it?
Your first model is defined like this:
final DefaultListModel<String> Names ...;
Your second model is defined like this:
final DefaultListModel<MyAPI> favourites;
Your first list model conains String instances, your second model contains MyAPI instances. So when this line is executed:
favourites.addElement((MyAPI) chose);
you are trying to make a MyAPI out of a String, which does not work and probably a ClassCastException is thrown.
Either you need to declare the second list model as final DefaultListModel<String> favourites; or you create an instance of MyAPI based on the selected String (new MyAPI(chose) ?).

Categories