So I have this piece of code which is almost exactly the same on the GWT Showcase
selectionModel = new SingleSelectionModel<T>(keyProvider);
cellTable.setSelectionModel(selectionModel);
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
selectedRow = ((SingleSelectionModel<T>).selectionModel)
.getSelectedObject();
});
Column<T, Boolean> checkColumn = new Column<T, Boolean>(new CheckboxCell(true, false)) {
#Override
public Boolean getValue(T object) {
return cellTable.getSelectionModel().isSelected(object);
}
};
cellTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
The problem is, when I uncheck the checkbox the SelectionChangeEvent doesn't handle it.
The only instance the onSelectionChange is being called, is when I select another record, but deselecting a record doesn't invoke this method.
any help?
You forgot to add DefaultSelectionEventManager i guess.
Change this line
cellTable.setSelectionModel(selectionModel);
to
cellTable.setSelectionModel(selectionModel,
DefaultSelectionEventManager.<T> createCheckboxManager());
Related
I want to filter GXT ComboBox Store. for example if I type 'st' in combobox I want combobox to show only values that contain 'st'
Here is my implementation
combo = new ComboBox<MerchantDTO>(store, label);
StoreFilter<MerchantDTO> filter = new StoreFilter<MerchantDTO>() {
#Override
public boolean select(Store<MerchantDTO> store, MerchantDTO parent, MerchantDTO item) {
boolean canView = (item.getName() != null && item.getName().toLowerCase().contains(combo.getText().toLowerCase()));
return canView;
}
};
store.setEnableFilters(true);
store.addFilter(filter);
This filter works and shows correct values, But combobox's dropdown list does not open automatically. I have to click on combobox manually to open dropdown list and see filtered results. I am using GXT 3.1.0 and GWT 2.7.0
I tried using combo.expand(); function but it didnt open dropdown list.
Any help would be appreciated.
I found solution. Here is sample how to add custom filter to GXT (version 3.1.0) ComboBox
1) Create class which extends ListStore and add String variable for user input text
public abstract class XListStore<M> extends ListStore<M> {
private String userText;
public XListStore(ModelKeyProvider<? super M> keyProvider) {
super(keyProvider);
}
#Override
protected boolean isFilteredOut(M item) {
return filter(item);
}
public abstract boolean filter(M item);
public String getUserText() {
return userText;
}
public void setUserText(String userText) {
this.userText = userText;
}
}
2) Initialize custom list store and implement filter method
XListStore<SampleDTO> store = new XListStore<SampleDTO>(new ModelKeyProvider<SampleDTO>() {
#Override
public String getKey(SampleDTO item) {
return item.getId();
}
}) {
public boolean filter(SampleDTO item) {
boolean result = false;
//Write you filter logic here
return result;
}
};
store.setEnableFilters(true);
3) Initialize ComboBox and add Key up handler
ComboBox<SampleDTO> comboBox = new ComboBox<SampleDTO>(store, label);
comboBox.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent event) {
store.setUserText(comboBox.getText());
}
});
Done. Now ComboBox will filter store according to user input and will open dropdown window automatically
I'm using GXT 3.0 and I want to develop a grid table in it. In table, a cell assigned to be have multiple jobs, like save, delete, update. So I need to develop a grid table which has multiple buttons in a cell. To visualize the problem I'm sharing this image :
I tried to add just a cell via
ColumnConfig.setCell()
method, and It's succeeded. But I must add multiple buttons, or cells to handle events. In short form I need multiple Cells inside a Cell.
I know there is a method called ColumnConfig.setWidget(), but it didn't helped. It just added toolbar(or any widget element) to top(header part).
Remember that I use GXT 3.0
Thanks for any help.
You must use a CompositeCell :
private CompositeCell<ObjectRow> createCompositeCell(){
HasCell<ObjectRow, String> button1 = new HasCell<ObjectRow, String>() {
public Cell<String> getCell() {
return new ButtonCell();
}
public FieldUpdater<ObjectRow, String> getFieldUpdater() {
return null;
}
public String getValue(ObjectRow object) {
return "Button 1";
}};
HasCell<ObjectRow, String> button2 = new HasCell<ObjectRow,String>(){
public Cell<String> getCell() {
return new ButtonCell();
}
public FieldUpdater<ObjectRow, String> getFieldUpdater() {
return null;
}
public String getValue(ObjectRow object) {
return "Button 2";
}
};
List<HasCell<ObjectRow, ?>> cells = new ArrayList<HasCell<ObjectRow, ?>>();
cells.add(buton1);
cells.add(button2);
CompositeCell<ObjectRow> compositeCell = new CompositeCell<ObjectRow>(cells);
return compositeCell;
}
You can set a different FieldUpdater for handle button click.
I am trying to display image fetch from database in a table view. Here is how I set up my table view with image column:
TableColumn prodImageCol = new TableColumn("IMAGES");
prodImageCol.setCellValueFactory(new PropertyValueFactory<Product, Image>("prodImage"));
prodImageCol.setMinWidth(100);
// setting cell factory for product image
prodImageCol.setCellFactory(new Callback<TableColumn<Product, Image>, TableCell<Product, Image>>() {
#Override
public TableCell<Product, Image> call(TableColumn<Product, Image> param) {
TableCell<Product, Image> cell = new TableCell<Product, Image>() {
#Override //Error here
public void updateItem(Product item, boolean empty) {
if (item != null) {
ImageView imageview = new ImageView();
imageview.setFitHeight(50);
imageview.setFitWidth(50);
imageview.setImage((Image) item.getprodImage());
setGraphic(imageview);
}
}
};
return cell;
}
});
However, I am getting method does not override or implement a method from a supertype. I have no idea why is it so because I follow the same thing from a website on how to display image in table view. Can somebody please explain to me why is it so? Thanks in advance.
UPDATE: The signature of the updateItem method is:
#Override
protected void updateItem(Image image, boolean b) {
super.updateItem(image, b);
}
I posted my original answer too quickly (before I got the same compile error you did).
You can have a method like this if you like:
public void updateItem(Product item, boolean empty);
You just can't annotate it with:
#Override
Which means you are redefining a method with the exact same signature (name and arguments) from the base class.
Alternatively, reverse the generic type arguments:
<Image, Product> vs. <Product, Image>
I have a class called ErrorHighlighter which gets notified anytime a property called errorString is changed. Based on this propertychangeevent I update the HighLighterPredicate to highlight a particular row with a red background.
ErrorHighlighter receives the propertychangeevent, it also changes the HighlighterPredicate, but the table row does not get updated with red background.
I also update the tooltip of the row. That does not get reflected either.
Please see the code below. Could someone please help?
public class ErrorRowHighlighter extends ColorHighlighter implements PropertyChangeListener {
private Map<Integer, String> rowsInError;
private SwingObjTreeTable<ShareholderHistoryTable> treeTable;
public ErrorRowHighlighter(SwingObjTreeTable<ShareholderHistoryTable> treeTable) {
super(CommonConstants.errorColor, null);
this.treeTable = treeTable;
rowsInError=new HashMap<Integer, String>();
setHighlightPredicate(new HighlightPredicate() {
#Override
public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
if(rowsInError.containsKey(adapter.row)){
return true;
}
return false;
}
});
this.treeTable.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
int row=ErrorRowHighlighter.this.treeTable.rowAtPoint(e.getPoint());
if(rowsInError.containsKey(row)){
ErrorRowHighlighter.this.treeTable.setToolTipText(rowsInError.get(row));
}else{
ErrorRowHighlighter.this.treeTable.setToolTipText(null);
}
}
});
}
public void highlightRowWithModelDataAsError(ShareholderHistoryTable modelData){
int indexForNodeData = treeTable.getIndexForNodeData(modelData);
if(indexForNodeData>-1){
rowsInError.put(indexForNodeData, modelData.getErrorString());
updateHighlighter();
}
}
public void unhighlightRowWithModelDataAsError(ShareholderHistoryTable modelData){
int indexForNodeData = treeTable.getIndexForNodeData(modelData);
if(indexForNodeData>-1){
rowsInError.remove(indexForNodeData);
updateHighlighter();
}
}
public void updateHighlighter(){
treeTable.removeHighlighter(this);
treeTable.addHighlighter(this);
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
ShareholderHistoryTable sourceObject= (ShareholderHistoryTable) evt.getSource();
if(StringUtils.isNotEmpty(sourceObject.getErrorString())){
highlightRowWithModelDataAsError(sourceObject);
}else{
unhighlightRowWithModelDataAsError(sourceObject);
}
}
}
This looks like a mistake on my part. The method treeTable.getIndexForNodeData() actually returns back the index of the row by doing a pre-order traversal of the underlying tree data structure. This includes a root node that is not being displayed on the jxtreetable. Hence I needed to minus 1 from the index
int indexForNodeData = treeTable.getIndexForNodeData(modelData)-1;
This fixed the problem for me. I am leaving the post rather than deleting it if anyone wants to look at an example of a ColorHighlighter and a property change listener.
I have form with dateTimeField, and ListView.
ListView looks like that:
final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) {
#Override
protected void populateItem(final ListItem<String> item) {
final String country = item.getModelObject();
item.add(new ValidationDisplayableLabel("country", country, new String[] { modelPath }));
item.add(new AjaxLink("deleteLink") {
#Override
public void onClick(AjaxRequestTarget target) {
model.getObject().getCountry().remove(country);
if (issPeriod) {
addButton.setVisible(true);
countryTextField.setVisible(true);
findButton.setVisible(true);
}
if (target != null)
target.addComponent(rowPanel);
}
});
}
};
countryTextField = new ValidationDisplayableTextField("countryCodeInput", model.bind("oneCountry"), "job.country.value");
**countryView.setReuseItems(true);**
rowPanel.add(countryView);
rowPanel.add(countryTextField);
addButton.setOutputMarkupPlaceholderTag(true);
rowPanel.add(addButton);
And the addButton looks like that:
AjaxSubmitLink addButton = new AjaxSubmitLink(LinkNames.addCountry.toString()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form form) {
if (model.getObject().getOneCountry() != null)
addCountry();
if (target != null)
target.addComponent(rowPanel);
target.addComponent(form.getPage().get("feedbackPanel"));
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form)
{
onSubmit(target, form);
}
};
The thing is, that when I fail my dateTimeField (e.g. set hours to 100), enter country code in countryTextField, and press on addButton, it displays validation message in feedback panel, that hour range is incorrect, but don't add the country. This is because my model isn't updated. Maybe there is a way to update it manually? So validation message will be displayed, but the country listView still could be updated?
Submit of the whole form is on other button, so logically it is normal to add a country even if there is a validation error in dateTimeField.
Thanks!
P.S. i've read a lot of posts about similar problem, but most of them were solved with .setReuseItems(true), but it doesn't work in my case.
P.P.S Apache wicket 1.4.17
As an update to this answer, in Wicket 6, you can accomplish this by overriding onError() in the Form:
#Override
protected void onError() {
super.onError();
this.updateFormComponentModels();
}
I faced a similar problem in my project, the workaround I found was to use a special Visitor. It will update the model even though the submitted input is invalid.
public class VisitorUpdateModelWithoutValidation implements FormComponent.IVisitor {
public Object formComponent(IFormVisitorParticipant formComponent) {
if (formComponent instanceof FormComponent) {
final FormComponent<?> formComponent1 = (FormComponent<?>) formComponent;
boolean required = formComponent1.isRequired();
if (required) {
formComponent1.setRequired(false);
}
formComponent1.modelChanging();
formComponent1.validate();
formComponent1.updateModel();
formComponent1.modelChanged();
if (required) {
formComponent1.setRequired(true);
}
}
return Component.IVisitor.CONTINUE_TRAVERSAL;
}
}
Simply use it in the onSubmit method of your behavior : getForm().visitFormComponents(new VisitorUpdateModelWithoutValidation());
You can issue a field.clearInput() on the fields you are updating before you target the update(s).