Combine elm/url Url Query param parsers using a pipeline style - think elm-json-decode-pipeline but for Url Query params:
import Url exposing (Url)
import Url.Parser as Parser exposing ((<?>), s, top)
import Url.Parser.Query as Query
import Url.Query.Pipeline as Pipeline
type Route
= Home (Maybe MyQuery)
| AnotherRoute
type alias MyQuery =
{ one : String
, two : Maybe String
, three : List Int
}
query : Query.Parser (Maybe MyQuery)
query =
Pipeline.succeed MyQuery
|> Pipeline.required (Query.string "one")
|> Pipeline.optional (Query.string "two")
|> Pipeline.with (Query.custom "three" (List.filterMap String.toInt))
routes : Parser.Parser (Route -> a) a
routes =
Parser.oneOf
[ Parser.map Home (top <?> query)
, Parser.map AnotherRoute (s "another-route")
]
fromString : String -> Maybe Route
fromString =
Url.fromString >> Maybe.andThen (Parser.parse routes)Some examples from above:
fromString "http://example/another-route" == Just AnotherRoute
fromString "http://example?one=hello&two=world&three=1&three=2"
== Just
(Home
(Just
{ one = "hello"
, two = Just "world"
, three = [ 1, 2 ]
}
)
)
-- required param "one" is missing
fromString "http://example?two=world&three=1"
== Just (Home Nothing)The examples below use the function parse
parse : Query.Parser (Maybe MyQuery) -> String -> Maybe MyQueryMaybe MyQuery?elm/url's Query Parsers all return Maybe a.
The Pipeline functions is also Maybe a to maintain compatibility with elm/url.
Combine a parser that must not be Nothing, if the parser returns Nothing the whole pipeline will return Nothing
type alias MyQuery =
{ one : String
, two : Maybe String
}
myQuery : Query.Parser (Maybe MyQuery)
myQuery =
Pipeline.succeed MyQuery
|> Pipeline.required (Query.string "one")
|> Pipeline.optional (Query.string "two")Examples:
parse myQuery "one=one&two=two"
== Just { one = "one", two = Just "two" }
parse myQuery "one=one"
== Just { one = "one", two = Nothing }
-- missing required param
parse myQuery "two=two"
== NothingCombine a parser that returns a Maybe value
type alias MyQuery =
{ one : Maybe String
, two : Maybe String
}
myQuery : Query.Parser (Maybe MyQuery)
myQuery =
Pipeline.succeed MyQuery
|> Pipeline.optional (Query.string "one")
|> Pipeline.optional (Query.string "two")Examples:
parse myQuery "one=one"
== Just { one = Just "one", two = Nothing }
parse myQuery "two=two"
== Just { one = Nothing "one", two = Just "two" }
parse myQuery ""
== Just { one = Nothing, two = Nothing }Combine any parser as is: useful for Lists or Custom Types
type alias MyQuery =
{ one : List String
, two : Fruit
}
type Fruit
= Apple
| Pear
myQuery : Query.Parser (Maybe MyQuery)
myQuery =
Pipeline.succeed MyQuery
|> Pipeline.with (Query.custom "one" identity)
|> Pipeline.with (Query.enum "two" fruitOptions |> Query.map (Maybe.withDefault Apple))Examples:
parse myQuery "one=a&one=b&two=pear"
== Just { one = [ "a", "b" ], two = Pear }
parse myQuery "two=apple"
== Just { one = [], two = Apple }Apply a default value for a parser containing a Maybe
type alias MyQuery =
{ one : String
, two : Fruit
}
type Fruit
= Apple
| Pear
myQuery : Query.Parser (Maybe MyQuery)
myQuery =
Pipeline.succeed MyQuery
|> Pipeline.required (Query.string "one")
|> Pipeline.withDefault (Query.enum "two" fruitOptions) AppleExamples:
parse myQuery "one=one&two=pear"
== Just { one = "one", two = Pear }
parse myQuery "one=one"
== Just { one = "one", two = Apple }Apply a hardcoded value
type alias MyQuery =
{ one : String
, two : Int
}
myQuery : Query.Parser (Maybe MyQuery)
myQuery =
Pipeline.succeed MyQuery
|> Pipeline.required (Query.string "one")
|> Pipeline.hardcoded 42Examples:
parse myQuery "one=one"
== Just { one = "one", two = 42 }
Start off a pipeline
Examples: