I'm trying to set field at index 0 in Vaadin combo box to default value, so I could avoid error message if user doesen't select anything. So I would like that instead of blank field I have populated field at index 0.
I have tried to set it and managed it with this:
field.setNullSelectionAllowed(true);
field.setNullSelectionItemId(container.getIdByIndex(0));
So I don't have blank value at index 0, instead my previous value of index 1 is now at index 0. And that is exactly what I want and need and in combo box looks just as I want.
But, unfortunately, when I submit my form, value is not passed. Only values after index 0 are passed. It's so frustrating, can somebody help me? Value passed to setNullSelectionItemId exists 100%.
How can I grab value from index at place 0 in combo box?
p.s. here is my code:
public Field<?> buildAndBindComboBox(final String caption, final BeanItemContainer<?> container,
final Object propertyId, final String title, final ValueChangeListener listener, final boolean nullAllowed,
final boolean required, final boolean enabled, final boolean visible) {
#SuppressWarnings("serial")
ComboBox field = new ComboBox(caption, container) {
// http://dev.vaadin.com/ticket/10544
// - typing in ComboBox causes Internal Error
private boolean inFilterMode;
#Override
public void containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent event) {
if (inFilterMode) {
super.containerItemSetChange(event);
}
}
#Override
protected List<?> getOptionsWithFilter(boolean needNullSelectOption) {
try {
inFilterMode = true;
return super.getOptionsWithFilter(needNullSelectOption);
} finally {
inFilterMode = false;
}
}
};
field.setStyleName("comboBox");
field.setInputPrompt("Select");
if(defaultValue == true){
field.setNullSelectionAllowed(false);
field.setNullSelectionItemId(container.getIdByIndex(0).toString());
//field.select(container.getIdByIndex(0));
//field.setValue(container.getIdByIndex(0));
//field.setRequired(false);
defaultValue = false;
} else {
field.setNullSelectionAllowed(nullAllowed);
field.setRequired(required);
}
field.setImmediate(true);
field.setNewItemsAllowed(false);
field.setFilteringMode(FilteringMode.CONTAINS);
if (title != null) {
field.setItemCaptionPropertyId(title);
}
//field.setNullSelectionAllowed(nullAllowed);
//field.setRequired(required);
field.setVisible(visible);
if (listener != null) {
field.addValueChangeListener(listener);
}
this.bind(field, propertyId);
field.setEnabled(enabled);
return field;
}
public void setDefaultValueFirstItem(boolean def){
defaultValue = def;
}
It is binded like this:
commitmentFeeBinder.setDefaultValueFirstItem(true);
commitmentFeeBinder.buildAndBindComboBox("No working day labels", noWorkingDays, "noWorkingDaysCF", "title", null, false, !transaCF, true, !transaCF);
If I understood your question correctly, Steffen Harbich is correct in suggesting that if you want the first item to be selected by default you should disable null selection and select the first item by default. E.g. this works:
ComboBox cb = new ComboBox("", Arrays.asList("First", "Second", "Third"));
cb.setNullSelectionAllowed(false);
cb.select("First");
Or alternatively with a BeanItemContainer:
List<MyBean> beans = Arrays.asList(new MyBean("First"), new MyBean("Second"), new MyBean("Third"));
BeanItemContainer<MyBean> bic = new BeanItemContainer<>(MyBean.class, beans);
ComboBox cb = new ComboBox("", bic);
cb.setNullSelectionAllowed(false);
cb.select(bic.getIdByIndex(0));
private void resetComboBoxToIndex(ComboBox combo, int index) {
BeanItemContainer<Bean_ComboBox> items_combo = (BeanItemContainer<Bean_ComboBox>)combo.getContainerDataSource();
if(items_combo != null && items_combo.size() > index) {
Bean_ComboBox primerItem = items_combo.getIdByIndex(index);
if(primerItem != null) {
combo.select(primerItem);
}
}
}
Related
I could not find any column to set background image inside SearchManager class.
When Google Play app's search result is selected, a background image is displayed but I don't seem to find any public api/column to set it.
Here is my code for content provider's query method
Any idea guys?
Device: Nexus player
#Nullable
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
final String searchKey = (selectionArgs == null) ? "" : selectionArgs[0];
if (!TextUtils.isEmpty(searchKey)) {
// Get title list from search query
ArrayList<TitleSimpleInfo> searchedTitleList = searchTitlesWithKeyword(searchKey);
// return null cursor if no data found
if (searchedTitleList == null || searchedTitleList.isEmpty()) {
return null;
}
// prepare cursor
MatrixCursor matrixCursor = new MatrixCursor(new String[]{
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_TEXT_2,
SearchManager.SUGGEST_COLUMN_CONTENT_TYPE,
SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE,
});
// add search result to cursor
for (TitleSimpleInfo title : searchedTitleList) {
matrixCursor.addRow(new Object[]{
title.getTitleName(),
title.getTitleCatch(),
SEARCH_CONTENT_TYPE,
Intent.ACTION_SEARCH,
SEARCH_INTENT_DATA + title.getTitleCode(),
SEARCH_IMAGE_HEADER + title.getThumbnailUrl(),
});
}
return matrixCursor;
} else {
return null;
}
}
I use table component and generate column for optiongroup.
when change optionGroup's value, and click the save button,
the table get the before value - not changed value..
How to get the chaged value ? Not origin value.
here code...
public class MyTypeColumnGenerator implements ColumnGenerator{
public Object generateCell( Table source, Object itemId, Object columnId) {
BeanItem<MyType> beanItem = (BeanItem<MyType>)source.getItem(itemId);
MyType view = beanItem.getBean() ;
if(view.getValueType().equals(ValueType.Flag)){
// radio
OptionGroup opt = new OptionGroup() ;
opt.addItem(1) ; // y
opt.addItem(0) ; // n
opt.setItemCaption(1, Messages.getString(Messages.Opt_Y));
opt.setItemCaption(0, Messages.getString(Messages.Opt_N));
opt.setStyleName("horizontal");
if(view.getFactorValue() == 0){
opt.select(0);
}else if(view.getFactorValue() == 1){
opt.select(1);
}
return opt ;
}else{
Label label = new Label();
label.setValue("N/A");
return label;
}
}
}
btnSave.addClickListener(new ClickListener() {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public void buttonClick(ClickEvent event) {
Collection<?> items = table.getItemIds() ;
for (Object item : items) {
Property pName = table.getContainerProperty(item, "name");
Property pVal = table.getContainerProperty(item, "value");
}
pVal gets only origin value , not changes value.
You have to add a ValueChangeListener to the OptionGroup and inside the listener actually set the value on your MyType view using something like view.setValue(...).
Your code would then look something like that:
OptionGroup opt = new OptionGroup() ;
opt.addValueChangeListener(new Property.ValueChangeListener() {
#Override
public void valueChange (Property.ValueChangeEvent event){
view.setValue(event.getProperty().getValue());
}
});
i'm creating one application in which i get gift images with id's from web server through JSON. When i click on any gift image, it goes on next page where it shows all information of that image (get image information with its id from web server through JSON).
Problem is: When i click on any gift image on page to see its relevant information, it gets the last gift image id every time, i want when i click on any image, it gets the specific image id which i click. How it is possible??
Screenshot of the page is : http://ugo.offroadstudios.com/gifts.png
Here is sample code:
public class Gifts extends MainScreen {
String giftsid;
BitmapField giftimg;
public Gifts(){
setTitle("Gift Store");
creategifts();
}
public void creategifts()
{
//Link URL
String strURL = "http://ugo.offroadstudios.com/api/frndgift/?loginusername=adil;deviceside=true";
webConnection wb = new webConnection();
String res = wb.getJson(strURL);
try {
JSONObject object = new JSONObject(res);
if(object.getString("status") == "error")
{
Dialog.alert("Invalid "+object.getString("status"));
}
else
{
int totalgifts;
totalgifts = object.getInt("totalgifts");
Bitmap listThumb;
JSONArray imagearr;
JSONArray giftsidarr;
String imgname;
Bitmap bmpResized;
for(int i=0; i < totalgifts; i++){
imagearr = object.getJSONArray("gifts_image");
imgname = imagearr.getString(i);
giftsidarr = object.getJSONArray("gifts_id");
giftsid = giftsidarr.getString(i);
listThumb = getImage.getImageFromUrl("http://ugo.offroadstudios.com/wp-content/plugins/bp-gifts-rebirth/includes/images/"+imgname+";deviceside=true");
bmpResized = GPATools.ResizeTransparentBitmap(listThumb, 80, 80,
Bitmap.FILTER_LANCZOS, Bitmap.SCALE_TO_FIT);
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("giftsid "+giftsid);
UiApplication.getUiApplication().pushScreen(new SendGift(giftsid));
return true;
}
};
add(giftimg);
}
}
}
catch (JSONException e) {
System.out.println("EX is "+e);
e.printStackTrace();
}
}
}
You are always getting the gift id of the last gift in the list because you have created your buttons with this code:
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("giftsid "+giftsid);
UiApplication.getUiApplication().pushScreen(new SendGift(giftsid));
return true;
}
};
Your navigationClick() method used the giftsid variable, which is a persistent member variable of your class. You assign this variable in your for loop, so the final value it keeps is the last value assigned in the loop (giftsidarr.getString(totalgifts)).
Although you declare the navigationClick() method in a loop where the giftsid is many different values, the navigationClick() method uses the value of giftsid when it is run. The last value.
There's many ways to fix it. You can use a separate constant value in your loop:
final String nextGiftsId = giftsid;
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("nextGiftsId= "+nextGiftsId);
UiApplication.getUiApplication().pushScreen(new SendGift(nextGiftsId));
return true;
}
};
Or, as Signare suggested, attach a cookie to each button that identifies its corresponding gift:
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
String giftId = (String)getCookie(); // read gift id from the cookie
Dialog.alert("giftId= "+giftId);
UiApplication.getUiApplication().pushScreen(new SendGift(giftId));
return true;
}
};
giftimg.setCookie(giftsid); // set the cookie after creating the field
Inside your for loop, add the following code -
giftimg[i].setChangeListener(this);
Then -
public void fieldChanged(Field field, int context) {
for(int i=0;i<totalgifts;i++) {
if(field == giftimg[i]) {
// you can trigger your event
}
}
EDIT :-
giftimg[i].setChangeListener(listener);
listener = new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if ( field instanceof BitmapField ) {
for(int i=0;i<totalgifts;i++) {
if ( field == giftimg[i] ) {
// you can trigger your event
}
}
}
}
};
I am implementing a simple app, where in the registration page user can select news categories. Requirements are below
All the categories are the CheckBoxField's. User have to select at least one category.
Select all CheckBox will allow to select all/deselect all categories CheckBox.
If user manually selects all checkbox fields then "Select All" checkbox must be selected.
Approaches: I have created the categories checkbox in a loop.
for(int i=0;i<interests.length;i++){
allFields[i] = new ColorCheckBoxField(interests[i], false, checkBoxStyle | USE_ALL_WIDTH);
allFields[i].setCookie(i+"");
allFields[i].setFont(bodyFont);
allFields[i].setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
ColorCheckBoxField tempChoice = (ColorCheckBoxField)field;
int index =Integer.parseInt(tempChoice.getCookie().toString().trim());
//set the selection
if(tempChoice.getChecked()){
parent.selectInterest(index);
}
boolean flag = true;
int[] intrests = parent.getSelectedInterest();
for (int i = 0; i < intrests.length; i++) {
if(intrests[i]==0){
flag = false;
}
}
if(flag==true){
selectAll.setChecked(flag); // select all is Checkbox object
}else{
selectAll.setChecked(false);
}
}
});
vfm.add(allFields[i]);
}
My selectAll checkbox logic is
selectAll = new ColorCheckBoxField("Select All", false, checkBoxStyle | USE_ALL_WIDTH);
selectAll.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
ColorCheckBoxField temp = (ColorCheckBoxField) field;
//if (context == FieldChangeListener.PROGRAMMATIC ) {
checkAll(temp.getChecked()); // it loops through all checkbox and set them checked
//}
}
});
innerHfm.add(selectAll);
I understand the problem, its due to infinite loop. I have used "FieldChangeListener.PROGRAMMATIC" but that wont help because i want the field listener to work for both pragmatically and manually. I don't have any option left to fix. Any hack will help me?
That's correct that you have to use FieldChangeListener.PROGRAMMATIC. But you have to use it with interest checkboxes instead of using it for selectAll checkbox.
Please add one defensive check to FieldChangeListener for interest checkboxes:
if ( nonProgrammaticChange(context) ) {
ColorCheckBoxField tempChoice = (ColorCheckBoxField)field;
int index = Integer.parseInt(tempChoice.getCookie().toString().trim());
...
}
Where nonProgrammaticChange is:
private boolean nonProgrammaticChange (int context) {
return (context & FieldChangeListener.PROGRAMMATIC) != FieldChangeListener.PROGRAMMATIC;
}
I see bug in your code - you don't clear interest in parent if checkbox is unchecked.
Minor improvements as for me - use Vector where you'll store indexes of selected checkboxes. This will allow to replace this code:
boolean flag = true;
int[] intrests = parent.getSelectedInterest();
for ( int i = 0; i < intrests.length; i++ ) {
if( intrests[i] == 0 ) {
flag = false;
}
}
To this code:
selectedInterestIndexes.size() == interests.length
And probably this will give you less iteration in other places.
As well I would work more on removal of duplicates and code readability.
The scenario of the problem is this
1) We map the struts field values to the dtos. The dtos contain integer fields which again are displayed on the screen.
2) Now I enter an incorrect value which gives conversion error for that integer field.
3) At that point in time I decide to quit the page(i.e press cancel), I get a conversion error. This is because the StrutsConversionErrorInterceptor gets called everytime.
Is there any way that I can skip the strutsConversionErrorInterceptor when I am calling a particular method the way we can skip validation using excludeMethods
Use this code to override Struts's StrutsConversionErrorInterceptor...
public class MyConversionErrorInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";
protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
ValueStack stack = invocation.getStack();
try {
stack.push(value);
return "'" + stack.findValue("top", String.class) + "'";
} finally {
stack.pop();
}
}
#Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext invocationContext = invocation.getInvocationContext();
Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
ValueStack stack = invocationContext.getValueStack();
HashMap<Object, Object> fakie = null;
BaseAction baseAction = (BaseAction) invocation.getAction();
String buttonName = baseAction.getButtonName();
for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
String propertyName = entry.getKey();
Object value = entry.getValue();
if (shouldAddError(propertyName, value)) {
String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
ValidationAware va = (ValidationAware) action;
if(buttonName.equalsIgnoreCas("Next")){
va.addFieldError(propertyName, message);
}
}
if (fakie == null) {
fakie = new HashMap<Object, Object>();
}
if(buttonName.equalsIgnoreCas("Next")){
fakie.put(propertyName, getOverrideExpr(invocation, value));
}
}
}
if (fakie != null) {
// if there were some errors, put the original (fake) values in
// place right before the result
stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);
if (fakie != null) {
invocation.getStack().setExprOverrides(fakie);
}
}
});
}
return invocation.invoke();
}
protected boolean shouldAddError(String propertyName, Object value) {
if (value == null) {
return false;
}
if ("".equals(value)) {
return false;
}
if (value instanceof String[]) {
String[] array = (String[]) value;
if (array.length == 0) {
return false;
}
if (array.length > 1) {
return true;
}
String str = array[0];
if ("".equals(str)) {
return false;
}
}
return true;
}
}
You can specify you button names on which you want validation to fire. In above code I have used "Next" in code you can see
if(buttonName.equalsIgnoreCas("Next"))
Yes, you can skip calling the interceptor.
Just remove the interceptor definition from your action definition in struts.xml file.
i.e., remove <interceptor-ref name="conversionError"/>
Mainly this interceptor adds any error found in the ActionContext's conversionErrors map as a field error (provided that the action implements ValidationAware). In addition, any field that contains a validation error has its original value saved such that any subsequent requests for that value return the original value rather than the value in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to the user).
After you removed this interceptor, if the struts failed to map the field with parameter of the object(i.e., from string to int), it throws result input action error.
This seems to be a better method to handle this scenario - using Conversion Validator. Repopulating Field upon conversion Error section is something very useful:
http://struts.apache.org/2.0.14/docs/conversion-validator.html