Редакторы GWT — выберите элемент из списка, используя поле со списком значений.

У меня есть ValueAwareEditor, который содержит пару подредакторов:

По сути, OfferDto состоит из тарифа и комиссии. Комиссия может быть одного из 4 подтипов, но всегда только одна. Обычно этот список возможных комиссий внутри TariffDto будет содержать только один элемент, но иногда может содержать два.

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>();
}

Когда комиссии содержат более одного элемента, я хочу отобразить раскрывающийся список с двумя вариантами и добавить, чтобы пользователь мог выбирать между ними, каждый раз сбрасывая комиссию в OfferDto и CommissionEditor.

Проблема в том, что при повторном вызове Commission.setValue() редактор не меняется. Что я должен делать здесь?

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);
        }
    }
}

В настоящее время я отображаю список комиссий в ValueListBox, а затем, когда значение изменяется, я помещаю это значение в OfferDto. Комиссия вроде выставляется правильно, но subEditor не меняется.

Любая помощь очень ценится.

ИЗМЕНИТЬ:

CommissionEditor показывает соответствующий подредактор в зависимости от типа.

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);
            }
        }
    };

}

Возможное решение:

Я изменил OfferEditor так:

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

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

Новый редактор CommissionsEditor представляет собой CompositeEditor. Нужно взять List тариф.комиссии и установить выбранную комиссию в 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;
    }

}

Когда CommissionsEditor отображает раскрывающийся список и вызывается onValueChange(), создается новый редактор, но значение комиссии никогда не устанавливается.

По какой-то причине выбранное значение subEditor не помещается в offer.setCommission(). Я думал, что chain.attach() выполнит это для меня?


person slugmandrew    schedule 02.12.2013    source источник
comment
Я не уверен, но не думаю, что вам нужно вручную вызывать editor.setValue(). Разве не достаточно просто позвонить value.setCommission(selected);. Это должно косвенно вызывать setValue() вашего CommisionEditor. Но помимо этого кажется, что лучше использовать CompositeEditor   -  person Ümit    schedule 03.12.2013
comment
О да, извините. Я запутался, думая, что setValue() обновит реальный редактор. Должен ли OfferEditor реализовывать CompositeEditor или CommissionEditor? Спасибо   -  person slugmandrew    schedule 03.12.2013
comment
Пока это единственный опыт работы с CompositeEditor: stackoverflow.com/questions/13346308/ ... My CommssionEditor реализует AbstractSubTypeEditor несколько раз точно так же, как это делает Supply для Электроснабжение и газоснабжение.   -  person slugmandrew    schedule 03.12.2013
comment
Ну, я не совсем уверен, как выглядит ваш пользовательский интерфейс. Как выглядит ваш ComissionEditor? Это просто TextBox? Но, в конце концов, я думаю, что ComissionEditor должен быть CompositeEditor, потому что во время выполнения в зависимости от размера List<Comission> вы хотите отображать либо DropDownList, либо Textbox, либо Label.   -  person Ümit    schedule 03.12.2013
comment
Редактор Комиссии был добавлен к вопросу. Я не буду публиковать подредакторы, но они, по сути, представляют собой текстовое поле с двумя кнопками, используемыми для увеличения значения.   -  person slugmandrew    schedule 03.12.2013
comment
Вы пытались поставить точки останова в setValue() и посмотреть, что произойдет?   -  person Ümit    schedule 03.12.2013
comment
Не уверен, какое setValue вы имеете в виду... Я попытался превратить OfferEditor в CompositeEditor и получил необходимую мне функциональность, но проблема заключалась в том, что TariffRenderer не работал (я считаю, что CompositeEditor может редактировать только один подтип). Я добавил свою попытку решения выше. Спасибо еще раз   -  person slugmandrew    schedule 04.12.2013