MangelMaxime / Fable.Form

Home Page:https://mangelmaxime.github.io/Fable.Form/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Explore if Fable.Form can be used with React hooks

MangelMaxime opened this issue · comments

In theory, it should be possible to make Fable.Form works outside of Elmish.

The base package of Fable.Form don't have a dependency on Elmish only the view does to get access to Dispatch which is used to send the new form representation.

I think it should be possible to make Fable.Form support both Elmish and Hooks.

@MangelMaxime

I am playing around with Fable form trying to implement it with only React .

I managed to use React.useReducer as a update function which also gives me a Dispatch , only thing is that an update function used by useReducer needs to be pure so no Cmd commands after changing the model.

This is what i have sofar

   type Values = {
      Email : string
      Password : string
      RememberMe : bool
   }

   type Model = Form.View.Model<Values>

   type Message =
      | FormChanged of Model
      | LogIn of string * string * bool

   let evolve (model : Model) = function
      | FormChanged newModel -> newModel
      | LogIn (email, password, rememberMe) ->
         { model with State = Form.View.Success "You have logged in successfully" }

   let initialState () =
      {
         Email = ""
         Password = ""
         RememberMe = false
      }
      |> Form.View.idle

   let form =

      let emailField =
         Form.textField {
               Parser = fun v ->
                  if v.Contains("@") then Ok v
                  else Error "Invalid email address, Email address must contain a @ symbol"
               Value = fun v -> v.Email
               Update = fun newValue values -> { values with Email = newValue }
               Error = fun _ -> None
               Attributes = {
                  Label = "Email"
                  Placeholder = "Enter your email address"
                  HtmlAttributes = [  ]
               }
            }

      let passwordField =
         Form.passwordField {
            Parser = Ok
            Value = fun v -> v.Password
            Update = fun newValue values -> { values with Password = newValue }
            Error = fun _ -> None
            Attributes = {
               Label = "Password"
               Placeholder = "Enter your password"
               HtmlAttributes = [ prop.className "w" ]
            }
         }

      let rememberMe =
         Form.checkboxField {
            Parser = Ok
            Value = fun v -> v.RememberMe
            Update = fun newValue values -> { values with RememberMe = newValue }
            Error = fun _ -> None
            Attributes = { Text = "Remember me" }
         }

      let onSubmit = fun email password rememberMe -> LogIn (email, password, rememberMe)

      Form.succeed onSubmit
      |> Form.append emailField
      |> Form.append passwordField
      |> Form.append rememberMe

   type Component =

      [<ReactComponent>]
      static member LogInForm () =

         let model, dispatch = React.useReducer (evolve, initialState ())

         Form.View.asHtml
            {
               Dispatch = dispatch
               OnChange = FormChanged
               Action = Form.View.Action.SubmitOnly "Sign in"
               Validation = Form.View.ValidateOnSubmit
            }
            form
            model

@Dewald844

Hello,
thank you for the example, this is plus to have for people who want to avoid to use useElmish hooks.

My idea is to go one step farther and remove Elmish as a dependency of Fable.Form. This will require a few changes internally and to the exposed API but I hope to be able to focus on it soon once I am done upgrading another OSS project of mine.