3

I am using gwt2.3 celltable.

In my celltable there will be multiple column out of that few columns are dependent.

ex. Name and address columns are dependent Name and address columns contains my custom selection cells.

In Name column : 1 cell contains jon,tom,steve

when Name cell contains jon then I want to set US & UK in address cell

if user changes Name cell to tom then I want to set india & china in address cell

if user changes Name cell to steve then I want to set japana & bhutan in address cell

I want to change dependent data from address cell when name cells selection changes.

How I can achieve this thing? Any sample code or pointers to do this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
StackOverFlow
  • 4,486
  • 12
  • 52
  • 87
  • 1
    Your explanation is quite hard to understand... You want to change the Cell, at the point you change the selection? – Sam Jan 29 '13 at 15:09
  • @Sam i believe so. Vaibhav, we have tried a similar solution and code turns unbelievably shitty !!!! – appbootup Jan 30 '13 at 05:01
  • @Vaibhav I tried same but it did not work!!!!!. because it is difficult to differentiate individual Dom Element of Row. I changed columns behavior as you want. i.e. First row first column change affect on second column or may be any column as code. then select other row, first row become as it is. and all changes are elapsed of first row. – bNd Jan 31 '13 at 11:06
  • Your question is not clear: You have two columns, each containing a dopdown list and you want that when you select an option from the first dropdown, it changes the available values from the second dropdown, is that right? And you made a custom cell for the dropdown right? – qwertzguy Jan 31 '13 at 13:50
  • @qwertzguy #1 Yes, I made customSelectionCell for dropdown – StackOverFlow Jan 31 '13 at 13:54
  • @VaibhaV What class does your customSelectionCell extends? What is the type your CellTable handles (the parametized type) ? And how do you fetch the values to display in the second dropdown in function of the value of the first dropdown? (IE: Does values needs to be fetched or not?) – qwertzguy Jan 31 '13 at 14:38
  • @qwertzguy #1 My CustomSelectionCell extends AbstractEditableCell #2 CellTable #3 All dependent data fetched on client side – StackOverFlow Feb 01 '13 at 06:44
  • @qwertzguy On selection change of Name cell need to set dependent selection-data in same row-record of Address cell – StackOverFlow Feb 01 '13 at 06:46

4 Answers4

2

This solution is for GWT 2.5, but it should probably work in 2.3. I think the best is that you modify your RecordInfo element when you change the selection on the first column. You can do it similar to this in your CustomSelectionCell:

@Override
public void onBrowserEvent(Context context, Element parent, C value, NativeEvent event, ValueUpdater<C> valueUpdater) {
    super.onBrowserEvent(context, parent, value, event, valueUpdater);
    if (BrowserEvents.CHANGE.equals(event.getType())) {
        Xxxxx newValue = getSelectedValueXxxxx();
        valueUpdater.update(newValue);
    }
}

Then where you use your cell add a fieldUpdater like this, that will update the RecordInfo with the new value and ask to redraw the row:

column.setFieldUpdater(new FieldUpdater<.....>() {
    ....
    recordInfo.setXxxxx(newValue);
    cellTable.redrawRow(index);
    ....
});

This will call the render of the other CustomSelectionCell, in there you will be able to check if the value of the RecordInfo has changed and update the seletion values as needed. Example:

@Override
public void render(Context context, C value, SafeHtmlBuilder sb) {
    if (!value.getXxxxx().equals(this.lastValue)) {
        this.items = loadItemsForValueXxxx(value.getXxxxx());
    }
    .... // Your usual render.
}

Be careful when you changed the items to set a default selected item too.

qwertzguy
  • 15,699
  • 9
  • 63
  • 66
  • Can you provide sample demo + code, It will be good to play/experiment – StackOverFlow Feb 04 '13 at 18:26
  • No, I'm sorry I don't have time to recreate a project and re-code your CustomSelectionCell etc. But it shouldn't be too difficult for you to integrate those snippets of code. – qwertzguy Feb 05 '13 at 10:41
  • @qwertzguy : can you please explain a little bit more i'm trying to do the same same thing. i know how to update the list of selection cell but don't get how to fire the render method of selection cell on field updater of another column. – Ankit Singla Jun 25 '14 at 07:58
  • @AnkitSingla You need to use setFieldUpdater (2nd code snippet) on the "another column". The call to cellTable.redrawRow(index) will trigger the render of all the columns. – qwertzguy Jun 25 '14 at 13:51
  • @qwertzguy : i have map , List>>, first selection column contains keyset of map, and i want to update the second selection column list based on column 1 selecion. the problem is that its updating all row's i just want to update current row. – Ankit Singla Jun 27 '14 at 04:58
1

This is my implementation of DynamicSelectionCell.

DynamicSelectionCell allows you to render different options for different rows in the same GWT table.

Use a single DynamicSelectionCell object and use the addOption method to add options for each row. Options are stored in a Map with the Key being the row number.

For each row $i in the table the options stored in the Map for key $i are rendered.

Works on DataGrid, CellTable.

CODE

public class DynamicSelectionCell extends AbstractInputCell<String, String> {

    public TreeMap<Integer, List<String>> optionsMap = new TreeMap<Integer, List<String>>();
    interface Template extends SafeHtmlTemplates {
        @Template("<option value=\"{0}\">{0}</option>")
        SafeHtml deselected(String option);

        @Template("<option value=\"{0}\" selected=\"selected\">{0}</option>")
        SafeHtml selected(String option);
    }

    private static Template template;

    private TreeMap<Integer, HashMap<String, Integer>> indexForOption = new TreeMap<Integer, HashMap<String, Integer>>();

    /**
     * Construct a new {@link SelectionCell} with the specified options.
     *
     * @param options the options in the cell
     */
    public DynamicSelectionCell() {
        super("change");
        if (template == null) {
            template = GWT.create(Template.class);
        }
    }

    public void addOption(List<String> newOps, int key){
        optionsMap.put(key, newOps);
        HashMap<String, Integer> localIndexForOption = new HashMap<String, Integer>();
        indexForOption.put(ind, localIndexForOption);
        refreshIndexes();
    }

    public void removeOption(int index){        
        optionsMap.remove(index);
        refreshIndexes();
    }

    private void refreshIndexes(){
        int ind=0;
        for (List<String> options : optionsMap.values()){
            HashMap<String, Integer> localIndexForOption = new HashMap<String, Integer>();
            indexForOption.put(ind, localIndexForOption);
            int index = 0;
            for (String option : options) {
                localIndexForOption.put(option, index++);
            }
            ind++;
        }
    }

    @Override
    public void onBrowserEvent(Context context, Element parent, String value,
            NativeEvent event, ValueUpdater<String> valueUpdater) {
        super.onBrowserEvent(context, parent, value, event, valueUpdater);
        String type = event.getType();
        if ("change".equals(type)) {
            Object key = context.getKey();
            SelectElement select = parent.getFirstChild().cast();
            String newValue = optionsMap.get(context.getIndex()).get(select.getSelectedIndex());
            setViewData(key, newValue);
            finishEditing(parent, newValue, key, valueUpdater);
            if (valueUpdater != null) {
                valueUpdater.update(newValue);
            }
        }
    }

    @Override
    public void render(Context context, String value, SafeHtmlBuilder sb) {
        // Get the view data.
        Object key = context.getKey();
        String viewData = getViewData(key);
        if (viewData != null && viewData.equals(value)) {
            clearViewData(key);
            viewData = null;
        }

        int selectedIndex = getSelectedIndex(viewData == null ? value : viewData, context.getIndex());
        sb.appendHtmlConstant("<select tabindex=\"-1\">");
        int index = 0;
        try{
        for (String option : optionsMap.get(context.getIndex())) {
            if (index++ == selectedIndex) {
                sb.append(template.selected(option));
            } else {
                sb.append(template.deselected(option));
            }
        }
        }catch(Exception e){
            System.out.println("error");
        }
        sb.appendHtmlConstant("</select>");
    }

    private int getSelectedIndex(String value, int ind) {
        Integer index = indexForOption.get(ind).get(value);
        if (index == null) {
            return -1;
        }
        return index.intValue();
    }
} 
Varun Tulsian
  • 113
  • 1
  • 7
1

Varun Tulsian's answer is very good, but the code is incomplete.

The DynamicSelectionCell stores each rows' options in a map. When the cell updates or renders itself, it matches the row index from your Context to its matching row list in your map.

For posterity, see the simplified and updated version below:

public class DynamicSelectionCell extends AbstractInputCell<String, String> {

interface Template extends SafeHtmlTemplates {
    @Template("<option value=\"{0}\">{0}</option>")
    SafeHtml deselected(String option);

    @Template("<option value=\"{0}\" selected=\"selected\">{0}</option>")
    SafeHtml selected(String option);
}

private static Template template;

/**
 *  key: rowIndex
 *  value: List of options to show for this row
 */
public TreeMap<Integer, List<String>> optionsMap = new TreeMap<Integer, List<String>>();

/**
 * Construct a new {@link SelectionCell} with the specified options.
 *
 */
public DynamicSelectionCell() {
    super("change");
    if (template == null) {
        template = GWT.create(Template.class);
    }
}

public void addOptions(List<String> newOps, int rowIndex) {
    optionsMap.put(rowIndex, newOps);
}

public void removeOptions(int rowIndex) {
    optionsMap.remove(rowIndex);
}

@Override
public void onBrowserEvent(Context context, Element parent, String value,
                           NativeEvent event, ValueUpdater<String> valueUpdater) {
    super.onBrowserEvent(context, parent, value, event, valueUpdater);
    String type = event.getType();
    if ("change".equals(type)) {
        Object key = context.getKey();
        SelectElement select = parent.getFirstChild().cast();
        String newValue = optionsMap.get(context.getIndex()).get(select.getSelectedIndex());
        setViewData(key, newValue);
        finishEditing(parent, newValue, key, valueUpdater);
        if (valueUpdater != null) {
            valueUpdater.update(newValue);
        }
    }
}

@Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
    // Get the view data.
    Object key = context.getKey();
    String viewData = getViewData(key);
    if (viewData != null && viewData.equals(value)) {
        clearViewData(key);
        viewData = null;
    }

    int selectedIndex = getSelectedIndex(viewData == null ? value : viewData, context.getIndex());
    sb.appendHtmlConstant("<select tabindex=\"-1\">");
    int index = 0;
    try {
        for (String option : optionsMap.get(context.getIndex())) {
            if (index++ == selectedIndex) {
                sb.append(template.selected(option));
            } else {
                sb.append(template.deselected(option));
            }
        }
    } catch (Exception e) {
        System.out.println("error");
    }
    sb.appendHtmlConstant("</select>");
}

private int getSelectedIndex(String value, int rowIndex) {
    if (optionsMap.get(rowIndex) == null) {
        return -1;
    }
    return optionsMap.get(rowIndex).indexOf(value);
}
}
Ajean
  • 5,528
  • 14
  • 46
  • 69
Lolleroni
  • 11
  • 1
  • 1
0

Or you could do something like creating a custom cell, which has methods you can call in the getValue of that particular column

say

final DynamicSelectionCell selection = new DynamicSelectionCell("...");
    Column<GraphFilterCondition, String> operandColumn=new Column<GraphFilterCondition, String>(selection) {
        @Override
        public String getValue(FilterCondition object) {
            if(object.getWhereCol()!=null){
                 ((DynamicSelectionCell)this.getCell()).addOptions(new String[]{">","<",">="});
            }
            if(object.getWhereCondition()!=null){
                return object.getWhereCondition().getGuiName();
            }
            return "";
        }
    };

This should work I guess.

Also check this other question

Community
  • 1
  • 1
Photon
  • 180
  • 2
  • 8