# Values - Displaying and edit custom types For more convenient and type-safe displaying and editing of your custom types, Forms provides the `ValueLabel` and `ValueField` types. ## ValueLabel `ValueLabel` is like a `UILabel` but generic on a custom type. It exposes a value property and uses a formatter to convert a value to a `String` for display: ```swift let label = ValueLabel(value: 4711, formatter: { "\($0) kg" }) label.value = 75 ``` You can also provide an instance of a `Formatter`: ```swift let euroFormatter = NumberFormatter() euroFormatter.currencyCode = "EUR" euroFormatter.numberStyle = .currency let label = ValueLabel(value: 47.11, formatter: euroFormatter) ``` If you often use the same formatter for your custom type you can add a convenience initializer: ```swift struct Euro { var amount: Double } extension ValueLabel where Value == Euro { convenience init(value: Value, style: TextStyle = .defaultLabel) { self.init(value: value, keyPath: \.amount, formatter: euroFormatter) } } ``` This means you do not have to provide explicit formatter everywhere: ```swift let label = ValueLabel(value: Euro(4711)) label.value = Euro(0) ``` Form already comes with similar initializers for integer and floating point types: ```swift let label = ValueLabel(value: 47.11) label.value += 100 ``` ## ValueField Similar to `ValueLabel`, `ValueField` is like a `UITextField` but generic on a custom type for editing custom values. However, to be able to edit a value it needs an instance of a `TextEditor`. `TextEditor` is a protocol and Form comes with two concrete implementations named `ValueEditor` and `DecimalEditor`. `ValueEditor` comes with several convenience initializers: ```swift /// Country code editor, e.g. +46 let editor = ValueEditor(isValidCharacter: isDigit, minCharacters: 1, maxCharacters: 3, prefix: "+") let field = ValueField(value: "46", editor: editor) ``` When working with numeric values it is often better to use `NumberEditor` that uses a `NumberFormatter` to derive its behavior and formatting: ```swift let editor = NumberEditor(formatter: euroFormatter) let field = ValueField(value: 47.11, editor: editor) ``` For integer and floating point values you can pass the formatter directly: ```swift let field = ValueField(value: 47.11, formatter: euroFormatter) ``` To avoid repetition, you typically add convenience initializers to `ValueField` for your custom types: ```swift extension ValueField where Value == Euro { convenience init(value: Value, style: FieldStyle = .decimal) { let editor = NumberEditor(formatter: euroFormatter) self.init(value: value, keyPath: \.amount, editor: editor, style: style) } } ``` This allows you to use your custom types directly with `ValueField`s: ```swift let field = ValueField(value: Euro(0)) ```