thoth-org / Thoth.Elmish.FormBuilder

https://thoth-org.github.io/Thoth.Elmish.FormBuilder/
MIT License
10 stars 5 forks source link

Improve Thoth.Elmish.FormBuilder docs #8

Open MangelMaxime opened 4 years ago

MangelMaxime commented 4 years ago

Issue by nojaf Thursday Jan 10, 2019 at 13:23 GMT Originally opened as https://github.com/MangelMaxime/Thoth/issues/116


I've created my own FormComponent for Thoth.Elmish.FormBuilder.

namespace nojaf.FormInputs

open Thoth.Elmish.FormBuilder
open Thoth.Elmish.FormBuilder.Types
open Thoth.Json
open Fable.Helpers.React
open Fable.Helpers.React.Props

[<RequireQualifiedAccess>]
module ColorPicker =

    type Msg =
        | ChangeRed of int
        | ChangeGreen of int
        | ChangeBlue of int
        interface IFieldMsg

    type Validator = State -> ValidationState

    type State =
        { Label : string
          Red: int
          Green: int
          Blue: int
          Name : string }

        member this.Value() = sprintf "rgb(%i,%i,%i)" this.Red this.Green this.Blue

    let private init (state: FieldState) =
        state, FormCmd.none

    let private toJson (state : FieldState) =   
        let state : State = state :?> State
        state.Name, Encode.string (state.Value())

    let private update (msg : FieldMsg) (state : FieldState) =
        // Cast the received message into it's real type
        let msg = msg :?> Msg
        // Cast the received state into it's real type
        let state = state :?> State

        match msg with
        | ChangeBlue blue ->
            { state with Blue = blue }
            |> box, FormCmd.none
        | ChangeRed red ->
            { state with Red = red }
            |> box, FormCmd.none
        | ChangeGreen green ->
            { state with Green = green }
            |> box, FormCmd.none

    let private view (state: FieldState) (dispatch: IFieldMsg -> unit) =
        let state : State = state :?> State
        let changeValue msg (ev: Fable.Import.React.FormEvent) =
            let value = ev.Value |> (int)
            dispatch (msg value)

        div [] [
            label [ Class "label"; HtmlFor state.Name ] [ str state.Label ]
            div [] [
                strong [] [str "R"]
                input [Type "range"; Min 0; Max 255; Value state.Red; OnChange (changeValue Msg.ChangeRed)]
            ]
            div [] [
                strong [] [str "G"]
                input [Type "range"; Min 0; Max 255; Value state.Green; OnChange (changeValue Msg.ChangeGreen)]
            ]
            div [] [
                strong [] [str "B"]
                input [Type "range"; Min 0; Max 255; Value state.Blue; OnChange (changeValue Msg.ChangeBlue)]
            ]
            div [Style [CSSProp.BackgroundColor (state.Value()); CSSProp.Width 100; CSSProp.Height 100; CSSProp.MarginTop 30; CSSProp.MarginBottom 30]] []
        ]

    let config : FieldConfig =
        { View = view
          Update = update
          Init = init
          Validate = id
          IsValid =  fun _ -> true
          ToJson = toJson
          SetError = fun s _ -> s }

    type ColorPicker private (state: State) =
        static member Create(name: string) =
            ColorPicker 
                { Label = ""
                  Red = 0
                  Green = 0
                  Blue = 0
                  Name = name }
        member __.WithDefaultView () : FieldBuilder =
            { Type = "nojaf-color-picker"
              State = state
              Name = state.Name
              Config = config }
        member __.WithLabel (label : string) =
            ColorPicker { state with Label = label }

When reading the docs while making I think in general it would help if api docs showed the structure of the types as well. Perhaps something similar to how fake does this.

At some points I was a bit confused is this my own type or a FormBuilder type?

The sample State was also a bit confusing. Do I really need all these properties?

MangelMaxime commented 4 years ago

Comment by MangelMaxime Thursday Jan 10, 2019 at 14:18 GMT


About the sample State, yes you need all these properties for a generic input.