GWT Editors - select an item from a list using a valuelistbox

1.4k views Asked by At

I have a ValueAwareEditor that contains a couple of sub editors:

Essentially, an OfferDto is composed of a TariffDto and a Commission. The Commission can be one of 4 sub-types, but there is only ever one. Usually this list of possible commissions inside the TariffDto will only contain one element, but it can sometimes contain two.

public class OfferDto
{
    private TariffDto tariff;

    // selected from the list in the tariff
    private Commission commission;
}

public class TariffDto extends EntityDto
{
    // omitted for brevity...

    protected List<Commission> commissions = new ArrayList<Commission>();
}

When commissions contains more than one item, I want to display a dropdown with the two optiions, and add allow the user to choose between them, each time resetting the commission in the OfferDto and the CommissionEditor.

The problem is that, when call commission.setValue() for the second time, the editor does not change. What should I be doing here?

public class OfferEditor extends Composite implements ValueAwareEditor<OfferDto>
{
    @UiField
    TariffRenderer tariff;

    @Ignore
    @UiField
    HTMLPanel panel;

    @UiField
    CommissionEditor commission;

    @Override
    public void setValue(final OfferDto value)
    {
        panel.clear();
        List<Commission> commissions = value.getTariff().getCommissions();

        if(commissions.size() == 1)
        {
            value.setCommission(commissions.get(0));
        }
        else
        {
            // multiple commissions
            ValueListBox<Commission> dropdown = new ValueListBox<Commission>(new Renderer<Commission>()
            {
                @Override
                public String render(Commission object)
                {
                    return object == null ? "" : object.getName();
                }
                @Override
                public void render(Commission object, Appendable appendable) throws IOException
                {
                    appendable.append(render(object));
                }
            });

            dropdown.setValue(value.getCommission());
            dropdown.setAcceptableValues(commissions);
            dropdown.addValueChangeHandler(new ValueChangeHandler<Commission>()
            {
                @Override
                public void onValueChange(ValueChangeEvent<Commission> event)
                {
                    Commission selected = event.getValue();

                    // this works, but the CommissionEditor that was first rendered remains
                    value.setCommission(selected);

                }

            });

            panel.add(dropdown);
        }
    }
}

Currently, I am rendering the list of commissions in a ValueListBox, then when the value changes I am pushing that value to the OfferDto. The Commission seems to get set right, but the subEditor does not change.

Any help greatly appreciated.

EDIT:

CommissionEditor shows the relevant sub-editor depending on the type.

public class CommissionEditor extends Composite implements Editor<Commission>
{
    private static CommissionEditorUiBinder uiBinder = GWT.create(CommissionEditorUiBinder.class);

    interface CommissionEditorUiBinder extends UiBinder<Widget, CommissionEditor>
    {
    }

    @UiField
    Panel subEditorPanel;

    public CommissionEditor()
    {
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Ignore
    final UnitRateCommissionEditor unitRateCommissionEditor = new UnitRateCommissionEditor();

    @Path("")
    final AbstractSubTypeEditor<Commission, UnitRateCommission, UnitRateCommissionEditor> unitRateCommissionEditorWrapper = new AbstractSubTypeEditor<Commission, UnitRateCommission, UnitRateCommissionEditor>(
            unitRateCommissionEditor)
    {
        @Override
        public void setValue(final Commission value)
        {
            if(value instanceof UnitRateCommission)
            {
                setValue(value, value instanceof UnitRateCommission);
                System.out.println("UnitRateCommission setValue");

                subEditorPanel.clear();
                subEditorPanel.add(unitRateCommissionEditor);
            }
        }
    };

    @Ignore
    final StandingChargeCommissionEditor standingChargeCommissionEditor = new StandingChargeCommissionEditor();

    @Path("")
    final AbstractSubTypeEditor<Commission, StandingChargeCommission, StandingChargeCommissionEditor> standingChargeCommissionEditorWrapper = new AbstractSubTypeEditor<Commission, StandingChargeCommission, StandingChargeCommissionEditor>(
            standingChargeCommissionEditor)
    {
        @Override
        public void setValue(final Commission value)
        {
            if(value instanceof StandingChargeCommission)
            {
                setValue(value, value instanceof StandingChargeCommission);
                System.out.println("StandingChargeCommission setValue");

                subEditorPanel.clear();
                subEditorPanel.add(standingChargeCommissionEditor);
            }
        }
    };

    @Ignore
    final PerMwhCommissionEditor perMwhCommissionEditor = new PerMwhCommissionEditor();

    @Path("")
    final AbstractSubTypeEditor<Commission, PerMwhCommission, PerMwhCommissionEditor> perMwhCommissionEditorWrapper = new AbstractSubTypeEditor<Commission, PerMwhCommission, PerMwhCommissionEditor>(
            perMwhCommissionEditor)
    {
        @Override
        public void setValue(final Commission value)
        {
            if(value instanceof PerMwhCommission)
            {
                setValue(value, value instanceof PerMwhCommission);
                System.out.println("PerMwhCommission setValue");

                subEditorPanel.clear();
                subEditorPanel.add(perMwhCommissionEditor);
            }
        }
    };

}

Possible Solution:

I changed OfferEditor as so:

public class OfferEditor extends Composite implements Editor<OfferDto>
{       
    @UiField
    TariffRenderer tariff;

    @Path("tariff.commissions")
    @UiField
    CommissionsEditor commission;
}

New editor CommissionsEditor is a CompositeEditor. It needs to take List tariff.commissions and set the chosen Commission into offer.commission:

public class CommissionsEditor extends Composite implements CompositeEditor<List<Commission>, Commission, CommissionEditor>
{
    private static CommissionsEditorUiBinder uiBinder = GWT.create(CommissionsEditorUiBinder.class);

    interface CommissionsEditorUiBinder extends UiBinder<Widget, CommissionsEditor>
    {
    }

    private EditorChain<Commission, CommissionEditor> chain;

    @UiField
    FlowPanel dropdownPanel, subEditorPanel;

    @Ignore
    CommissionEditor subEditor;

    public CommissionsEditor()
    {
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Override
    public void setValue(List<Commission> valueList)
    {
        // clear both panels
        dropdownPanel.clear();
        subEditorPanel.clear();

        if(valueList.size() == 1)
        {
            // set the commission to the first in the list
            Commission selected = valueList.get(0);
            subEditor = new CommissionEditor();
            subEditorPanel.add(subEditor);
            chain.attach(selected, subEditor);
        }
        else if(valueList.size() > 1)
        {
            ValueListBox<Commission> dropdown = new ValueListBox<Commission>(new Renderer<Commission>()
            {
                @Override
                public String render(Commission object)
                {
                    return object == null ? "" : object.getName();
                }
                @Override
                public void render(Commission object, Appendable appendable) throws IOException
                {
                    appendable.append(render(object));
                }
            });

            dropdownPanel.add(dropdown);
            dropdown.setValue(valueList.get(0));
            dropdown.setAcceptableValues(valueList);

            dropdown.addValueChangeHandler(new ValueChangeHandler<Commission>()
            {
                @Override
                public void onValueChange(ValueChangeEvent<Commission> event)
                {
                    Commission selected = event.getValue();

                    subEditorPanel.clear();

                    CommissionEditor subEditor = new CommissionEditor();
                    subEditorPanel.add(subEditor);
                    chain.attach(selected, subEditor);

                }

            });

        }

    }

    @Override
    public void flush()
    {

    }

    @Override
    public void onPropertyChange(String... paths)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void setDelegate(EditorDelegate<List<Commission>> delegate)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public CommissionEditor createEditorForTraversal()
    {
        return new CommissionEditor();
    }

    @Override
    public String getPathElement(CommissionEditor subEditor)
    {
        return null;
    }

    @Override
    public void setEditorChain(EditorChain<Commission, CommissionEditor> chain)
    {
        this.chain = chain;
    }

}

When the CommissionsEditor renders the dropdown and onValueChange() is called, the new editor gets created, but the value for the commission never seems to get set.

For some reason the selected subEditor's value is not pushed into offer.setCommission(). I thought chain.attach() would perform this for me?

0

There are 0 answers