The example below is truncated for brevity.
Make you sure you handle all the properties of the config
parameter in your implementation.
It can happen that a field has the right logic for you, but you are using a different CSS framework.
In this case, you can customize the view of the field to match your CSS framework without having to rewrite all the code.
For example, it allows you to re-use the Attributes
, and its pipeline builder API, etc.
In this example, we are going to customize the view of a text field.
Create a new file named TextField.fs
.
Create the namespace for hosting your custom field and open the required modules
namespace MyForm.Fields
open Sutil
open Browser
open Fable.Form
open Browser.Types
open Fable.Form.Simple
open Fable.Form.Simple.Sutil.Bulma
open Fable.Form.Simple.Fields.Html
open Fable.Form.Simple.Sutil.Bulma.Fields
open Fable.Form.Simple.Sutil.Bulma.Helpers.Focus
module TextField =
Create a new class which inherits from TextField.Field<'Values>
, and override the RenderField
method.
type Field<'Values>(innerField: TextField.InnerField<'Values>) =
inherit TextField.Field<'Values>(innerField)
override _.RenderField(config: StandardRenderFieldConfig<string, TextField.Attributes>) =
Html.div [
Html.p config.Attributes.Label
Html.input [
Ev.onMount (fun ev ->
let input = (ev.target :?> HTMLInputElement)
if FocusedField.Instance.fieldId = config.Attributes.FieldId then
FocusedField.Instance.fieldId <- ""
input.focus ()
FocusedField.Instance.selection
|> Option.iter (fun (selectionStart, selectionEnd) ->
input.selectionStart <- selectionStart
input.selectionEnd <- selectionEnd
)
)
Ev.onUnmount (fun ev ->
let input = (ev.target :?> HTMLInputElement)
if document.activeElement = input then
FocusedField.SaveFocused(
config.Attributes.FieldId,
input.selectionStart,
input.selectionEnd
)
)
Ev.onChange config.OnChange
// Handle the different properties
prop.disabled config.Disabled
prop.readOnly config.IsReadOnly
prop.value config.Value
]
match config.Error with
| Some(Error.External externalError) -> Html.p externalError
| _ ->
if config.ShowError then
config.Error
|> Option.map Form.View.errorToString
|> Option.defaultValue ""
|> Html.p
]
In another field named Form.fs
, create the field which will be used by the user to create an instance of the custom field.
namespace MyForm
open Fable.Form
open MyForm.Fields
open Fable.Form.Simple.Sutil.Bulma
open Fable.Form.Simple.Fields.Html
open Fable.Form.Simple.Sutil.Bulma.Fields
[<RequireQualifiedAccess>]
module Form =
let textField
(config: Base.FieldConfig<TextField.Attributes, string, 'Values, 'Output>)
: Form<'Values, 'Output>
=
TextField.form (fun field -> TextField.Field field) config