В поисках примера подтверждения GWT ... где ты?

В качестве продолженияПочему в CellTable нет достойных примеров использования CompositeCell?

Я пытаюсь добавить поддержку проверки JSR-303. Я следовал советам по настройке Комы здесь:Как установить gwt-validation с gwt-2.4.0 (Примечание: я использую встроенную проверку GWT 2.4, а не проверку GWT).

Опять же, чтобы получить некоторое повторное использование, я создал пару классов,ValidatableInputCell а такжеAbstractValidatableColumn, Я получил вдохновение для них от:

http://code.google.com/p/google-web-toolkit/source/browse/trunk/samples/validation/src/main/java/com/google/gwt/sample/validation/client/ValidationView.java? г = 10642http://gwt.google.com/samples/Showcase/Showcase.html#!CwCellValidation

Давайте посмотрим на них ...

public class ValidatableInputCell extends AbstractInputCell<String, ValidatableInputCell.ValidationData> {

interface Template extends SafeHtmlTemplates {
    @Template("<input type=\"text\" value=\"{0}\" size=\"{1}\" style=\"{2}\" tabindex=\"-1\"></input>")
    SafeHtml input(String value, String width, SafeStyles color);
}

private static Template template;

/**
 * The error message to be displayed as a pop-up near the field
 */
private String errorMessage;

private static final int DEFAULT_INPUT_SIZE = 15;

/**
 * Specifies the width, in characters, of the &lt;input&gt; element contained within this cell
 */
private int inputSize = DEFAULT_INPUT_SIZE;

public ValidatableInputCell() {
    super("change", "keyup");
    if (template == null) {
        template = GWT.create(Template.class);
    }
}

public void setInputSize(int inputSize) {
    this.inputSize = inputSize;
}

public void setErrorMessage(String errorMessage) {
    this.errorMessage = SafeHtmlUtils.htmlEscape(errorMessage);
}

@Override
public void onBrowserEvent(Context context, Element parent, String value,
        NativeEvent event, ValueUpdater<String> valueUpdater) {
    super.onBrowserEvent(context, parent, value, event, valueUpdater);

    // Ignore events that don't target the input.
    final InputElement input = (InputElement) getInputElement(parent);
    final Element target = event.getEventTarget().cast();
    if (!input.isOrHasChild(target)) {
        return;
    }

    final Object key = context.getKey();
    final String eventType = event.getType();

    if ("change".equals(eventType)) {
        finishEditing(parent, value, key, valueUpdater);
    } else if ("keyup".equals(eventType)) {
        // Mark cell as containing a pending change
        input.getStyle().setColor("blue");

        ValidationData viewData = getViewData(key);
        // Save the new value in the view data.
        if (viewData == null) {
            viewData = new ValidationData();
            setViewData(key, viewData);
        }
        final String newValue = input.getValue();
        viewData.setValue(newValue);
        finishEditing(parent, newValue, key, valueUpdater);

        // Update the value updater, which updates the field updater.
        if (valueUpdater != null) {
            valueUpdater.update(newValue);
        }
    }
}

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

    /*
     * If viewData is null, just paint the contents black. If it is non-null,
     * show the pending value and paint the contents red if they are known to
     * be invalid.
     */
    final String pendingValue = viewData == null ? null : viewData.getValue();
    final boolean invalid = viewData == null ? false : viewData.isInvalid();

    final String color = pendingValue != null ? invalid ? "red" : "blue" : "black";
    final SafeStyles safeColor = SafeStylesUtils.fromTrustedString("color: " + color + ";");
    sb.append(template.input(pendingValue != null ? pendingValue : value, String.valueOf(inputSize), safeColor));
}

@Override
protected void onEnterKeyDown(Context context, Element parent, String value,
        NativeEvent event, ValueUpdater<String> valueUpdater) {
    final Element target = event.getEventTarget().cast();
    if (getInputElement(parent).isOrHasChild(target)) {
        finishEditing(parent, value, context.getKey(), valueUpdater);
    } else {
        super.onEnterKeyDown(context, parent, value, event, valueUpdater);
    }
}

@Override
protected void finishEditing(Element parent, String value, Object key,
        ValueUpdater<String> valueUpdater) {
    final ValidationData viewData = getViewData(key);

    final String pendingValue = viewData == null ? null : viewData.getValue();
    final boolean invalid = viewData == null ? false : viewData.isInvalid();

    if (invalid) {
        final DecoratedPopupPanel errorMessagePopup = new DecoratedPopupPanel(true);
        final VerticalPanel messageContainer = new VerticalPanel();
        messageContainer.setWidth("200px");
        final Label messageTxt = new Label(errorMessage, true);
        messageTxt.setStyleName(UiResources.INSTANCE.style().error());
        messageContainer.add(messageTxt);
        errorMessagePopup.setWidget(messageContainer);

        // Reposition the popup relative to input field
        final int left = parent.getAbsoluteRight() + 25;
        final int top = parent.getAbsoluteTop();

        errorMessagePopup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
            @Override
            public void setPosition(int offsetWidth, int offsetHeight) {
                errorMessagePopup.setPopupPosition(left, top);
            }
        });
    }
    // XXX let user continue or force focus until value is valid? for now the former is implemented
    super.finishEditing(parent, pendingValue, key, valueUpdater);
}

/**
 * The ViewData used by {@link ValidatableInputCell}.
 */
static class ValidationData {
    private boolean invalid;
    private String value;

    public String getValue() {
        return value;
    }

    public boolean isInvalid() {
        return invalid;
    }

    public void setInvalid(boolean invalid) {
        this.invalid = invalid;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

}

а также

public abstract class AbstractValidatableColumn<T> implements HasCell<T, String> {

private ValidatableInputCell cell = new ValidatableInputCell();
private CellTable<T> table;

public AbstractValidatableColumn(int inputSize, CellTable<T> table) {
    cell.setInputSize(inputSize);
    this.table = table;
}

@Override
public Cell<String> getCell() {
    return cell;
}

@Override
public FieldUpdater<T, String> getFieldUpdater() {
    return new FieldUpdater<T, String>() {
        @Override
        public void update(int index, T dto, String value) {
            final Set<ConstraintViolation<T>> violations = validate(dto);
            final ValidationData viewData = cell.getViewData(dto);
            if (!violations.isEmpty()) {  // invalid
                final StringBuffer errorMessage = new StringBuffer();
                for (final ConstraintViolation<T> constraintViolation : violations) {
                    errorMessage.append(constraintViolation.getMessage());
                }
                viewData.setInvalid(true);
                cell.setErrorMessage(errorMessage.toString());
                table.redraw();
            } else {  // valid
                viewData.setInvalid(false);
                cell.setErrorMessage(null);
                doUpdate(index, dto, value);
            }
        }
    };
}

protected abstract void doUpdate(int index, T dto, String value);

protected Set<ConstraintViolation<T>> validate(T dto) {
    final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
    final Set<ConstraintViolation<T>> violations = validator.validate(dto);
    return violations;
}

}

Я используюAbstractValidatableColumn вот так...

protected HasCell<ReserveOfferDTO, String> generatePriceColumn(DisplayMode currentDisplayMode) {
    HasCell<ReserveOfferDTO, String> priceColumn;
    if (isInEditMode(currentDisplayMode)) {
        priceColumn = new AbstractValidatableColumn<ReserveOfferDTO>(5, this) {

            @Override
            public String getValue(ReserveOfferDTO reserveOffer) {
                return obtainPriceValue(reserveOffer);
            }

            @Override
            protected void doUpdate(int index, ReserveOfferDTO reserveOffer, String value) {
                // number format exceptions should be caught and handled by event bus's handle method
                final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
                final BigDecimal price = BigDecimal.valueOf(valueAsDouble);
                reserveOffer.setPrice(price);
            }

        };
    } else {
        priceColumn = new Column<ReserveOfferDTO, String>(new TextCell()) {

            @Override
            public String getValue(ReserveOfferDTO reserveOffer) {
                return obtainPriceValue(reserveOffer);
            }
        };
    }
    return priceColumn;
}

Ой! И вотDTO с аннотациями JSR-303 ...

public class ReserveOfferDTO extends DateComparable implements Serializable {

private static final long serialVersionUID = 1L;

@NotNull @Digits(integer=6, fraction=2)
private BigDecimal price;
@NotNull @Digits(integer=6, fraction=2)
private BigDecimal fixedMW;

private String dispatchStatus;
private String resourceName;
private String dateTime;
private String marketType;
private String productType;

...

}

Отбрасывание точки останова вonBrowserEvent Я ожидаю, что триггер проверки будет иметь место при каждом нажатии клавиши и / или после того, как ячейка потеряет фокус. Это никогда не вызывается. Я могу ввести в камеру все, что захочу. Какие-нибудь подсказки относительно подхода к исправлению?

Мои первые мысли ... а) AbstractValidatableColumn # getFieldUpdater никогда не вызывается, и б) логика в ValidatableInputCell # onBrowserEvent или ValidatableInputCell # нуждается в пересмотре.

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

Ответы на вопрос(2)

Ваш ответ на вопрос