evancz / url-parser

Parse URLs into nicely structured data
http://package.elm-lang.org/packages/evancz/url-parser/latest/
BSD 3-Clause "New" or "Revised" License
114 stars 29 forks source link

Add example for multiple query parameters #33

Closed rofrol closed 6 years ago

rofrol commented 7 years ago

It's not clear what should be done to have multiple query parameters.

process-bot commented 7 years ago

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

magopian commented 6 years ago

It wasn't immediately obvious to me that in such case, you need to map the parser, eg:

type alias QueryData =
    { hash : Maybe String
    , lang : Maybe String
    }

queryParser =
    top <?> stringParam "hash" <?> stringParam "lang"

parsePath (map QueryData queryParser) location
-- /?hash=abc&lang=fr ==> Just { hash = Just "abc", lang = Just "fr" }

If you omit the maping, you'll have an error like the following:

The 1st argument to function `parsePath` is causing a mismatch.

75|             parsePath queryParser url
                          ^^^^^^^^^^^
Function `parsePath` is expecting the 1st argument to be:

    UrlParser.Parser (Maybe String -> Maybe String) (Maybe String)

But it is:

    UrlParser.Parser
        (Maybe String -> Maybe String -> Maybe String)
        (Maybe String)

Hint: It looks like a function needs 1 more argument.
rofrol commented 6 years ago

I got answer on so https://stackoverflow.com/questions/43111085/evancz-url-parser-and-multiple-query-parameters

prikhi commented 6 years ago

Another, more complex example:

https://github.com/Southern-Exposure-Seed-Exchange/southernexposure.com/blob/373bb759d08b7a34a15025d76ebd4276bd6b1064/client/src/Products/Sorting.elm#L56-L63

https://github.com/Southern-Exposure-Seed-Exchange/southernexposure.com/blob/8704426fa289cf90ed589e8d4ddadc4b47233482/client/src/Products/Pagination.elm#L43-L52

I parse a datatype from the sortBy query parameter, falling back to a default if there is no parameter:

-- Sorting.elm
type Option
    = ProductNameAsc
    | ProductNameDesc

default = ProductNameAsc

fromQueryString pathParser =
    Url.map (\f a -> f a)
        (pathParser
            <?> Url.customParam "sortBy" (Maybe.withDefault "" >> fromQueryValue)
        )

fromQueryValue data =
    case data of
        "name-asc" ->
            ProductNameAsc

        "name-desc" ->
            ProductNameDesc
        _ ->
            default

Then, I compose that query parser to build a more complex data type:

-- Pagination.elm
type alias Data =
    { page : Int
    , perPage : Int
    , sorting : Sorting.Option
    }

default = Data 1 25 Sorting.default

fromQueryString pathParser =
    Url.map (\constructor page perPage -> constructor << Data page perPage)
        (pathParser
            <?> optionalIntParam "page" (default.page)
            <?> optionalIntParam "perPage" (default.perPage)
        )
        |> Sorting.fromQueryString

where optionalIntParam : String -> Int -> QueryParser (Int -> b) b

evancz commented 6 years ago

I think this will be clearer in the next iteration of the API, so we can revisit if this is clear enough after it comes out.

wscherphof commented 5 years ago

Time has come to revisit this now?

Natim commented 5 years ago

Time has come to revisit this now?

How would you want it to work?