Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally toggle `preventDefault` on form submissions in Elm

Tags:

elm

Is there a way to conditionally toggle preventDefault on form submissions? I've tried using onWithOptions, below, but it seems only the first setting is used, even though I can see it change using Debug.log, when there is a name on the model.

, onWithOptions
    "submit"
    (if model.name == "" then
        (Debug.log "prevent" { preventDefault = True, stopPropagation = True })
      else
        (Debug.log "allow" { preventDefault = False, stopPropagation = False })
    )
    (Json.succeed FormSubmit)

Updated with findings from answer

As stated by @Tosh, hiding the button resolves the issue:

, button
    [ onPreventClickHtml FormSubmit
    , Html.Attributes.hidden (model.name == "" |> not) ]
    [ text " prevent" ]
, button
    [ onClick FormSubmit
    , Html.Attributes.hidden (model.name == "") ]
    [ text "allow" ]

Where onPreventClickHtml is:

onPreventClickHtml : Msg -> Attribute Msg
onPreventClickHtml msg =
    onWithOptions
        "click"
        { preventDefault = True, stopPropagation = True }
        (Json.succeed msg)

Conditionally displaying the button does not work:

, (if model.name == "" then
    button
        [ onPreventClickHtml FormSubmit ]
        [ text " prevent" ]
  else
    button
        [ type' "submit", onClick FormSubmit ]
        [ text "allow" ]
  )

I'm using elm-mdl and so found implementing the solution more challenging because from my experience creating a custom onclick requires types which are not exposed by elm-mdl, and so need to be duplicated.

, if model.name == "" then
    Material.Options.nop
  else
    Material.Options.css "visibility" "hidden"
, onPreventClick FormSubmit

, if model.name == "" then
    Material.Options.css "visibility" "hidden"
  else
    Material.Options.nop
, Button.onClick FormSubmit



onPreventClick : Msg -> Property Msg
onPreventClick message =
    Material.Options.set
        (\options -> { options | onClick = Just (onPreventClickHtml message) })

-- Duplicated from elm-mdl
type alias Property m =
    Material.Options.Property (Config m) m

-- Duplicated from elm-mdl
type alias Config m =
    { ripple : Bool
    , onClick : Maybe (Attribute m)
    , disabled : Bool
    , type' : Maybe String
    }

Another approach, which worked for my scenario, was changing the button type:

, if model.name == "" then
    Button.type' "reset"
  else
    Button.type' "submit"
like image 891
chris Avatar asked Oct 19 '22 00:10

chris


1 Answers

One simple workaround suggestion until someone can show us how to solve it.

How about create two buttons (with different options as you've shown) and depending on the condition show only one of them? You can use Html.Attributes.hide for that.

like image 156
Tosh Avatar answered Oct 22 '22 00:10

Tosh