Использование редакторов GWT со сложным сценарием использования

Я пытаюсь создать страницу, которая очень похожа на страницу создания Google Form.

enter image description here

Вот как я пытаюсь смоделировать ее, используя структуру GWT MVP (Places and Activities) и Editors .

CreateFormActivity (действие и презентатор)

CreateFormView (интерфейс для просмотра с вложенным интерфейсом презентатора)

CreateFormViewImpl (реализует CreateFormView и редактор

CreateFormViewImpl имеет следующие суб-редакторы:

  • TextBox title
  • TextBox description
  • QuestionListEditor questionList

QuestionListEditor реализует IsEditor >

QuestionEditor реализует редактор В QuestionEditor есть следующие подредакторы:

  • TextBox questionTitle
  • TextBox helpText
  • ValueListBox questionType
  • Необязательный подредактор для каждого типа вопроса ниже.

Редактор для каждого типа вопроса:

TextQuestionEditor

ParagraphTextQuestionEditor

MultipleChoiceQuestionEditor

CheckboxesQuestionEditor

ListQuestionEditor

ScaleQuestionEditor

GridQuestionEditor


Конкретные вопросы:

  1. Как правильно удалять вопросы из формы. (см. дополнительный вопрос )
  2. Как мне создать редактор для каждого типа вопросов? Я попытался прослушать изменение значения questionType, я не уверен, что делать после. (отвечает BobV)
  3. Должен ли каждый редактор для конкретного типа вопроса быть оболочкой с дополнительным редактором поля? Поскольку единовременно можно использовать только один из них. (отвечает BobV)
  4. Как лучше всего управлять созданием / удалением объектов глубоко в иерархии объектов. Пример) Указание ответов на вопрос номер 3, который относится к вопросу с несколькими вариантами ответов. (см. дополнительный вопрос )
  5. Можно ли использовать редактор OptionalFieldEditor для создания оболочки для ListEditor? (ответил BobV)

Реализация на основе ответа

Редактор вопросов

public class QuestionDataEditor extends Composite implements
CompositeEditor>,
LeafValueEditor, HasRequestContext {

interface Binder extends UiBinder {}

private CompositeEditor.EditorChain> chain;

private QuestionBaseDataEditor subEditor = null;
private QuestionDataProxy currentValue = null;
@UiField
SimplePanel container;

@UiField(provided = true)
@Path("dataType")
ValueListBox dataType = new ValueListBox(new Renderer() {

    @Override
    public String render(final QuestionType object) {
        return object == null ? "" : object.toString();
    }

    @Override
    public void render(final QuestionType object, final Appendable appendable) throws IOException {
        if (object != null) {
            appendable.append(object.toString());
        }
    }
});

private RequestContext ctx;

public QuestionDataEditor() {
    initWidget(GWT. create(Binder.class).createAndBindUi(this));
    dataType.setValue(QuestionType.BooleanQuestionType, true);
    dataType.setAcceptableValues(Arrays.asList(QuestionType.values()));

    /*
     * The type drop-down UI element is an implementation detail of the
     * CompositeEditor. When a question type is selected, the editor will
     * call EditorChain.attach() with an instance of a QuestionData subtype
     * and the type-specific sub-Editor.
     */
    dataType.addValueChangeHandler(new ValueChangeHandler() {
        @Override
        public void onValueChange(final ValueChangeEvent event) {
            QuestionDataProxy value;
            switch (event.getValue()) {

            case MultiChoiceQuestionData:
                value = ctx.create(QuestionMultiChoiceDataProxy.class);
                setValue(value);
                break;

            case BooleanQuestionData:
            default:
                final QuestionNumberDataProxy value2 = ctx.create(BooleanQuestionDataProxy.class);
                value2.setPrompt("this value doesn't show up");
                setValue(value2);
                break;

            }

        }
    });
}

/*
 * The only thing that calls createEditorForTraversal() is the PathCollector
 * which is used by RequestFactoryEditorDriver.getPaths().
 * 
 * My recommendation is to always return a trivial instance of your question
 * type editor and know that you may have to amend the value returned by
 * getPaths()
 */
@Override
public Editor createEditorForTraversal() {
    return new QuestionNumberDataEditor();
}

@Override
public void flush() {
    //XXX this doesn't work, no data is returned
    currentValue = chain.getValue(subEditor);
}

/**
 * Returns an empty string because there is only ever one sub-editor used.
 */
@Override
public String getPathElement(final Editor subEditor) {
    return "";
}

@Override
public QuestionDataProxy getValue() {
    return currentValue;
}

@Override
public void onPropertyChange(final String... paths) {
}

@Override
public void setDelegate(final EditorDelegate delegate) {
}

@Override
public void setEditorChain(final EditorChain> chain) {
    this.chain = chain;
}

@Override
public void setRequestContext(final RequestContext ctx) {
    this.ctx = ctx;
}

/*
 * The implementation of CompositeEditor.setValue() just creates the
 * type-specific sub-Editor and calls EditorChain.attach().
 */
@Override
public void setValue(final QuestionDataProxy value) {

    // if (currentValue != null && value == null) {
    chain.detach(subEditor);
    // }

    QuestionType type = null;
    if (value instanceof QuestionMultiChoiceDataProxy) {
        if (((QuestionMultiChoiceDataProxy) value).getCustomList() == null) {
            ((QuestionMultiChoiceDataProxy) value).setCustomList(new ArrayList());
        }
        type = QuestionType.CustomList;
        subEditor = new QuestionMultipleChoiceDataEditor();

    } else {
        type = QuestionType.BooleanQuestionType;
        subEditor = new BooleanQuestionDataEditor();
    }

    subEditor.setRequestContext(ctx);
    currentValue = value;
    container.clear();
    if (value != null) {
        dataType.setValue(type, false);
        container.add(subEditor);
        chain.attach(value, subEditor);
    }
}

}

Редактор базовых данных вопросов

public interface QuestionBaseDataEditor extends HasRequestContext,                         IsWidget {


}

Пример подтипа

public class BooleanQuestionDataEditor extends Composite implements QuestionBaseDataEditor {
interface Binder extends UiBinder {}

@Path("prompt")
@UiField
TextBox prompt = new TextBox();

public QuestionNumberDataEditor() {
    initWidget(GWT. create(Binder.class).createAndBindUi(this));
}

@Override
public void setRequestContext(final RequestContext ctx) {

}
}

Единственная оставшаяся проблема заключается в том, что данные, специфичные для подтипа QuestionData, не используются отображается или смывается. Я думаю, это связано с настройками редактора, которые я использую.

Например, значение для приглашения в BooleanQuestionDataEditor не устанавливается и не сбрасывается, а в полезных данных rpc равно нулю.

Я предполагаю: поскольку QuestionDataEditor реализует LeafValueEditor, драйвер не будет посещать субредактор, даже если он был прикреплен.

Большое спасибо всем, кто может помочь !!!

12
задан Community 23 May 2017 в 10:31
поделиться