com.github.mvysny.karibudsl.v8.BinderUtils.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of karibu-dsl-v8 Show documentation
Show all versions of karibu-dsl-v8 Show documentation
Karibu-DSL, Kotlin extensions/DSL for Vaadin
The newest version!
package com.github.mvysny.karibudsl.v8
import com.vaadin.data.*
import com.vaadin.data.converter.*
import com.vaadin.server.Page
import com.vaadin.server.WebBrowser
import com.vaadin.ui.AbstractTextField
import java.math.BigDecimal
import java.math.BigInteger
import java.time.*
import java.util.*
import kotlin.reflect.KMutableProperty1
/**
* Trims the user input string before storing it into the underlying property data source. Vital for mobile-oriented apps:
* Android keyboard often adds whitespace to the end of the text when auto-completion occurs. Imagine storing a username ending with a space upon registration:
* such person can no longer log in from his PC unless he explicitely types in the space.
* @param blanksToNulls if true then a blank String value is passed as `null` to the model. Defaults to false.
*/
public fun Binder.BindingBuilder.trimmingConverter(blanksToNulls: Boolean = false): Binder.BindingBuilder =
withConverter(object : Converter {
override fun convertToModel(value: String?, context: ValueContext?): Result {
var trimmedValue: String? = value?.trim()
if (blanksToNulls && trimmedValue.isNullOrBlank()) {
trimmedValue = null
}
return Result.ok(trimmedValue)
}
override fun convertToPresentation(value: String?, context: ValueContext?): String? {
// must not return null here otherwise TextField will fail with NPE:
// // workaround for https://github.com/vaadin/framework/issues/8664
return value ?: ""
}
})
public fun Binder.BindingBuilder.toInt(): Binder.BindingBuilder =
withConverter(StringToIntegerConverter(karibuDslI18n("cantConvertToInteger")))
public fun Binder.BindingBuilder.toDouble(): Binder.BindingBuilder =
withConverter(StringToDoubleConverter(karibuDslI18n("cantConvertToDecimal")))
public fun Binder.BindingBuilder.toLong(): Binder.BindingBuilder =
withConverter(StringToLongConverter(karibuDslI18n("cantConvertToInteger")))
public fun Binder.BindingBuilder.toBigDecimal(): Binder.BindingBuilder =
withConverter(StringToBigDecimalConverter(karibuDslI18n("cantConvertToDecimal")))
public fun Binder.BindingBuilder.toBigInteger(): Binder.BindingBuilder =
withConverter(StringToBigIntegerConverter(karibuDslI18n("cantConvertToInteger")))
public val WebBrowser.timeZone: ZoneId
get() = if (!timeZoneId.isNullOrBlank()) {
// take into account zone ID. This is important for historical dates, to properly compute date with daylight savings.
ZoneId.of(timeZoneId)
} else {
// fallback to time zone offset
ZoneOffset.ofTotalSeconds(timezoneOffset / 1000)
}
public val browserTimeZone: ZoneId get() = Page.getCurrent().webBrowser.timeZone
/**
* Returns the current date and time at browser's current time zone.
*/
public val WebBrowser.currentDateTime: LocalDateTime
get() =
LocalDateTime.now(ZoneOffset.ofTotalSeconds(timezoneOffset / 1000))
public fun Binder.BindingBuilder.toDate(): Binder.BindingBuilder =
withConverter(LocalDateToDateConverter(browserTimeZone))
@JvmName("localDateTimeToDate")
public fun Binder.BindingBuilder.toDate(): Binder.BindingBuilder =
withConverter(LocalDateTimeToDateConverter(browserTimeZone))
public fun Binder.BindingBuilder.toInstant(): Binder.BindingBuilder =
withConverter(LocalDateToInstantConverter(browserTimeZone))
@JvmName("localDateTimeToInstant")
public fun Binder.BindingBuilder.toInstant(): Binder.BindingBuilder =
withConverter(LocalDateTimeToInstantConverter(browserTimeZone))
/**
* Allows you to create [BeanValidationBinder] like this: `beanValidationBinder()` instead of `BeanValidationBinder(Person::class.java)`
*/
public inline fun beanValidationBinder(): BeanValidationBinder = BeanValidationBinder(T::class.java)
/**
* Allows you to bind the component directly in the component's definition. E.g.
* ```
* textField("Name:") {
* bind(binder).trimmingConverter().bind(Person::name)
* }
* ```
*/
public fun HasValue.bind(binder: Binder): Binder.BindingBuilder {
var builder = binder.forField(this)
@Suppress("UNCHECKED_CAST")
if (this is AbstractTextField) builder = builder.withNullRepresentation("" as FIELDVALUE)
return builder
}
/**
* A type-safe binding which binds only to a property of given type, found on given bean.
* @param prop the bean property
*/
public fun Binder.BindingBuilder.bind(prop: KMutableProperty1): Binder.Binding {
// oh crap, don't use binding by getter and setter - validations won't work!
// we need to use bind(String) even though that will use undebuggable crappy Java 8 lambdas :-(
// bind({ bean -> prop.get(bean) }, { bean, value -> prop.set(bean, value) })
return bind(prop.name)
}
/**
* A converter that converts between [LocalDate] and [Instant].
* @property zoneId the time zone id to use.
*/
public class LocalDateToInstantConverter(public val zoneId: ZoneId = browserTimeZone) : Converter {
override fun convertToModel(localDate: LocalDate?, context: ValueContext): Result =
Result.ok(localDate?.atStartOfDay(zoneId)?.toInstant())
override fun convertToPresentation(date: Instant?, context: ValueContext): LocalDate? =
date?.atZone(zoneId)?.toLocalDate()
}
/**
* A converter that converts between [LocalDateTime] and [Instant].
* @property zoneId the time zone to use
*/
public class LocalDateTimeToInstantConverter(public val zoneId: ZoneId = browserTimeZone) : Converter {
override fun convertToModel(localDate: LocalDateTime?, context: ValueContext): Result =
Result.ok(localDate?.atZone(zoneId)?.toInstant())
override fun convertToPresentation(date: Instant?, context: ValueContext): LocalDateTime? =
date?.atZone(zoneId)?.toLocalDateTime()
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy