Skip to content

Commit d4d48c0

Browse files
Review: extend the information about built-in formatters
1 parent 96cc32a commit d4d48c0

1 file changed

Lines changed: 100 additions & 30 deletions

File tree

  • content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis

content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/_index.md

Lines changed: 100 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -171,52 +171,53 @@ The `formatter` field on `EditableValue` is defined as follows:
171171
type ParseResult<T> = { valid: true; value: T } | { valid: false };
172172

173173
interface SimpleFormatter<T> {
174-
format(value: T | undefined): string;
175-
parse(value: string): ParseResult<T>;
176-
}
174+
format(value: T | undefined): string;
175+
parse(value: string): ParseResult<T>;
177176
}
178177
```
179178

180-
You can supply a fully custom formatter using `setFormatter` (the object must implement `format` and `parse`):
179+
##### Built-in Formatter Types {#built-in-formatter-types}
181180

182-
```ts
183-
myDecimalAttribute.setFormatter({
184-
format(value: Big | undefined): string {
185-
return value !== undefined ? `$${Number(value).toFixed(2)}` : "";
186-
},
187-
parse(text: string): ParseResult<T> {
188-
const num = Number(text.replace(/[$,]/g, ""));
189-
return isNaN(num) ? { valid: false } : { valid: true, value: new Big(num) };
190-
}
191-
});
181+
The Mendix platform provides two typed, configurable built-in formatters that extend `SimpleFormatter<T>`. The actual type of `EditableValue.formatter` is `ValueFormatter<T>` — a union that covers both built-in and plain formatters:
192182

183+
```ts
184+
type ValueFormatter<T> =
185+
| (TypedFormatter<T> & (NumberFormatter | DateTimeFormatter))
186+
| (SimpleFormatter<T> & { readonly type?: never });
193187
```
194188

195-
Call `setFormatter(undefined)` to reset the formatter to the platform default.
196-
197-
**Date/DateTime** attributes have additional capabilities because of `DateTimeFormatter`, which extends `SimpleFormatter<Date>`:
189+
Use the `type` property as a type guard to narrow to a specific built-in formatter before accessing its extra API:
198190

199191
```ts
200-
interface DateTimeFormatter {
201-
type: "datetime";
202-
format(value: Date | undefined): string;
203-
parse(value: string): { valid: true; value: Date } | { valid: false };
204-
withConfig(config: DateTimeFormatterConfig): DateTimeFormatter;
205-
getFormatPlaceholder(): string;
206-
config: DateTimeFormatterConfig;
192+
if (myAttribute.formatter.type === "datetime") {
193+
// DateTimeFormatter — has withConfig, getFormatPlaceholder
194+
} else if (myAttribute.formatter.type === "number") {
195+
// NumberFormatter — has withConfig
196+
} else {
197+
// Plain SimpleFormatter — string, enum, or boolean
207198
}
208199
```
209200

210-
You can check `formatter.type` to detect the attribute's data type at runtime and branch your widget logic accordingly:
201+
##### DateTimeFormatter
202+
203+
**Date/DateTime** attributes receive a `DateTimeFormatter`, which extends `SimpleFormatter<Date>`:
211204

212205
```ts
213-
if (myAttribute.formatter.type === "datetime") {
214-
// Date-specific formatting logic
215-
} else {
216-
// String, number, enum, or boolean formatting logic
206+
interface DateTimeFormatter extends SimpleFormatter<Date> {
207+
readonly type: "datetime";
208+
readonly config: DateTimeFormatterConfig;
209+
withConfig(config: DateTimeFormatterConfig): DateTimeFormatter;
210+
getFormatPlaceholder(): string | undefined;
217211
}
218212
```
219213

214+
The `withConfig` method returns a **new formatter** with a different date pattern while preserving the user's locale. It accepts a `DateTimeFormatterConfig` with the following options:
215+
216+
* `{ type: "date" }` — platform default date format
217+
* `{ type: "time" }` — platform default time format
218+
* `{ type: "datetime" }` — platform default datetime format
219+
* `{ type: "custom", pattern: "..." }` — custom Unicode date pattern (for example `"EEEE"`, `"dd MMMM"`, `"MMMM YYYY"`)
220+
220221
The following example formats a date attribute using a custom month-year pattern:
221222

222223
```ts
@@ -229,13 +230,82 @@ if (myDateAttribute.formatter.type === "datetime") {
229230
}
230231
```
231232

232-
For enumeration and Boolean attributes, `format` converts the raw value into a human-readable caption as configured in Studio Pro:
233+
`getFormatPlaceholder` returns a locale-appropriate placeholder string for the active date pattern, useful for input field `placeholder` attributes:
234+
235+
```ts
236+
const placeholder = myDateAttribute.formatter.type === "datetime"
237+
? myDateAttribute.formatter.getFormatPlaceholder()
238+
: undefined;
239+
```
240+
241+
##### NumberFormatter
242+
243+
**Decimal**, **Integer**, and **Long** attributes receive a `NumberFormatter`, which extends `SimpleFormatter<Big>`:
244+
245+
```ts
246+
interface NumberFormatter extends SimpleFormatter<Big> {
247+
readonly type: "number";
248+
readonly config: NumberFormatterConfig;
249+
withConfig(config: NumberFormatterConfig): NumberFormatter;
250+
}
251+
```
252+
253+
`NumberFormatterConfig` has the following options:
254+
255+
```ts
256+
interface NumberFormatterConfig {
257+
readonly groupDigits: boolean; // e.g. 1,000,000
258+
readonly decimalPrecision?: number;
259+
}
260+
```
261+
262+
The following example disables the thousands separator and fixes the output to four decimal places:
263+
264+
```ts
265+
if (myNumberAttribute.formatter.type === "number") {
266+
const customFormatter = myNumberAttribute.formatter.withConfig({
267+
groupDigits: false,
268+
decimalPrecision: 4
269+
});
270+
const formatted = customFormatter.format(myNumberAttribute.value); // e.g. "1234.5600"
271+
}
272+
```
273+
274+
##### Plain SimpleFormatter
275+
276+
For **string**, **enumeration**, and **Boolean** attributes the platform provides a plain `SimpleFormatter<T>` without a `type` property. These formatters convert raw values to human-readable captions (for example, enum captions configured in Studio Pro) and parse text input back to the typed value. They do **not** have `withConfig` or `getFormatPlaceholder`:
233277

234278
```ts
235279
// myEnumAttribute is an EditableValue<string>
236280
const caption = myEnumAttribute.formatter.format(myEnumAttribute.value); // e.g. "In Progress"
237281
```
238282

283+
##### Custom Formatters via setFormatter
284+
285+
You can supply a fully custom formatter for any attribute type using `setFormatter`. The object must implement `format` and `parse`:
286+
287+
```ts
288+
myDecimalAttribute.setFormatter({
289+
format(value: Big | undefined): string {
290+
return value !== undefined ? `$${Number(value).toFixed(2)}` : "";
291+
},
292+
parse(text: string): { valid: true; value: Big } | { valid: false } {
293+
const num = Number(text.replace(/[$,]/g, ""));
294+
return isNaN(num) ? { valid: false } : { valid: true, value: new Big(num) };
295+
}
296+
});
297+
```
298+
299+
Call `setFormatter(undefined)` to reset the formatter to the platform default.
300+
301+
##### Quick Reference
302+
303+
| Formatter type | `type` value | `withConfig` | `getFormatPlaceholder` | Applies to |
304+
|---|---|---|---|---|
305+
| `DateTimeFormatter` | `"datetime"` |`DateTimeFormatterConfig` || `Date` |
306+
| `NumberFormatter` | `"number"` |`NumberFormatterConfig` || `Big` (Decimal, Integer, Long) |
307+
| `SimpleFormatter` | `undefined` ||| `string`, `boolean`, Enum |
308+
239309
### ModifiableValue {#modifiable-value}
240310

241311
`ModifiableValue` is used to represent values that can be changed by a pluggable widget client component. It is passed only to [association properties](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types-10/#association), and is defined as follows:

0 commit comments

Comments
 (0)