Skip to main content

Custom widget for field

Continuing to fiddle with our registration form. We want to mask the password field. We have two options, either parametrize the string widget or define another widget for the password

We will learn how to parameterize in the meta chapter, now let's define a special widget for passwords

Create before all declarations (and type) our Widget

module PasswordWidget = {
type t = string

@react.component
let make = (~value: t, ~onChange: t => unit) => {
let onChange = React.useCallback1(
e => ReactEvent.Form.target(e)["value"] |> onChange,
[onChange],
)
<input type_="password" placeholder="Empty password" value onChange />
}
React.setDisplayName(make, "PasswordWidget")
}

And then attach it to our password fields

  module RegisterFormSchema = %schema(
type formData = {
phone: string,
age: int,
name: string,
@sc_widget(module(PasswordWidget: Widgets.Widget with type t = string))
password: string,
@sc_widget(module(PasswordWidget: Widgets.Widget with type t = string))
confirmPassword: string
}
)

That's all

You can run to open a browser and check the results.

Full listing​

  module PasswordWidget = {
type t = string

@react.component
let make = (~value: t, ~onChange: t => unit) => {
let onChange = React.useCallback1(
e => ReactEvent.Form.target(e)["value"] |> onChange,
[onChange],
)
<input type_="password" placeholder="Empty password" value onChange />
}
React.setDisplayName(make, "Passwordidget")
}

module RegisterFormSchema = %schema(
type formData = {
phone: string,
age: int,
name: string,
@sc_widget(module(PasswordWidget: Widgets.Widget with type t = string))
password: string,
@sc_widget(module(PasswordWidget: Widgets.Widget with type t = string))
confirmPassword: string
}
)

open RegisterFormSchema

let formData = {
phone: "",
age: 0,
name: "",
password: "",
confirmPassword: "",
}

module AllStringTypeWidget = {
type t = string

@react.component
let make = (~value: t, ~onChange: t => unit) => {
let onChange = React.useCallback1(
e => ReactEvent.Form.target(e)["value"] |> onChange,
[onChange],
)
<input type_="text" placeholder="Empty String Widget" value onChange />
}
React.setDisplayName(make, "AgeWidget")
}

let customPrimitives: PrimitiveWidget.customWidgets = {
stringWidget: Some(module(AllStringTypeWidget)),
intWidget: None,
floatWidget: None,
boolWidget: None,
}

@react.component
let make = () => {
let (state, setState) = React.useState(_ => formData)

let onChange = v => {
Js.Console.log(v)
setState(_ => v)
}
<FormRender uiSchema formData=state schema onChange customPrimitives />
}
}