Accept any error type in request

This commit is contained in:
Tom Nunn 2023-03-07 20:39:24 +00:00
parent 75ba802b6b
commit 7f322a5e22
6 changed files with 40 additions and 41 deletions

View File

@ -67,12 +67,12 @@ update msg model =
|> Tuple.mapBoth (\select -> { model | select = select }) SelectEffect
fetchCocktails : String -> (Result String (List Cocktail) -> Msg) -> Cmd Msg
fetchCocktails : String -> (Result Http.Error (List Cocktail) -> Msg) -> Cmd Msg
fetchCocktails query tagger =
Http.get
{ url = "https://thecocktaildb.com/api/json/v1/1/search.php?s=" ++ String.replace " " "+" query
, expect =
Http.expectJson (Result.mapError (\_ -> "Failed fetching cocktails") >> tagger)
Http.expectJson tagger
(Decode.field "drinks"
(Decode.oneOf
[ Decode.list cocktailDecoder
@ -90,7 +90,7 @@ fetchCocktails query tagger =
type MyEffect
= NoEffect
| SelectEffect (Select.Effect MyEffect Msg)
| FetchCocktails String (Result String (List Cocktail) -> Msg)
| FetchCocktails String (Result Http.Error (List Cocktail) -> Msg)
performEffect : MyEffect -> Cmd Msg

View File

@ -71,12 +71,12 @@ simulateEffect effect =
fetchCocktails query msg
fetchCocktails : String -> (Result String (List App.Cocktail) -> msg) -> SimulatedEffect msg
fetchCocktails : String -> (Result SimulateHttp.Error (List App.Cocktail) -> msg) -> SimulatedEffect msg
fetchCocktails query tagger =
SimulateHttp.get
{ url = "https://thecocktaildb.com/api/json/v1/1/search.php?s=" ++ String.replace " " "+" query
, expect =
SimulateHttp.expectJson (Result.mapError (\_ -> "Failed fetching cocktails") >> tagger)
SimulateHttp.expectJson tagger
(Decode.field "drinks"
(Decode.oneOf
[ Decode.list App.cocktailDecoder

View File

@ -8,7 +8,7 @@ import Internal.RequestState exposing (RequestState(..))
import Internal.UpdateOptions exposing (UpdateOptions)
update : UpdateOptions effect a msg -> (Msg a -> msg) -> Msg a -> Model a -> ( Model a, Effect effect msg )
update : UpdateOptions err effect a msg -> (Msg a -> msg) -> Msg a -> Model a -> ( Model a, Effect effect msg )
update ({ onSelect } as options) tagger msg model =
update_ options tagger msg model
|> withEffect
@ -22,7 +22,7 @@ update ({ onSelect } as options) tagger msg model =
)
update_ : UpdateOptions effect a msg -> (Msg a -> msg) -> Msg a -> Model a -> ( Model a, Effect effect msg )
update_ : UpdateOptions err effect a msg -> (Msg a -> msg) -> Msg a -> Model a -> ( Model a, Effect effect msg )
update_ { request, requestMinInputLength, debounceRequest, onFocus, onLoseFocus, onInput } tagger msg model =
case msg of
InputChanged val ->
@ -128,7 +128,7 @@ update_ { request, requestMinInputLength, debounceRequest, onFocus, onLoseFocus,
InputDebounceReturned val ->
if val == Model.toInputValue model then
( Model.setRequestState (Just Loading) model
, Maybe.map (\effect -> Effect.Request (effect val (GotRequestResponse val >> tagger))) request
, Maybe.map (\effect -> Effect.Request (effect val (Result.mapError (\_ -> "") >> GotRequestResponse val >> tagger))) request
|> Maybe.withDefault Effect.none
)

View File

@ -1,8 +1,8 @@
module Internal.UpdateOptions exposing (UpdateOption(..), UpdateOptions, fromList)
type UpdateOption effect a msg
= Request (String -> (Result String (List a) -> msg) -> effect)
type UpdateOption err effect a msg
= Request (String -> (Result err (List a) -> msg) -> effect)
| DebounceRequest Float
| RequestMinInputLength Int
| OnSelect (Maybe a -> msg)
@ -11,8 +11,8 @@ type UpdateOption effect a msg
| OnInput (String -> msg)
type alias UpdateOptions effect a msg =
{ request : Maybe (String -> (Result String (List a) -> msg) -> effect)
type alias UpdateOptions err effect a msg =
{ request : Maybe (String -> (Result err (List a) -> msg) -> effect)
, debounceRequest : Float
, requestMinInputLength : Int
, onSelect : Maybe (Maybe a -> msg)
@ -22,7 +22,7 @@ type alias UpdateOptions effect a msg =
}
init : UpdateOptions effect a msg
init : UpdateOptions err effect a msg
init =
{ request = Nothing
, debounceRequest = 300
@ -34,7 +34,7 @@ init =
}
fromList : List (UpdateOption effect a msg) -> UpdateOptions effect a msg
fromList : List (UpdateOption err effect a msg) -> UpdateOptions err effect a msg
fromList =
List.foldl
(\opt opts ->

View File

@ -260,7 +260,7 @@ update tagger msg select =
Debug.todo "Do something when the thing is selected/deselected"
-}
updateWith : List (UpdateOption a msg) -> (Msg a -> msg) -> Msg a -> Select a -> ( Select a, Cmd msg )
updateWith : List (UpdateOption err a msg) -> (Msg a -> msg) -> Msg a -> Select a -> ( Select a, Cmd msg )
updateWith options tagger msg select =
Update.update (UpdateOptions.fromList options) tagger msg select
|> Tuple.mapSecond (Effect.perform identity)
@ -268,13 +268,13 @@ updateWith options tagger msg select =
{-| Options for use with updateWith.
-}
type alias UpdateOption a msg =
UpdateOptions.UpdateOption (Cmd msg) a msg
type alias UpdateOption err a msg =
UpdateOptions.UpdateOption err (Cmd msg) a msg
{-| Use an HTTP request to retrieve matching remote results. ote that in order to avoid an elm/http dependency in this package,
you will need to provide the request Cmd yourself. Provide a function that takes the input value and a msg tagger and returns a Cmd.
Update will return this Cmd when the user types in the input. Note, you need to map the error of the response to String before passing to the msg tagger.
Update will return this Cmd when the user types in the input.
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
@ -283,17 +283,17 @@ Update will return this Cmd when the user types in the input. Note, you need to
Select.updateWith [ Select.request fetchThings ] SelectMsg subMsg model.select
|> Tuple.mapFirst (\select -> { model | select = select })
fetchThings : String -> (Result String (List Thing) -> Msg) -> Cmd Msg
fetchThings : String -> (Result Http.Error (List Thing) -> Msg) -> Cmd Msg
fetchThings query tagger =
Http.get
{ url = "https://awesome-thing.api/things?search=" ++ query
, expect =
Http.expectJson (Result.mapError (\_ -> "Failed fetching things") >> tagger)
Http.expectJson tagger
(Decode.list thingDecoder)
}
-}
request : (String -> (Result String (List a) -> msg) -> Cmd msg) -> UpdateOption a msg
request : (String -> (Result err (List a) -> msg) -> Cmd msg) -> UpdateOption err a msg
request effect =
UpdateOptions.Request effect
@ -303,7 +303,7 @@ request effect =
Select.updateWith [ Select.request fetchThings, Select.requestDebounceDelay 500 ] SelectMsg subMsg model.select
-}
requestDebounceDelay : Float -> UpdateOption a msg
requestDebounceDelay : Float -> UpdateOption err a msg
requestDebounceDelay delay =
UpdateOptions.DebounceRequest delay
@ -314,7 +314,7 @@ If this is too low you may get an unmanagable number of results! Default is 3 ch
Select.updateWith [ Select.request fetchThings, Select.requestMinInputLength 4 ] SelectMsg subMsg model.select
-}
requestMinInputLength : Int -> UpdateOption a msg
requestMinInputLength : Int -> UpdateOption err a msg
requestMinInputLength len =
UpdateOptions.RequestMinInputLength len
@ -324,28 +324,28 @@ requestMinInputLength len =
Select.updateWith [ Select.onSelectedChange SelectionChanged ] SelectMsg subMsg model.select
-}
onSelectedChange : (Maybe a -> msg) -> UpdateOption a msg
onSelectedChange : (Maybe a -> msg) -> UpdateOption err a msg
onSelectedChange msg =
UpdateOptions.OnSelect msg
{-| If provided this msg will be sent whenever the input value changes.
-}
onInput : (String -> msg) -> UpdateOption a msg
onInput : (String -> msg) -> UpdateOption err a msg
onInput msg =
UpdateOptions.OnInput msg
{-| If provided this msg will be sent whenever the input is focused.
-}
onFocus : msg -> UpdateOption a msg
onFocus : msg -> UpdateOption err a msg
onFocus msg =
UpdateOptions.OnFocus msg
{-| If provided this msg will be sent whenever the input loses focus.
-}
onLoseFocus : msg -> UpdateOption a msg
onLoseFocus : msg -> UpdateOption err a msg
onLoseFocus msg =
UpdateOptions.OnLoseFocus msg

View File

@ -109,29 +109,28 @@ update =
Debug.todo "Do something when the thing is selected/deselected"
-}
updateWith : List (UpdateOption effect a msg) -> (Msg a -> msg) -> Msg a -> Select a -> ( Select a, Effect effect msg )
updateWith : List (UpdateOption err effect a msg) -> (Msg a -> msg) -> Msg a -> Select a -> ( Select a, Effect effect msg )
updateWith options =
Update.update (UpdateOptions.fromList options)
{-| Options for use with updateWith.
-}
type alias UpdateOption effect a msg =
UpdateOptions.UpdateOption effect a msg
type alias UpdateOption err effect a msg =
UpdateOptions.UpdateOption err effect a msg
{-| Update with an HTTP request to retrieve matching remote results.
Note that in order to avoid an elm/http dependency in this package, you will need to provide the request Effect yourself.
Provide an effect (your app's own Effect type) that uses the input value and a msg tagger that can be used to perform an HTTP request.
Provide an effect (your app's own Effect type) that uses the input value and a msg tagger that can perform an HTTP request.
Update will use this Effect when the user types into the input.
When the effect is performed you must use Select.Effect.performWithRequest instead of Select.Effect.perform.
You need to map the error of the request to string before passing to the msg tagger.
type MyEffect
= SelectEffect (Select.Effect MyEffect Msg)
| FetchThings String (Result String (List Thing) -> Msg)
| FetchThings String (Result Http.Error (List Thing) -> Msg)
update : Msg -> Model -> ( Model, MyEffect )
update msg model =
@ -151,19 +150,19 @@ You need to map the error of the request to string before passing to the msg tag
Http.get
{ url = "https://awesome-thing.api/things?search=" ++ query
, expect =
Http.expectJson (Result.mapError (\_ -> "Failed fetching things") >> tagger)
Http.expectJson tagger
(Decode.list thingDecoder)
}
-}
request : (String -> (Result String (List a) -> msg) -> effect) -> UpdateOption effect a msg
request : (String -> (Result err (List a) -> msg) -> effect) -> UpdateOption err effect a msg
request effect =
UpdateOptions.Request effect
{-| Configure debouncing for the request. How long should we wait in milliseconds after the user stops typing to send the request? Default is 300.
-}
requestDebounceDelay : Float -> UpdateOption effect a msg
requestDebounceDelay : Float -> UpdateOption err effect a msg
requestDebounceDelay delay =
UpdateOptions.DebounceRequest delay
@ -171,35 +170,35 @@ requestDebounceDelay delay =
{-| How many characters does a user need to type before a request is sent?
If this is too low you may get an unmanagable number of results! Default is 3 characters.
-}
requestMinInputLength : Int -> UpdateOption effect a msg
requestMinInputLength : Int -> UpdateOption err effect a msg
requestMinInputLength len =
UpdateOptions.RequestMinInputLength len
{-| If provided this msg will be sent whenever the selected item changes.
-}
onSelectedChange : (Maybe a -> msg) -> UpdateOption effect a msg
onSelectedChange : (Maybe a -> msg) -> UpdateOption err effect a msg
onSelectedChange msg =
UpdateOptions.OnSelect msg
{-| If provided this msg will be sent whenever the input value changes.
-}
onInput : (String -> msg) -> UpdateOption effect a msg
onInput : (String -> msg) -> UpdateOption err effect a msg
onInput msg =
UpdateOptions.OnInput msg
{-| If provided this msg will be sent whenever the input gets focus.
-}
onFocus : msg -> UpdateOption effect a msg
onFocus : msg -> UpdateOption err effect a msg
onFocus msg =
UpdateOptions.OnFocus msg
{-| If provided this msg will be sent whenever the input loses focus.
-}
onLoseFocus : msg -> UpdateOption effect a msg
onLoseFocus : msg -> UpdateOption err effect a msg
onLoseFocus msg =
UpdateOptions.OnLoseFocus msg