Предоставьте преобразователь для привязки данных, определив пару объектов SerializableFunction

В Vaadin 8 Framework и Vaadin 10 Flow возможность привязки данных позволяет нам предоставлять _ 1_ для связи между ожидаемым типом данных виджета (например, String для TextField) и типом данных свойства резервного компонента (например, Integer number).

В этом примере встроенная реализация Converter _ 6_.

binder
.forField( this.phaseField )
.withConverter( 
    new StringToIntegerConverter( "Must enter an integer number" ) 
)
.bind( Panel::getPhase , Panel::setPhase ) ;

Но как насчет определения Converter для других типов? Как я могу легко определить короткое и сладкое Converter? Например, преобразование строки в UUID конвертер. Я хочу показать канонический 36- шестнадцатеричная строка символов в TextField и в другом направлении преобразовать эту строку обратно в UUID.

// String to UUID
UUID uuid = UUID.fromString( myString ) ;

// UUID to String
String myString = uuid.toString() ;

Я вижу, что Binder.BindingBuilder предлагает пару методов withConverter, которые принимают пару SerializableFunction объектов.

  • Binder.BindingBuilder:: withConverter (SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation)
  • Binder.BindingBuilder:: _ 19_ (SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation, String errorMessage)

➥ Итак, как мне определить пару _ 21_ объекты / классы?

Я заметил, что в этом интерфейсе указан известный подинтерфейс _ 22_ <SOURCE,TARGET>. Это выглядит знакомо, и я подозреваю, что это ключ к легкому определению короткого простого преобразователя. Но я не совсем понимаю синтаксис с лямбдами и все, что здесь происходит.

Я не спрашиваю, как написать класс, реализующий _ 24_. Я спрашиваю, как написать пару _ 25_ аргументы для передачи _ 26_, перечисленных выше как пункты маркера.

Цитата этот JavaDoc:

Interface Binder.BindingBuilder<BEAN,TARGET>

withConverter

default <NEWTARGET> Binder.BindingBuilder<BEAN,NEWTARGET> withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation)

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

Функции сопоставления используются для преобразования между типом представления, который должен соответствовать текущему целевому типу данных привязки, и типом модели, который может быть любым типом данных и становится новым целевым типом привязки. При вызове bind(ValueProvider, Setter) целевой тип привязки должен соответствовать типам получателя / установщика.

Например, TextField может быть привязан к свойству с целочисленным типом, используя соответствующие функции, такие как: withConverter(Integer::valueOf, String::valueOf);

Параметры типа:

NEWTARGET - тип для преобразования в

Параметры:

toModel - функция, которая может преобразовывать из старого целевого типа в новый целевой тип

toPresentation - функция, которая может преобразовывать из нового целевого типа в старый целевой тип

Возврат:

новая привязка соответствующего типа

Броски:

IllegalStateException - если привязка уже была вызвана


person Basil Bourque    schedule 12.07.2018    source источник
comment
Вы спрашиваете, как сделать свой собственный конвертер?   -  person Jay    schedule 12.07.2018
comment
@ Джей Нет. Я не спрашиваю, как написать класс, реализующий _ 1_. Я спрашиваю, как написать пару SerializableFunction аргументов для передачи _ 3_, перечисленные в моем вопросе как маркеры. Изучите JavaDoc, который я связал в предыдущем предложении.   -  person Basil Bourque    schedule 12.07.2018


Ответы (2)


Вы можете сделать это, передав два лямбда-выражения в withConverter, примерно так:

binder.forField(textField)
.withConverter(text -> UUID.fromString(text), uuid -> uuid.toString())
.bind(/* ... */);

Если вам нужно более сложное преобразование, то правую часть лямбда можно заключить в скобки, например

binder.forField(textField).withConverter( text -> {
    if ( text == null ) {
       return something;
    } else {
       return somethingElse;
    } 
}, uuid -> { return uuid.toString(); } )
.bind(/* ... */);
person ollitietavainen    schedule 12.07.2018
comment
Как обычная лямбда квалифицируется как SerializableFunction требуется для .withConverter метода? - person Basil Bourque; 12.07.2018
comment
Это из-за магии Java 8 и аннотации @FunctionalInterface в интерфейсе SerializableFunction. Дополнительную информацию можно найти в документации javadocs: docs.oracle. com / javase / 8 / docs / api / java / lang / - person ollitietavainen; 13.07.2018
comment
Это действительно работает; проверено в моем проекте. Но я все еще в замешательстве. Какова цель команды Vaadin, определяющей интерфейс SerializableFunction, если мы можем просто вставить обычную лямбду? - person Basil Bourque; 15.07.2018
comment
Я понял, что вопрос, заданный в моем предыдущем комментарии, - это сама по себе интересная тема. Поэтому я разместил отдельный вопрос: Какую цель выполняет интерфейс SerializableFunction, определенный в Vaadin 8, если мы можем просто передать обычную лямбду выражение на его месте? - person Basil Bourque; 15.07.2018

Если вам нужен преобразователь несколько раз, я рекомендую создать отдельный класс, реализующий интерфейс com.vaadin.data.Converter. Однако, как вы уже знаете, использование лямбда-выражений тоже возможно (см. Ответ @ollitietavainen). Но это не относится к Vaadin, это функция Java 8+, о которой вы можете прочитать например здесь. По сути, вы можете использовать лямбды везде, где требуется объект, реализующий интерфейс только с одним методом.

person Steffen Harbich    schedule 12.07.2018