Timo
Timo

Reputation: 121

How To Structure A Model So It Can Be Turned Into A Dynamic Form Easily

I want to have an expert opinion on how to shape a model to make it fit into a table/form.

I tried a lot, but got stuck.

This is my model:

type alias Model =
{   freeSyllables : List FreeSyllable
,   addFreeSyllableInput : String
,   addUsageStartInput : Bool
,   addUsageMidInput : Bool
,   addUsageEndInput : Bool
}

it's build up out of:

type alias FreeSyllable =
{   syllable : String
,   usage : Usage
}

type alias Usage =
{   start : Bool
,   mid : Bool
,   end : Bool
}

My view is a mixture between a form and a table. The table/form should be editable per row if I click an edit-Button, which every row should have.

How would you design the model and how would you react upon changes in the table/form?

Thanks ... :D

Upvotes: 0

Views: 226

Answers (1)

Igor Drozdov
Igor Drozdov

Reputation: 15055

The inspiration can be taken from Todo MVC example

The idea is having an editing : Bool field in FreeSyllable record and depending on the value of editing either input or text (or something else) is displayed. The value of editing is set by clicking either edit or submit buttons (or by losing focus event... whatever)

Here is an example just for illustrating how it can work:

The FreeSyllable type with a new editing field:

type alias FreeSyllable =
  {   syllable : String
  ,   usage : Usage
  ,   editing : Bool
  }

The view that displays either input or text and sends UpdateSyllable and EditingSyllable events:

view model =
    div []
        [ ul [] (List.indexedMap viewSyllable model.freeSyllables)
        ]

viewSyllable index freeSyllable =
    li []
        [ if freeSyllable.editing then
            div []
                [ input [ onInput (UpdateSyllable index), value freeSyllable.syllable ] []
                , a [ onClick (EditingSyllable index False) ] [ text "submit" ]
                ]
          else
            div []
                [ text freeSyllable.syllable
                , a [ onClick (EditingSyllable index True) ] [ text "edit" ]
                ]
        ]

The update which updates the model:

type Msg
    = UpdateSyllable Int String
    | EditingSyllable Int Bool


update msg model =
    case msg of
        UpdateSyllable index syllable ->
            let
                updateSyllable idx freeSyllable =
                    if idx == index then
                        { freeSyllable | syllable = syllable }
                    else
                        freeSyllable
            in
                { model | freeSyllables = List.indexedMap updateSyllable model.freeSyllables }

        EditingSyllable index editing ->
            let
                updateSyllable idx freeSyllable =
                    if idx == index then
                        { freeSyllable | editing = editing }
                    else
                        freeSyllable
            in
                { model | freeSyllables = List.indexedMap updateSyllable model.freeSyllables }

Hope I've managed to clarify the idea.

Upvotes: 1

Related Questions