larribas / elm-multi-input / MultiInput

A component to input multiple items and display/manage them comfortably.

You can completely customize the type of items it accepts or the way different items are split up. Examples are an input for multiple item (as in an item client's FROM field), or a tag input (as in Github's repository topics). It allows pasting in bulk, removing existing items and ammending the last typed item.

For a better feel of what you can do with this component, visit the demo here

Custom Configuration


type alias ViewConfig msg =
{ placeholder : String
, isValid : String -> Basics.Bool
, toOuterMsg : Msg -> msg 
}

Specific settings for the component's view function.

isValid determines whether a typed item is correct (and give visual feedback to the user) toOuterMsg turns the internal messages for the component into messages from the outer page/component

{ placeholder = "Write your email here"
, isValid = \x -> String.contains "@"
, toOuterMsg = MultiInputMsg
}


type alias UpdateConfig =
{ separators : List String }

Specific settings for the component's update function.

You can specify a list of strings that act as separators for the different items.

{ separators = [ "\n", "\t", ",", " " ] }

Main workflow


type Msg
    = FocusElement
    | TextareaBlurred String
    | KeyDown Basics.Int
    | RemoveItem String
    | InputChanged String

Internal messages to manage the component's state.


type alias State =
{ nextItem : String
, id : String
, needsRefocus : Basics.Bool 
}

Component's internal state.

init : String -> State

Initialize the component's state.

It needs a unique ID supplied by the user, in case there are several inputs like this on the same document. By default, we begin with an empty textarea.

update : UpdateConfig -> Msg -> State -> List String -> ( State, List String, Platform.Cmd.Cmd Msg )

Updates the component's state and a supplied list of items.

Given a particular change on the input (e.g. a series of items have been pasted, the component has lost focus, a special key has been pressed...) it will update the list of distinct items and the current state of the component.

subscriptions : State -> Platform.Sub.Sub Msg

Subscribes to relevant events for the input

This allows the component to control the input focus properly, subscribing to the Browser's animation frame sequence.

The subscription is managed only when strictly needed, so it does not have an impact on performance.

view : ViewConfig msg -> List (Html.Attribute msg) -> List String -> State -> Html msg

Renders the component visually.

   MultiInput.view MultiInputMsg [] "Write a placeholder here" model.inputItems model.inputItemsState

See README for actual examples.