0
votes

I am trying to write a simple application in Fable, but I have problems setting up elements. I am not able to add new elements without ruining the existing ones.

let view model dispatch =
    div [ Class "main-container" ]
        [ input [ Class "input"
                  Value model.Value
                  OnChange (fun ev -> ev.target?value |> string |> ChangeValue |> dispatch) ]
          span [ ]
            [ str "Hello, "
              str model.Value
              str "!" ] ]

This is the example from fable.io webste. I am trying to add, for example, another input, text, button or any other element, but how can I? I cannot find any rules that need to be followed. What am I missing on?

UPDATE:

let view model dispatch =
    let digit n = digitBtn n dispatch
    div
      [ calcStyle ]
      [
        br []
        table []
            [ digit 1 ] ]  

yields the error

Type mismatch. Expecting a 'Model -> Dispatch -> 'a' but given a 'Model -> (string -> unit) -> Fable.Import.React.ReactElement' The type 'Msg' does not match the type string

2
I don't know your calcStyle and digitBtn functions, but if I just remove the style (leave an empty list) and have let digit n = button [ Type "button" ] [ str (n.ToString()) ], it does compile... Can you post the rest of the file? (Program.mkProgram ...) - psfinaki
In your updated example, I have to guess at what the definition of digitBtn is, but it seems to expect a different dispatch function than what you're getting in view here. In that case you either need to change how dispatch is used in digitBtn or pass it a dispatch function that conforms to what it expects. A common pattern is to wrap the dispatched value in a Msg variant by doing MyMsgVariant >> dispatch - glennsl

2 Answers

0
votes

Basically, div takes a list of properties and then a list of elements to hold inside. So to add another element inside, you can add an item to that list.

For example, another input:

let view model dispatch =
    div [ Class "main-container" ]
        [ input [ Class "input"
                  Value model.Value
                  OnChange (fun ev -> ev.target?value |> string |> ChangeValue |> dispatch) ]
          span [ ]
            [ str "Hello, "
              str model.Value
              str "! " ]
          span [ ]
            [ str "How's life, "
              str model.Value
              str "?" ] ]
0
votes

Here's another text element added to the end of it:

let view model dispatch =
    div [ Class "main-container" ]
        [ input [ Class "input"
                  Value model.Value
                  OnChange (fun ev -> ev.target?value |> string |> ChangeValue |> dispatch) ]
          span [ ]
            [ str "Hello, "
              str model.Value
              str "!" ]
          str "Goodbye!" ]

Without knowing what you've tried, I have to guess at what might be confusing you. But my guess would be that it's F#'s unique whitespace sensitivity. F# will often treat newline as a delimiter between lines indented at the same level. in this case, input ..., span ... and str ... are items of a list.

You can however also delimit list items explicitly with a semicolon:

let view model dispatch =
    div [ Class "main-container" ]
        [ input [ Class "input"
                  Value model.Value
                  OnChange (fun ev -> ev.target?value |> string |> ChangeValue |> dispatch) ]
          span [ ]
            [ str "Hello, "
              str model.Value
              str "!" ]; str "Goodbye!" ]

See more about list syntax in the F# Language Reference documentation.