A form from a descriptor
The writable properties of a case class become input fields, their accessors bind them to an instance. The form below is built that way in your browser.
Live
Generated, bound, typed
Change a field: the accessor writes the instance, and the line below reads it back. The age field only accepts numbers because the property type says scala.Int.
Profile form
Three vars, three fields, no field written by hand.
- profile
- Profile(Ada,[email protected],36)
scala
case class Profile(var name: String, var email: String, var age: Int)
val descriptor = ReflectMacros.reflectWithAccessors[Profile]
descriptor.getWriteableProperties.foreach { property =>
val accessor = property.accessor.get
val numeric = property.propertyType.typeName == "scala.Int"
textField(property.name, accessor.get(profile).toString, numeric) { value =>
accessor.set(profile, if numeric then value.toIntOption.getOrElse(0) else value)
}
}
Why it works in the browser
No runtime reflection involved
Scala.js has no java.lang.reflect. The descriptor and its accessors were generated at compile time, so the form is ordinary code that happens to be written by a macro.
Extending the recipe
Read a @Label annotation for the field caption instead of the property name.
Choose the input by propertyType: a checkbox for scala.Boolean, a date field for java.time.LocalDate.
Validate before set, and keep the previous value when a conversion fails.
Use getReadableProperties for a read-only detail view of the same class.