I am using GWT 2.3.I which I am using GWT cell table.
Here below is the code for my cell table:
public class FormGrid extends SuperGrid {
List<Form> formList;
#Override
public void setColumns(CellTable table) {
TextColumn<Form> nameColumn = new TextColumn<Form>() {
#Override
public String getValue(Form object) {
return object.getName();
}
};
table.addColumn(nameColumn, "Name");
}
#Override
public void setData() {
if (formList != null && formList.size() > 0) {
AsyncDataProvider<Form> provider = new AsyncDataProvider<Form>() {
#Override
protected void onRangeChanged(HasData<Form> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= formList.size() ? formList.size() : end;
List<Form> sub = formList.subList(start, end);
updateRowData(start, sub);
}
};
provider.addDataDisplay(getTable());
provider.updateRowCount(formList.size(), true);
}
}
public List<Form> getFormList() {
return formList;
}
public void setFormList(List<Form> formList) {
this.formList = formList;
}
}
In this my set column and set data will be called fro super class flow.This cell table is working fine.
Now I want to put a filter type facility (like search) in this cell table.It should be like, there is a texbox above the cell table and what ever written in that text box, it should fire a like query to all form name for that text box value.
for example I have 1000 form in the grid.Now if user writes 'app' in some filter textbox above the cell table the all the form which have 'app' in there name will be filtered and grid has only those forms only.
This is the first case:
Another case is I am only render one column in grid name.I have two more properties in form (description,tag).But I am not rendering them.now for filter if user writes 'app' in filter box then it should make a query to all three (name, description, and tag) and should return if 'app' matched to any of three.
I am not getting how to apply filter in cell table.
Please help me out.Thanks in advance.
You can find an implementation in the expenses sample.
Here is a short summary of the steps
1.) Create a Textbox and a SearchButton.
2.) add a clickHandler to the SearchButton (You can also add KeyUpHandler to the Textbox alternatively)
searchButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
search();
}
});
3.) In the search function retrieve the searchString and store it.
private void search() {
searchString = searchBox.getText();
setData();
}
4.) modify your setdata() function to take searchString into account
#Override
public void setData() {
if (formList != null && formList.size() > 0) {
AsyncDataProvider<Form> provider = new AsyncDataProvider<Form>() {
#Override
protected void onRangeChanged(HasData<Form> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
//new function if searchString is specified take into account
List<Form> sub = getSubList(start,end);
end = end >= sub.size() ? sub.size() : end;
updateRowData(sub.subList(start, end);, sub);
}
};
provider.addDataDisplay(getTable());
provider.updateRowCount(formList.size(), true);
}
}
private List<Form> getSubList(int start, int end) {
List<Form> filtered_list = null;
if (searchString != null) {
filtered_list= new ArrayList<Form>();
for (Form form : formList) {
if (form.getName().equals(searchString) || form.getTag().equals(searchString) || form.getDescription().equals(searchString))
filtered_list.add(form);
}
}
else
filtered_list = formList;
return filtered_list;
}
can propose another solution what can be used quite easy multiple times.
Idea is to create custom provider for your celltable.
GWT celltable filtering
Video in this post shows it in action.
Here is the part of code of custom list data provider which u have to implement.
#Override
protected void updateRowData(HasData display, int start, List values) {
if (!hasFilter() || filter == null) { // we don't need to filter, so call base class
super.updateRowData(display, start, values);
} else {
int end = start + values.size();
Range range = display.getVisibleRange();
int curStart = range.getStart();
int curLength = range.getLength();
int curEnd = curStart + curLength;
if (start == curStart || (curStart < end && curEnd > start)) {
int realStart = curStart < start ? start : curStart;
int realEnd = curEnd > end ? end : curEnd;
int realLength = realEnd - realStart;
List<t> resulted = new ArrayList<t>(realLength);
for (int i = realStart - start; i < realStart - start + realLength; i++) {
if (filter.isValid((T) values.get(i), getFilter())) {
resulted.add((T) values.get(i));
}
}
display.setRowData(realStart, resulted);
display.setRowCount(resulted.size());
}
}
}
Related
We would like to implement AutoCompleteTextField field, once user has selected the field from AutoComplete result, then system would auto populate on other text field, i have used the component AjaxFormComponentUpdatingBehavior (blur), however this will take effect on every text input from AutoCompleteTextField field, but if i change to AjaxFormComponentUpdatingBehavior (change), it doesnt work.
Below is the sample code:
AutoCompleteTextField<String> field_postcode = new AutoCompleteTextField<String>("field_postcode",
new PropertyModel<String>(getModelObject(), "wAdditionalInfo.postal"), autoCompleteRenderer) {
private static final long serialVersionUID = 1L;
#Override
protected Iterator<String> getChoices(String input) {
if (Strings.isEmpty(input)) {
List<String> emptyList = Collections.emptyList();
return emptyList.iterator();
}
List<String> choices = new ArrayList<String>();
List<Postcode> postcodeList = getProfileManager().findAllPostcodeByPostcode(input);
for (Postcode p : postcodeList) {
String postcode = p.getPostcode();
if (postcode.startsWith(input)) {
choices.add(p.getPostcode());
if (choices.size() == 10) {
break;
}
}
}
return choices.iterator();
}
};
field_postcode.setRequired(true);
field_postcode.add(new AjaxFormComponentUpdatingBehavior("blur"){
private static final long serialVersionUID=-1107858522700306810L;
#Override protected void onUpdate( AjaxRequestTarget target){
Postcode postcode = getProfileManager().findPostcodeByPostcode(field_postcode.getInput());
if (postcode != null) {
City city = postcode.getCity();
State state = city.getState();
field_city.setModelObject(city.getCity());
ddl_state.setModelObject(state);
if (isDisplayTip) {
//isDisplayTip true mean is from widrawal webform
isReadonly = true;
} else {
field_city.setEnabled(false);
}
ddl_state.setEnabled(false);
} else {
if (isDisplayTip) {
isReadonly = false;
} else {
field_city.setEnabled(true);
}
ddl_state.setEnabled(true);
}
target.add(field_city, ddl_state);
}
}
);
Is there any api from wicket to achieve this? We need to have something when user select the option from Auto complete, then it only onUpdate method of AjaxFormComponentUpdatingBehavior
According to https://github.com/apache/wicket/blob/cbc237159c4c6632b4f7db893c28ab39d1b40ed4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js#L620 it should trigger change event on the HTMLInputElement and thus notify you on the server side.
Use the browser debugger to see whether https://github.com/apache/wicket/blob/cbc237159c4c6632b4f7db893c28ab39d1b40ed4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js#L453 is executed and whether it leads to an Ajax call with the value in the parameters.
I develop extension of PDT plugin. I need dialog with interfaces only (not classes). Basic code looks like it:
OpenTypeSelectionDialog2 dialog = new OpenTypeSelectionDialog2(
DLTKUIPlugin.getActiveWorkbenchShell(),
multi,
PlatformUI.getWorkbench().getProgressService(),
null,
type,
PHPUILanguageToolkit.getInstance());
It's works fine but I get classes and interfaces together (type variables). Is any method to filter it? I can't find this kind of mechanism in PDT but classes and interfaces are recognize correctly (icons next to names).
I don't know if its the best solution but it works.
int falseFlags = 0;
int trueFlags = 0;
IDLTKSearchScope scope = SearchEngine.createSearchScope(getScriptFolder().getScriptProject());
trueFlags = PHPFlags.AccInterface;
OpenTypeSelectionDialog2 dialog = new OpenTypeSelectionDialog2(
DLTKUIPlugin.getActiveWorkbenchShell(),
multi,
PlatformUI.getWorkbench().getProgressService(),
scope,
IDLTKSearchConstants.TYPE,
new PHPTypeSelectionExtension(trueFlags, falseFlags),
PHPUILanguageToolkit.getInstance());
And PHPTypeSelectionExtension looks like this:
public class PHPTypeSelectionExtension extends TypeSelectionExtension {
/**
* #see PHPFlags
*/
private int trueFlags = 0;
private int falseFlags = 0;
public PHPTypeSelectionExtension() {
}
public PHPTypeSelectionExtension(int trueFlags, int falseFlags) {
super();
this.trueFlags = trueFlags;
this.falseFlags = falseFlags;
}
#Override
public ITypeInfoFilterExtension getFilterExtension() {
return new ITypeInfoFilterExtension() {
#Override
public boolean select(ITypeInfoRequestor typeInfoRequestor) {
if (falseFlags != 0 && (falseFlags & typeInfoRequestor.getModifiers()) != 0) {
// Try to filter by black list.
return false;
} else if (trueFlags == 0 || (trueFlags & typeInfoRequestor.getModifiers()) != 0) {
// Try to filter by white list, if trueFlags == 0 this is fine 'couse we pass black list.
return true;
} else {
// Rest is filter out.
return false;
}
}
};
}
#SuppressWarnings("restriction")
#Override
public ISelectionStatusValidator getSelectionValidator() {
return new TypedElementSelectionValidator(new Class[] {IType.class, INamespace.class}, false);
}
}
I am using GWT 2.5 to create a CellTable with a sortable date column.
My code is as follows:
CellTable<Activity> table = new CellTable<Activity>();
table.setRowStyles(new RowStyles<Activity>() {
#Override
public String getStyleNames(Activity row, int rowIndex) {
return TABLE_ROW_STYLE_NAME;
}
});
// create date column
TextColumn<Activity> dateColumn = new TextColumn<Activity>() {
#Override
public String getValue(Activity a) {
return dateFormat.format(a.getDate());
}
};
dateColumn.setSortable(true);
dateColumn.setDefaultSortAscending(false);
// add column to table
table.addColumn(dateColumn, myConstants.dateColumnHeader());
// attach provider to table
activityProvider.addDataDisplay(table);
// create sort handler
ListHandler<Activity> sortHandler = new ListHandler<Activity>(activityProvider.getList());
sortHandler.setComparator(dateColumn, new Comparator<Activity>() {
#Override
public int compare(Activity a1, Activity a2) {
if (a1 == a2) {
return 0;
}
// compare the date columns
if (a1 != null) {
if (a2 != null) {
long a1Val = a1.getDate().getTime();
long a2Val = a2.getDate().getTime();
if (a1Val == a2Val) {
return 0;
}
else if (a1Val > a2Val) {
return 1;
}
else {
return -1;
}
}
else {
return 1;
}
}
return -1;
}
});
// add sort handler to table
table.addColumnSortHandler(sortHandler);
// add date column to table's sort list
table.getColumnSortList().push(dateColumn);
table.setWidth("100%");
getView().getActivityPanel().add(table);
With this code, the data is displayed in the table and the sorting arrow on the column appears. However, nothing happens when I click on the sortable column's header. The sorting order doesn't change, rows are not rearranged.
Can anyone spot the problem here? This code is almost the same as what they have in Google's own example.
This is what I use:
dateColumn.setSortable(true);
sortHandler.setComparator(dateColumn, new Comparator<ObjectPobject>() {
public int compare(ObjectPobject o1, ObjectPobject o2) {
return o1.getDate().compareTo(o2.getDate());
}
});
It should be
a1.getDate().getTime().compareTo(a2.getDate().getTime())
or
a1.getDate().after(a2.getDate())
This happens because GWT uses JavaScript comparisons, and compareTo does not work for dates.
has someone been able to correctly to update a cell browser at runtime, i.e. when u remove a node or add a node, the change is reflected immediately in the CEll Browser, because I am using a List and when i am making a change it is not being updated on the spot
You can use ListDataProvider setList(...) method for dynamic updates. Here is an example how I update cell browser via RPC:
private void loadAllData(final ListDataProvider<Data> dataProvider) {
dBservice.getAllData(new AsyncCallback<List<Data>>() {
public void onSuccess(List<Data> result) {
dataProvider.setList(result);
}
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
});
}
to refresh a cellBrowser you have to close all the child on the root node.
anyway something like this
for (int i = 0; i < cellBrowser.getRootTreeNode().getChildCount(); i++) {
cellBrowser.getRootTreeNode().setChildOpen(i, false);
}
the AsyncDataProvider calls refreshes data
private final class Model implements TreeViewModel{
private List<ZonaProxy> zonaList = null;
private List<CategoriaProxy> categoriaList = null;
public void setCategoriaList(List<CategoriaProxy> categoriaList) {
this.categoriaList = categoriaList;
}
public void setListZona(List<ZonaProxy> zonaList) {
this.zonaList = zonaList;
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public <T> NodeInfo<?> getNodeInfo(T value) {
CategoryDataProvider dataProvider1 = new CategoryDataProvider();
return new DefaultNodeInfo(dataProvider1, new CategoriaCell());
}
/**
* Check if the specified value represents a leaf node. Leaf nodes cannot be
* opened.
*/
public boolean isLeaf(Object value) {
if (value instanceof CategoriaProxy){
if (((CategoriaProxy) value).getLivello() == 3) {
return true;
}
}
return false;
}
}
private class CategoryDataProvider extends AsyncDataProvider<CategoriaProxy>
{
#Override
protected void onRangeChanged(HasData<CategoriaProxy> display)
{
requests.categoriaRequest().findAllCategorias(0, 8).with().fire(new Receiver<List<CategoriaProxy>>() {
#Override
public void onSuccess(List<CategoriaProxy> values) {
updateRowCount(values.size(), true);
updateRowData(0, values);
}
});
}
}
it Works.
Apparently it is not enough to change the data provider and refresh it.
You need also to force the affected cell to close and reopen it, as in this example
public void updateCellBrowser(String id) {
TreeNode node = getNode(cellBrowser.getRootTreeNode(),id);
if(node != null && ! node.isDestroyed()) {
TreeNode parent = node.getParent();
int index = node.getIndex();
parent.setChildOpen(index, false,true);
parent.setChildOpen(index, true, true);
}
}
In my particular example the cell ids are pathnames hence the following
implementation of getNode().
private TreeNode getNode(TreeNode node, String id) {
for(int i=0; i < node.getChildCount(); i++)
if(node.isChildOpen(i)) {
Object value = node.getChildValue(i);
if(value instanceof String) {
String nodeId = ((String) value);
if(id.equals(nodeId))
return node.setChildOpen(i, true);
if(id.startsWith(nodeId))
getNode(node.setChildOpen(i, true),id);
}
}
return null;
}
I'm capturing a right click event to show a context menu. What I haven't been able to figure out, is how to make the right click actually select the TreeItem, prior to showing of context menu.
All help is appreciated.
private Tree tree = new Tree() {
#Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONCONTEXTMENU) {
DOM.eventPreventDefault(event);
showContextMenu(event);
}
super.onBrowserEvent(event);
}
#Override
protected void setElement(Element elem) {
super.setElement(elem);
sinkEvents(Event.ONCONTEXTMENU);
}
};
ONMOUSEDOWN event gets fired before ONCONTEXTMENU. Have you tried to listen for onMouseDown events, and set the selected item? Something along these lines:
#Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
TreeItem selectedItem = findSelectedItem(event);
if (selectedItem != null) {
selectedItem.setSelected(true);
}
} else {
super.onBrowserEvent(event);
}
break;
case Event.ONCONTEXTMENU:
showContextMenu(event);
break;
default:
super.onBrowserEvent(event);
break;
}
and findSelectedItem traverses the tree looking for the selected item:
TreeItem findSelectedItem(Event e) {
return findSelectedItemRecursive(event.getClientX(), event.getClientY());
}
TreeItem findSelectedTreeItemRecursive(TreeItem root, int x, int y) {
if (null == root) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
TreeItem selected = findSelectedTreeItemRecursive(getItem(i), x, y);
if (selected != null) {
return selected;
}
}
return null;
}
int count = item.getChildCount();
for (int i = 0; i < count; i++) {
TreeItem selected = findSelectedTreeItem(item.getChild(i), x, y);
if (selected != null) {
return selected;
}
}
if (x >= item.getAbsoluteLeft()
&& x <= item.getAbsoluteLeft() + item.getOffsetWidth()
&& y >= item.getAbsoluteTop()
&& y <= item.getAbsoluteTop() + item.getOffsetHeight()) {
return item;
}
return null;
}
You can use dedicated overloaded TreeItem :
public class MyTreeItem extends TreeItem implements ContextMenuHandler {
public SBTreeItem(SBItemTree tree, String name) {
super();
Label w = new Label(name);
w.addDomHandler(this, ContextMenuEvent.getType());
setWidget(w);
}
public void onContextMenu(ContextMenuEvent event) {
Window.alert(getSBItem().getName());
event.getNativeEvent().stopPropagation();
}
}
I'd just like to add a couple of links leading to issues about this:
http://code.google.com/p/google-web-toolkit/issues/detail?id=4529&q=right%20click%20selection
http://code.google.com/p/google-web-toolkit/issues/detail?id=4604&q=right%20click%20selection
I know this is an old question, but hopefully here's an answer that will save time for the masses hitting this page from a Google search. IMO, the best way is to use Google's own internal tree searching code -- it's a solution that scales very well with the number of elements in the tree. I
am using GWT 2.5.1.
private void initTree() {
tree = new Tree() {
#Override
public void onBrowserEvent(Event event) {
/*
* If the event is a context menu event, we want the tree item
* to also be selected.
*
* This logic must occur before the call to the superclass
* method so the selection is updated before the context menu
* logic executes. This is useful when we want to make items in
* the context menu invisible/disabled based on the selection.
*/
if (DOM.eventGetType(event) == Event.ONCONTEXTMENU) {
if (getItemCount() > 0) {
// In my use case there is only 1 top-level tree item
TreeItem root = getItem(0);
// Taken from com.google.gwt.user.client.ui.Tree.elementClicked(Element):
ArrayList<Element> chain = new ArrayList<Element>();
collectElementChain(chain, getElement(), DOM.eventGetTarget(event));
TreeItem selection = findItemByChain(chain, 0, root);
/*
* For some reason SelectionEvent will only fire if
* selection is non-null; I am firing the selection
* event manually because I want to know when there has
* been a deselection of an item in the tree.
*/
if (selection != null) {
this.setSelectedItem(selection);
} else {
SelectionEvent.fire(this, null);
}
}
}
super.onBrowserEvent(event);
}
};
tree.setAnimationEnabled(true);
}
//// BEGIN code copied from com.google.gwt.user.client.ui.Tree:
/**
* Collects parents going up the element tree, terminated at the tree root.
*/
private void collectElementChain(ArrayList<Element> chain, Element hRoot,
Element hElem) {
if ((hElem == null) || (hElem == hRoot)) {
return;
}
collectElementChain(chain, hRoot, DOM.getParent(hElem));
chain.add(hElem);
}
private TreeItem findItemByChain(ArrayList<Element> chain, int idx,
TreeItem root) {
if (idx == chain.size()) {
return root;
}
Element hCurElem = chain.get(idx);
for (int i = 0, n = root.getChildCount(); i < n; ++i) {
TreeItem child = root.getChild(i);
if (child.getElement() == hCurElem) {
TreeItem retItem = findItemByChain(chain, idx + 1,
root.getChild(i));
if (retItem == null) {
return child;
}
return retItem;
}
}
return findItemByChain(chain, idx + 1, root);
}
//// END