I have a generic GXT3 ComboBox which display all available values for enums :
public static <T extends Enum<T>> ComboBox<T> buildEnumCombo(Class<T> t){
ListStore<T> listStore=new ListStore<T>(new EnumModelKeyProvider<T>());
for(T e:t.getEnumConstants()){
listStore.add(e);
}
ComboBox<T> combo= new ComboBox<T>(listStore, new EnumLabelProvider<T>());
combo.setTriggerAction(ComboBoxCell.TriggerAction.ALL);
return combo;
}
This combo works fine.
What I need : I would like a be able to add a "All" value.
I tried to add "null" in the store and customize the LabelProvider to display "All" for this particular case but it does not work as expected : the combo contains the expected line but it displays an empty text instead of "All" and the line does not have a correct size.
Here is my generic ModelKeyProvider for enums
public class EnumModelKeyProvider<T extends Enum> implements ModelKeyProvider<T> {
#Override
public String getKey(T item) {
if(item==null){
return null;
}else{
return item.name();
}
}
And my generic LabelProvider :
public class EnumLabelProvider<T extends Enum<T>> implements LabelProvider<T> {
#Override
public String getLabel(T item) {
if(item==null){
return "All";
}else{
return I18nEnum.i18nEnum(item);
}
}
}
Maybe not the solution you are looking for, but I solved this but simply setting the emptyText of the ComboBox to "All".
Try SimpleComboBox (tested on gxt 2.2.5)
private SimpleComboBox<String> createSimpleComboBox(){
SimpleComboBox<String> combo = new SimpleComboBox<String>();
combo.setTypeAhead(true);
combo.setTriggerAction(TriggerAction.ALL);
combo.setEditable(editable);
combo.setForceSelection(true);
combo.setTemplate(getComboTemplate());
return combo;
}
private native String getComboTemplate() /*-{
return [
'<tpl for=".">',
'<tpl if="value == \'\'">',
'<div class="x-combo-list-item" qtip="N/A" qtitle=""></BR></div>',
'</tpl>',
'<tpl if="value != \'\'">',
'<div class="x-combo-list-item" qtip="{value}" qtitle="">{value}</div>',
'</tpl>',
'</tpl>'
].join("");
}-*/;
public SimpleComboBox<String> buildComboBox(){
SimpleComboBox<String> combo = createSimpleComboBox();
combo.add("");
List<String> list = new ArrayList<String>();
for(T e:t.getEnumConstants()){
list.add(e.name());
}
combo.add(list);
return combo;
}
Related
i'm currently using a GXT3 grid to display data from a custom object EntityDAO.
This class contains 3 attributes: an id and two references to complex type objects
Let's call them
Long id;
UserInfo userInfo;
OutputInfo outputInfo;
I created an interface to explicit the desired display of these info:
interface EntityDAOProperties extends PropertyAccess<EntityDAO> {
ModelKeyProvider<EntityDAO> id();
#Path("userInfo.name")
ValueProvider<EntityDAO, String> step();
#Path("outputInfo.name")
ValueProvider<EntityDAO, String> outputInfo();
}
The display is perfectly fine. The matter is that i want to be able to add/edit rows to my grid.
To do so, I have a
GridRowEditing<EntityDAO> editing = createGridEditing(grid);
comprising a
SimpleComboBox<String> comboUser = new SimpleComboBox<String>(new LabelProvider<String>() {
#Override
public String getLabel(String item) {
return item;
}
});
for(...){
comboUser.add("entry " + i); // For instance
logger.info("entry : " +i); // For instance
i++;
}
comboUser.setEditable(false);
comboUser.setTriggerAction(TriggerAction.ALL);
When i double click on my line and make the GridRowEditing appear, the combo doesn't seem to have more than 1 row and the click on the expand arrow doesn't change anything to the matter.
I think you miss the part where you set the property editor for the combobox, here is the example code:
SimpleComboBox<Light> combo = new SimpleComboBox<Light>(new StringLabelProvider<Light>());
combo.setClearValueOnParseError(false);
combo.setPropertyEditor(new PropertyEditor<Light>() {
#Override
public Light parse(CharSequence text) throws ParseException {
return Light.parseString(text.toString());
}
#Override
public String render(Light object) {
return object == null ? Light.SUNNY.toString() : object.toString();
}
});
combo.setTriggerAction(TriggerAction.ALL);
combo.add(Light.SUNNY);
combo.add(Light.MOSTLYSUNNY);
combo.add(Light.SUNORSHADE);
combo.add(Light.MOSTLYSHADY);
combo.add(Light.SHADE);
// combo.setForceSelection(true);
editing.addEditor(cc2, new Converter<String, Light>() {
#Override
public String convertFieldValue(Light object) {
return object == null ? "" : object.toString();
}
#Override
public Light convertModelValue(String object) {
try {
return Light.parseString(object);
} catch (ParseException e) {
return null;
}
}
}, combo);
Hope this could help you.
I am trying to display an icon along with text in suggestion drop down using SuggestBox and MultiWordSuggestOracle following code:
public class Suggestions implements Suggestion {
private String suggestion;
public Suggestions(){}
public Suggestions(String suggestion){
this.suggestion = new String( suggestion );
}
#Override
public String getDisplayString() {
return ( suggestion + " <img src='/images/image.png'/> " );
}
#Override
public String getReplacementString() {
return suggestion;
}}
And in onModuleLoad function contain following code:
MultiWordSuggestOracle oracle = new MultiWordSuggestOracle(){
#Override
public boolean isDisplayStringHTML() {
return true;
}};
oracle.add(new Suggestions("A").getDisplayString());
SuggestBox suggestionBox = new SuggestBox(oracle);
Problem : html code is printed as normal text. Could you guys please suggest whats wrong with the code?
Thanx!
Because your Suggestion class is never used !
The multiword oracle has just the display string, and create his own Suggestion items.
Just override the methode createSuggestion in the oracle :
MultiWordSuggestOracle oracle = new MultiWordSuggestOracle(){
#Override
public boolean isDisplayStringHTML() {
return true;
}
#Override
protected MultiWordSuggestion createSuggestion(String replacementString, String displayString) {
return new Suggestions(replacementString);
}
};
oracle.add(new Suggestions("A").getDisplayString());
SuggestBox suggestionBox = new SuggestBox(oracle);
Below is what I did to get image+text in suggestion drop down.
public class Suggestions implements Suggestion {
private String suggestion;
public Suggestions(){}
public Suggestions(String suggestion){
this.suggestion = new String( suggestion );
}
#Override
public String getDisplayString() {
return ( suggestion + new Image('/images/image.png') );
}
#Override
public String getReplacementString() {
return suggestion;
}}
OnModuleLoad function is:
MultiWordSuggestOracle oracle = new MultiWordSuggestOracle(){
#Override
public boolean isDisplayStringHTML() {
return true;
}
#Override
protected MultiWordSuggestion createSuggestion(String replacementString, String displayString) {
return new Suggestions(replacementString);
}
};
oracle.add("A");
SuggestBox suggestionBox = new SuggestBox(oracle);
I have two buttons(edit + delete) in one column.
ButtonCell functionButtonCell = new ButtonCell() {
#Override
public void render(final Context context, final SafeHtml data, final SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<button type='button' class='gwt-Button' style = 'width:60px;margin:1px;'>Edit</button>");
sb.appendHtmlConstant("<br/>");
sb.appendHtmlConstant("<button type='button' class='gwt-Button' style = 'width:60px;margin:1px;'>Delete</button>");
}
};
functionColumn = new Column<AdminModel, String>(functionButtonCell) {
public String getValue(final AdminModel object) {
return object.getSeq().toString();
}
};
Bind event for this column in Presenter as
.........
view.getFunctionColumn().setFieldUpdater(new FieldUpdater<AdminModel, String>() {
public void update(final int index, final AdminModel object, final String value) {
Window.alert(index + "-" + value);
}
});
After clicked on edit button , alert-box has appeared , but not on delete button. When I clicked on delete button , nothing has appeared. What would be the problem ?
Addition: How can I decide which button was clicked by user (edit or delete) from my presenter ?
I would really appreciate any of your suggestions because I am troubled on it for a long times. Thanks!
ButtonCell filters events on the first child element only: https://gwt.googlesource.com/gwt/+/2.6.1/user/src/com/google/gwt/cell/client/ButtonCell.java This is why you don't get an event when clicking the second button (note: the goal of that code is to make sure you clicked on the button, and not on blank space around the button; see https://gwt.googlesource.com/gwt/+/a0dc88c8be7408be9554f746eb1ec93798183a28)
The easiest way to implement a two-button cell is to use a CompositeCell; it requires that child cells are rendered into sibling elements though (uses <span>s by default, example below overrides the rendering to use <div>s so your buttons stack each on its own line).
new CompositeCell<AdminModel>(Arrays.asList(
// First button
new HasCell<AdminModel, String>() {
#Override public Cell<String> getCell() { return new ButtonCell(); }
#Override public FieldUpdated<AdminModel, String> getFieldUpdater() {
return new FieldUpdater<AdminModel, String>() {
#Override public void update(int index, AdminModel object, String value) {
Window.alert("Edit " + object.getId());
}
};
}
#Override public String getValue(AdminModel o) {
return "Edit";
}
},
// Second button
new HasCell<AdminModel, String>() {
#Override public Cell<String> getCell() { return new ButtonCell(); }
#Override public FieldUpdated<AdminModel, String> getFieldUpdater() {
return new FieldUpdater<AdminModel, String>() {
#Override public void update(int index, AdminModel object, String value) {
Window.alert("Delete " + object.getId());
}
};
}
#Override public String getValue(AdminModel o) {
return "Delete";
}
}) {
#Override protected <X> void render(Cell.Context context, AdminModel value, SafeHtmlBuilder sb, HasCell<String,X> hasCell) {
// use a <div> instead of the default <span>
Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<div>");
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant("</div>");
}
};
(note: in your case, because the button's text doesn't depend on the row object, maybe you should rather use an ActionCell; it would better fit "semantically" with what you're doing, but otherwise it's almost the same; with an ActionCell, you'd use HasCell<AdminModel, AdminModel>, ActionCell<AdminModel>, getFieldUpdater would return null, and thegetValueof theHasCellwould just return theAdminModel` argument as-is).
Otherwise, implement your Cell (or AbstractCell) entirely by yourself.
Ideally, a column should have only one type of cell be it ImageCell, ButtonCell etc. Because all this ImageCell and ButtonCell does not provide any in-built events. The events are handled by FieldUpdater itself which does not have differentiators to identify that which ButtonCell is clicked. Ideally on click of that column, the field-updater will be called.
You should rather create your own composite widget which extends HasCell. This composite widget will have two different buttons and those in built methods are called on click of respective button.
public void onModuleLoad() {
CellTable<Person> table = new CellTable<Person>();
List<HasCell<Person, ?>> cells = new LinkedList<HasCell<Person, ?>>();
cells.add(new ActionHasCell("Edit", new Delegate<Person>() {
#Override
public void execute(Person object) {
// EDIT CODE
}
}));
cells.add(new ActionHasCell("Delete", new Delegate<Person>() {
#Override
public void execute(Person object) {
// DELETE CODE
}
}));
CompositeCell<Person> cell = new CompositeCell<Person>(cells);
table.addColumn(new TextColumn<Person>() {
#Override
public String getValue(Person object) {
return object.getName()
}
}, "Name");
// ADD Cells for Age and Address
table.addColumn(new Column<Person, Person>(cell) {
#Override
public Person getValue(Person object) {
return object;
}
}, "Actions");
}
private class ActionHasCell implements HasCell<Person, Person> {
private ActionCell<Person> cell;
public ActionHasCell(String text, Delegate<Person> delegate) {
cell = new ActionCell<Person>(text, delegate);
}
#Override
public Cell<Person> getCell() {
return cell;
}
#Override
public FieldUpdater<Person, Person> getFieldUpdater() {
return null;
}
#Override
public Person getValue(Person object) {
return object;
}
}
Also, see the link below.
[GWT CellTable-Need to have two buttons in last single cell of each row
Does anyone know how to display an Icon and a Text for the displaying field in ext-gwts combobo? I tried everything.
In the third ComboBox of this example (klick me) there is an icon and the text for the selectable values. This was no problem with the example template. But i want to show the icon and the text for the selected value too. How can i manage this?
I have a Model class for the icon and the text.
public class Language extends DbBaseObjectModel {
private static final long serialVersionUID = 8477520184310335811L;
public Language(String langIcon, String langName) {
setLangIcon(langIcon);
setLangName(langName);
}
public String getLangIcon() {
return get("langIcon");
}
public String getLangName() {
return get("langName");
}
public void setLangIcon(String langIcon) {
set("langIcon", langIcon);
}
public void setLangName(String langName) {
set("langName", langName);
}
}
This is how i initalize the ComboBox. I want to change the displayField "langName".
final ListStore<Language> countries = new ListStore<Language>();
final Language german = new Language("de_DE", "Deutsch");
final Language english = new Language("en_GB", "Englisch");
countries.add(german);
countries.add(english);
final ComboBox<Language> combo = new ComboBox<Language>();
combo.setWidth(100);
combo.setStore(countries);
combo.setDisplayField("langName");
combo.setTemplate(getFlagTemplate());
combo.setTypeAhead(true);
combo.setTriggerAction(TriggerAction.ALL);
combo.setValue(german);
This is the template for the ComboBox two show the selectable values.
private native String getFlagTemplate() /*-{
return [ '<tpl for=".">', '<div class="x-combo-list-item">',
'<img src="resources/images/lang/{langIcon}.png">',
' {langName}</div>', '</tpl>' ].join("");
}-*/;
How can i use an template for the displayField or is there an other possibility?
Thanks!
You need to implement a com.extjs.gxt.ui.client.widget.form.ListModelPropertyEditor.
The com.extjs.gxt.ui.client.widget.form.PropertyEditor#getStringValue returns the string that should be displayed and the com.extjs.gxt.ui.client.widget.form.PropertyEditor#convertStringValue converts the displayed string back into the model.
This isn't a very performant implementation but it works:
public class TemplateModelPropertyEditor<D extends ModelData> extends
ListModelPropertyEditor<D> {
/** Template to render the model. */
private XTemplate template;
#Override
public D convertStringValue(final String value) {
for (final D d : models) {
final String val = getStringValue(d);
if (value.equals(val)) {
return d;
}
}
return null;
}
#Override
public String getStringValue(final D value) {
if (template != null) {
final Element div = DOM.createDiv();
template.overwrite(div, Util.getJsObject(value));
return div.getInnerText();
}
final Object obj = value.get(displayProperty);
if (obj != null) {
return obj.toString();
}
return null;
}
public void setSimpleTemplate(final String html) {
template = XTemplate.create(html);
}
}
Usage:
TemplateModelPropertyEditor<Language> propertyEditor = new TemplateModelPropertyEditor<Language>();
propertyEditor.setSimpleTemplate(getFlagTemplate());
combo.setPropertyEditor(propertyEditor);
which imports?
I added these ones:
import com.extjs.gxt.ui.client.core.XTemplate;
import com.extjs.gxt.ui.client.util.Util;
import com.extjs.gxt.ui.client.widget.form.ListModelPropertyEditor;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
Everthing works fine, but it don't display an icon. When i debug the return div.getInnerText() method throws an error called: Method "getInnerText" with signature "()Ljava/lang/String;" is not applicable on this object.
The created div element looks okay
<DIV><DIV class=x-combo-list-item><IMG src="http://127.0.0.1:8888/resources/images/lang/de_DE.png"> Deutsch</DIV></DIV>
How to add the listbox items using UiBinder?
It is possible since february 2011 version:
http://code.google.com/p/google-web-toolkit/issues/detail?id=4654
Following this patch you are now able to add items following this syntax:
<g:ListBox>
<g:item value='1'>
first item
</g:item>
<g:item value='2'>
second item
</g:item>
</g:ListBox>
This is a listbox of translations of an enumeration, I suppose this also works for a listbox with string values (version of GWT: 2.1.0)
You only need the renderer for translating the enumeration values.
//UI XML
<g:ValueListBox ui:field="requesterType"/>
//JAVA CODE
#UiField(provided = true)
ValueListBox<RequesterType> requesterType = new ValueListBox<RequesterType>(requesterTypeRenderer);
static EnumRenderer<RequesterType> requesterTypeRenderer = new EnumRenderer<RequesterType>();
public Constructor() {
requesterTypeRenderer.setEmptyValue(Translations.translateEmptyValue(RequesterType.class));
requesterType.setAcceptableValues(Arrays.asList(EnumUtil.getRequesterTypes()));
}
/**
* Translates enum entries. Use setEmptyValue() if you want to have a custom empty value. Default empty value is "".
*
* #param <T>
* an enumeration entry which is to be registered in {#link Translations}
*/
public class EnumRenderer<T extends Enum<?>> extends AbstractRenderer<T> {
private String emptyValue = "";
#Override
public String render(T object) {
if (object == null)
return emptyValue;
return Translations.translate(object);
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
}
GWT ValueListbox otherwise know as a ComboBox or Dropdown component.
Another example that also demonstrates populating the list.
UiBinder...
<g:ValueListBox ui:field="subCategory"/>
Editor...
#UiField(provided = true)
ValueListBox<String> subCategory = new ValueListBox<String>(
new Renderer<String>() {
#Override
public String render(String object) {
String s = "Cats";
if (object != null) {
s = object.toString();
}
return s;
}
#Override
public void render(String object, Appendable appendable)
throws IOException {
render(object);
}
});
Constructor...
List<String> values = new ArrayList<String>();
values.add("Animal Shelters and Rescues");
values.add("Birds");
values.add("Cats");
values.add("Dogs");
values.add("Other Pets");
values.add("Rabbits");
subCategory.setAcceptableValues(values);