Find item in list and add to other list

Viewed 39

I have a model containing a list of items that are rendered in a select as options. The user can select an item, enter a number and click add to add the selected item and a "quantity" to a list.

My model looks like this:

type alias Drink =
  { id: String
  , name: String
  }

type alias Item =
  { id: String
  , quantity: Int
  }

type alias Model =
  { drinks: List Drink
  , selected: List Item
  , inputDrink: String
  , inputQuantity: Int
  }

I then want to render the selected list in a table. My main struggle right now is figuring out how I map over the array of selected items, based on the id of the current item find the name of the Drink to render in the table.

I've made this itemRow view:

itemRow : (Item, Drink) -> Html Msg
itemRow tuple =
  -- This bit not updated to work with a Tuple yet.
  tr [ id item.id ]
    [ td []
      [ button [] [ text "x" ]
      ]
    , td [] [ text drink.name ]
    , td []
      [ input [ type_ "number", value (String.fromInt item.quantity) ] []
      ]
    ]

So what I'd like is to do something like:

model.selected
|> List.map (\selected -> (selected, List.Extra.find (\drink -> drink.id == selected.id)) )
|> List.map itemRow

But to do this I need to get rid of the Maybe I get from List.Extra.find and I don't know how…

Any other tips or tricks on how I might better solve this by modelling the data differently very welcome. New to Elm :)

1 Answers

Here's how you remove the Nothings. Although you know that the find must always succeed, Elm requires you to handle the case where it does not. Here I just ignore those cases.

model.selected
  |> List.filterMap (\selected -> 
    case List.Extra.find (\drink -> drink.id == selected.id) of 
      Just x -> Just (selected, x)
      Nothing -> Nothing 
    )
  |> List.map itemRow
Related