Skip to content
This repository has been archived by the owner on May 2, 2024. It is now read-only.

Form fields for union types #49

Closed
nmk opened this issue Oct 18, 2016 · 10 comments
Closed

Form fields for union types #49

nmk opened this issue Oct 18, 2016 · 10 comments

Comments

@nmk
Copy link

nmk commented Oct 18, 2016

Assume one needs form fields for the following type Account:

type alias CompanyName = String

type Account
    = Private
    | Business CompanyName

I assume the correct form for the UI would be a radio selection between Private and Business, with a text input for the company name appearing if Business is selected.

What would the correct approach be with elm-simple-form?

The part which is unclear to me is how to set up the validation for have one field depend on another.

@etaque
Copy link
Owner

etaque commented Oct 20, 2016

Gosh, I'm afraid I don't have any satisfying answer for this, sorry... Not possible to do dependant validations at the moment.
We could look at how Json.Decode does that, implementation should be similar.

@nmk
Copy link
Author

nmk commented Oct 20, 2016

I did something like this:

type alias CompanyName =
    String


type AccountType
    = Private
    | Business CompanyName


type alias Registration =
    { email : String
    , accountType : AccountType
    }

validateRegistration : Validation () Registration
validateRegistration =
    let
        company =
            "company" := oneOf [ string, emptyString ]
    in
        Validate.succeed Registration
            |: ("email" := email)
            |: (("accountType" := validateAccountType) |: company)


validateAccountType : Validation e (String -> AccountType)
validateAccountType =
    string
        |> map
            (\s ->
                case s of
                    "business" ->
                        \x -> Business x

                    _ ->
                        \_ -> Private
            )

This works but is not ideal, as it allows Business "" as a valid value.

@etaque
Copy link
Owner

etaque commented Oct 20, 2016

Okey, you could try using andThen like in Json.Decode, because Validation's andThen follows the same logic:
http://package.elm-lang.org/packages/elm-lang/core/4.0.5/Json-Decode#andThen

@nmk
Copy link
Author

nmk commented Oct 20, 2016

This is the first thing I tried. However if the validation is like

validateRegistration : Validation () Registration
validateRegistration =
      Validate.succeed Registration
          |: ("email" := email)
          |: ("accountType" := string `andThen` accountType)

accountType : String -> Validation e AccountType
accountType s =
    case s of
        "business" ->
            succeed Business |: ("companyName" := string)

        _ ->
            succeed Private

then andThen shifts the scope of companyName under accountType (the errors include accountType.companyName: InvalidString). Is this intended? In the case of Json.Decode the "scope" is not shifted.

@etaque
Copy link
Owner

etaque commented Oct 20, 2016

Okey, that's not intended, as fair as I can remember.

@nmk
Copy link
Author

nmk commented Oct 20, 2016

@etaque
Copy link
Owner

etaque commented Oct 22, 2016

Thanks for the example. I'm writing tests first as this change will break things.

@etaque
Copy link
Owner

etaque commented Oct 22, 2016

Oh... could you try adding parenthesis like this:

(("accountType" := string) `andThen` accountType)

otherwise andThen is applying on string, not on the whole field getter!

@nmk
Copy link
Author

nmk commented Oct 22, 2016

You are right! That works and solves the problem nicely. It would be nice if we could get this in the documentation. I will try to get a PR in next week.

@nmk nmk closed this as completed Oct 22, 2016
@nmk
Copy link
Author

nmk commented Oct 22, 2016

Just for completeness, here is a link to a working gist: https://gist.github.com/nmk/e9fd97dd1a62c04fc52545fec5a9b4ef

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants