Customize SmartGwt ListGrid dynamically for passwords - smartgwt

I have a com.smartgwt.client.widgets.grid.ListGrid for my configurations screen.
I have 3 ListGridFields name, value, isHidden.
I want to use PasswordItem if isHidden is true, and TextItem if isidden is false.
How can I customize the grid?
I tried with setEditorCustomizer, but it only works when I am editing a cell. In view mode I am able to see the text.

I don't think there's a way to do what you want (show the PasswordItem editor when visualizing the ListGrid's fields). As you already found out, setEditorCustomizer works only when in editing mode.
But you can mask the field values. Here is how to do it:
// very important for not having to set all fields all over again
// when the target field is customized
listGrid.setUseAllDataSourceFields(true);
// customize the isHidden field to make it respond to changes and
// hide/show the password field accordingly
ListGridField isHidden = new ListGridField("isHiddenFieldName");
isHidden.addChangedHandler(new ChangedHandler() {
#Override
public void onChanged(ChangedEvent event) {
// the name of this field has to match the name of the field you
// want to hide (as defined in your data source descriptor,
// ListGridField definition, etc).
ListGridField passwordField = new ListGridField("passwordFieldName");
if ((Boolean) event.getValue() == true) {
passwordField.setCellFormatter(new CellFormatter() {
#Override
public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
return ((String) value).replaceAll(".", "*");
}
});
}
// you need to re-add here the isHidden field for the ChangeHandler to
// be present when recreating the ListGrid
listGrid.setFields(isHidden, passwordField);
listGrid.markForRedraw();
}
});
// add the customized field to the listGrid, so that we can have the
// desired ChangeHandler for the isHidden field
listGrid.setFields(isHidden);

Bear in mind that if you hide the value (or use a PassowrdItem), an 'expert' user could see the value, simply because the server is sending the value to the client.
If you actually have a security constraint, you may use DataSourceField.viewRequires, which accepts velocity expressions.

Related

Vaadin TextField's value not available in shortcut listener

I want to read a Vaadin Flow TextField's value when the user presses the Enter key. I can add a ShortcutListener to listen for the keypress, but the value of the TextField is null in the listener even though the TextField is not empty:
TextField textField = new TextField();
Shortcuts.addShortcutListener(UI.getCurrent(), () -> {
String text = texttextField.getValue();
// text doesn't contain the latest text
}, Key.ENTER);
Why is this happening and how can I read the value that the user has entered when the keypress listener is triggered?
The behavior boils down to browser events. While the user may have entered some text into the input element, the value of the TextField is not updated to the server until there's a ValueChange event - even the vaadin-text-field element in the browser doesn't "know" of the text (the value property has not been updated) when the enter keypress event occurs. By default, the value of the text field is only updated when the input loses focus. You can work around the issue by explicitly toggling a blur of the TextField:
// member field in class
boolean shortcutFired = false;
// ...
Shortcuts.addShortcutListener(UI.getCurrent(), () -> {
textField.blur();
shortcutFired = true;
}, Key.ENTER);
and listening to the value change event instead of the shortcut listener:
textField.addValueChangeListener(e -> {
if( shortcutFired ) {
String value = e.getValue();
// do something with the value
shortcutFired = false;
}
}
This approach doesn't work too well if you need to keep track of multiple fields; in that case, you might want to make the TextFields update their values to the server more eagerly by setting their ValueChangeMode to ValueChangeMode.EAGER. The downside of this approach is that it increases the amount of traffic between the browser and the network, as every keypress will trigger a server request.

ListGrid put focus in the FilterEditor

I have a ListGrid defined like this:
ListGrid lgrid = new ListGrid();
ListGridField first = new ListGridField("first",first");
ListGridField second = new ListGridField("second ",second ");
lgrid.setFields(first, second);
lgrid.setShowFilterEditor(true);
¿How can i put the keyboard focus in the first filter editor field after i call show() in the layout?
Thxs in advance.
Depending on what your use case is (which would be useful to provide a more focused answer), the solution you posted might not be what you really need, because if you scroll on your ListGrid, it could trigger a new data fetch (if there are more records to show), and move the cursor to the filter editor as a result (if your user is editing some records at that point, the cursor moving to the filter row is not what she would want to happen!!).
In such a case, you probably just want to call grid.focusInFilterEditor("fieldToFocus") after the listGrid.show() statement or in the ClickHandler of some button you use to fetch the data, etc.
Anyway, you don't need the Timer either. This works:
listGrid.addDataArrivedHandler(new DataArrivedHandler() {
#Override
public void onDataArrived(DataArrivedEvent event) {
grid.focusInFilterEditor("fieldToFocus");
}
});
I got the solution, its focusInFilterEditor, this is an example to set the focus after the data arrived to the grid:
// Put the focus on the first listGrid field when is loaded
listGrid.addDataArrivedHandler(new DataArrivedHandler() {
#Override
public void onDataArrived(DataArrivedEvent event) {
Timer t = new Timer() {
public void run() {
if(listGrid.getFilterEditorCriteria() == null){
listGrid.focusInFilterEditor("fieldToFocus");
}
}
};
t.schedule(600);
}
});

How determine if a Vaadin table row clicked in has been selected or deselected?

Following a user clicking in a row in a Vaadin 7 table, how can I tell
if the row has been selected or deselected - clicking in a selected row deselects the row - (since there is also a column of
checkboxes which needs to kept in synch)?
When I tried table.getValue() in an ItemClickListener, this returned null if the
row is selected and the item id if the row is deselected - i.e. the opposite of
what I would have expected?
table.addItemClickListener(new ItemClickEvent.ItemClickListener() {
#Override
public void itemClick(ItemClickEvent event) {
// how tell if row has been selected or deselected?
Object idx = table.getValue();
}
});
Thank you,
Steve
In the Table api you can use the getValue() method, which results the selected rows.
Depending if in multiselct mode or not, you can then deduce what happens.
Use Vaadin Grid instead of table. It has the selectionListener property which will help you achieve what you need.
Grid API
(since there is also a column of checkboxes which needs to kept in
synch)?
Use Grid ans set grid.setSelectionMode(SelectionMode.MULTI); you will have one extra column with checkboxes by default.
Now, If you don't want to use Grid.
For Table you should use vaadinTable.addValueChangeListener(...) instead of ItemClickListener.
For Example :
table.addValueChangeListener(new ValueChangeListener() {
#Override
public void valueChange(ValueChangeEvent event) {
//Set checkbox object as an itemId
CheckBox itemId = (CheckBox)event.getProperty().getValue();
//Manage Collection to add selected items
if(table.isSelected(itemId)) {
table.select(itemId);
itemId.setValue(true);//Add this item to collection
} else {
table.unselect(itemId); //Remove this item to collection
itemId.setValue(false);
}
}
});
One another option is,
table.addItemClickListener(new ItemClickEvent.ItemClickListener() {
#Override
public void itemClick(ItemClickEvent event) {
//Manage collection and manually fetch property of table
Object value = event.getItem().getItemProperty("property").getValue();
}
});

How to make a blackberry BitmapField non focusable in runtime

How to make a blackberry BitmapField non-focusable in runtime? I want make it dimmed based on a certain event.
Extend the BitmapField to override the isFocusable() method like this:
public class FocusableBitmapField extends BitmapField {
//Default value depending on whether you want it that way.
private boolean focusable = true;
public boolean isFocusable() {
return focusable;
}
public boolean setFocusable(boolean focusable) {
this.focusable = focusable;
}
}
Most of times this works:
field.setEditable(false);
You can also create a non-focusable field by passing the style flag Field.NON_FOCUSABLE or Field.FOCUSABLE to the constructor, but once instantiated you cannot change it's focusable state. Even if you could, then the field won't look "dimmed" or "disabled", but simply the focus will jump to the next focusable field after it. An example of this are non-focusable label fields.
UPDATE: This would work for built in fields like EditFields, Checkbox, RadioButtons, etc. In your case, this does not work since a BitmapField is not "editable", it's a read only field. You can make a trick like #adwiv answer shows, but the "disabled" or gray overlay you'll have to implement it yourself.

Vaadin addStyleName problem

I created a TextField with TextChangeListener. When user types in certain values (in this case 'admin') then addStyleName is invoked on that field and font color becomes red. But afterwards, the value is blank and each entered character is being cleared.
Here is the code of the application. Why after adding new style to TextField its value changes?
public class VaadintestApplication extends Application {
#Override
public void init() {
Window mainWindow = new Window("Vaadintest Application");
setTheme("test");
TextField textField = new TextField("username");
textField.setEnabled(true);
textField.setTextChangeEventMode(TextChangeEventMode.EAGER);
textField.addListener(new TextChangeListener() {
public void textChange(TextChangeEvent event) {
if ("admin".equals(event.getText())) {
((TextField) event.getComponent()).addStyleName("text-error");
} else {
((TextField) event.getComponent()).removeStyleName("text-error");
}
}
});
mainWindow.addComponent(textField);
setMainWindow(mainWindow);
}
}
I would guess that the following happens:
The style name change triggers a repaint on the server, causing the TextField component to be serialized again to the client
The client receives the serialization (the whole bloody thing, not just the changed parts, because that's how things work with Vaadin), and hence it changes the contents of the textfield, while ignoring any changes that are pending from the text change listener
Solutions:
Update the value of the TextField at the same time you add/remove the style name: ((TextField) event.getComponent()).setValue(event.getText())
Create a custom client side widget which extends VTextField and add the functionality there

Resources