Fable.Form 3.0.0

dotnet add package Fable.Form --version 3.0.0                
NuGet\Install-Package Fable.Form -Version 3.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Fable.Form" Version="3.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Fable.Form --version 3.0.0                
#r "nuget: Fable.Form, 3.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Fable.Form as a Cake Addin
#addin nuget:?package=Fable.Form&version=3.0.0

// Install Fable.Form as a Cake Tool
#tool nuget:?package=Fable.Form&version=3.0.0                

Fable.Form

Gitpod Ready-to-Code

Documentation

Fable.Form allows you to build forms that are:

  • Composable: they can be extended and embedded in other forms
  • Type safe: makes the most of F# compiler to tie everything together
  • Scalable: you don't need a Msg for each field neither repeat your view code
  • Terse: your field logic is defined in a single place
  • Modular: you can create your own fields and customize how existing fields are rendered

Example

let form : Form.Form<Values, Msg, _> =
    let emailField =
        Form.textField
            {
                Parser =
                    fun value ->
                        if value.Contains("@") then
                            Ok value
                        else
                            Error "The e-mail address must contain a '@' symbol"
                Value =
                    fun values -> values.Email
                Update =
                    fun newValue values ->
                        { values with Email = newValue }
                Error =
                    fun _ -> None
                Attributes =
                    {
                        Label = "Email"
                        Placeholder = "some@email.com"
                    }
            }

    let passwordField =
        Form.passwordField
            {
                Parser = Ok
                Value =
                    fun values -> values.Password
                Update =
                    fun newValue values ->
                        { values with Password = newValue }
                Error =
                    fun _ -> None
                Attributes =
                    {
                        Label = "Password"
                        Placeholder = "Your password"
                    }
            }

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

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

Development

This repository use NPM scripts to control the build system here is a list of the main scripts available:

Script Description
npm run clean To use when want to clean all the artifacts
npm run watch-examples To uses when working on the examples project
npm run watch-tests To use when working on the tests suits
npm run watch-docs To use when working on the documentation, hosted on http://localhost:8080
npm run publish-docs Build a new version of the documentation and publish it to Github Pages
npm run release Build a new version of the packages if needed and release it

The secret pun

Naming library is super annoying.

To make it easy to discover, in general, you need to choose a simple and clear name. Especially in a "small" ecosystem like Fable. The problem is that these names are rarely fun neither exciting.

But, it is possible to spice thing up for this reason Fable.Form stands for Fable.Formidable.

Special thanks to Urs Enzler who came up with this idea

History

In 2018, I created Thoth.Elmish.FormBuilder as an attempt to prevent having one Msg per field and repeat the same view code.

At that time, I was not able to find a way to do it in a fully type safe way and use "magic strings" and boxing/unboxing to work around the type system a bit.

The problem is that the system is pretty rigid and when you are in form logic you can't access the outside world or pass data in it. For example, it is hard to integrate external errors or pass the user session to send request on the server for auto completion, etc.

Fast forward three years later, I discovered the work done by Héctor Ramón in elm ecosystem with hecrj/composable-form. This library aligned perfectly with my original vision I had in 2018. I finally, decided to accept that Thoth.Elmish.FormBuilder should be archived and that I should write a new library which aligned with my original vision and goals.

Fable.Form can be seen has a port of hecrj/composable-form for Fable but adapted with my vision of how a form should work.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on Fable.Form:

Package Downloads
Fable.Form.Simple

Contains the global logic of how a form should behave. It can be used has a standalone library if you want to build your own fields or you can use Fable.Form.Simple.Bulma to have a ready to use fields made for Bulma CSS framework.

Fable.Form.Simple.Bulma

React implementation of standard fields using Bulma CSS framework, to be used with Fable.Form.Simple.

Fable.Form.Simple.MaterialUI

This library is a Material UI implementation of Fable.Form.Simple written in F#.

Fable.Form.Antidote

Package Description

Fable.Form.Antidote.View

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0 323 10/20/2024
3.0.0-beta-002 189 9/9/2024
3.0.0-beta-001 68 9/8/2024
2.0.0 2,774 6/23/2023
1.2.0 4,481 7/12/2022
1.1.0 4,493 6/7/2021
1.0.1 583 5/11/2021
1.0.0 538 5/11/2021

### 🚀 Features

* Add support for `ReadOnly` form/field ([02e31e6](https://github.com/glutinum-org/cli/commit/02e31e6fa32f3722da8868ae0b18d34fa1ea68f7))

   1. Set it at the field level

       ```fsharp
       Form.textField
           // ...
           |> Form.readOnly

       // or

       Form.textField
           // ...
           |> Form.readOnlyIf myCondition
       ```

   2. Set it at the form level

       ```fsharp
       let formValue : Form.View.Model<Values> = // ...

       { formValue with State = Form.View.State.Loading }
       ```

* Add `Form.disableIf` ([28337d9](https://github.com/glutinum-org/cli/commit/28337d90c3cd7b686f210db5ab5bde79b371bb66))
* Make it easier to add custom fields ([c99eed9](https://github.com/glutinum-org/cli/commit/c99eed98527d3a0f19b75967434b74af8cb7ca26))

   * Field attributes now needs to inherit from `IAttributes`
   * Refactor `Base.fill` to explicitly take a `values` argument instead of returning a lambda

       ```fsharp
       val fill:
           Form<'Values,'Output,'Field>
           -> 'Values -> FilledForm<'Output,'Field>
       ```

       ```fsharp
       val fill:
           Form<'Values,'Output,'Field> ->
           values: 'Values
           -> FilledForm<'Output,'Field>
       ```