1

In Application.Helper.View I would like to create an HTML component like:

button :: action -> Text -> Html
button action label = [hsx|<a href={urlTo action}>{label}</a>|]

which I can use in various views like: {button NewSessionAction "Login"}

However, what is the correct type signature for an action? Checking the source for urlTo (https://ihp.digitallyinduced.com/api-docs/src/IHP.RouterSupport.html#urlTo) shows that action conforms to HasPath but still I am not sure how I should write my function.

I am a novice at Haskell and so any guidance along with the "why" would be a great help.

  • Have you tried `(?context :: context, ConfigProvider context, HasPath action) => action -> Text -> Html` ? – pedrofurla Jan 07 '22 at 01:09
  • @pedrofurla Thanks! That makes it work. However, I have to import `IHP.RouterPrelude` to make it work, which then introduces conflicts because `IHP.ViewPrelude` is already imported. E.g. the compiler complains about an ambiguous reference to `get` which is imported from both. – stephenbenedict Jan 07 '22 at 04:46
  • 1
    Try to make it an qualified import like `import qualified IHP.RouterPrelude as Router` and then use `Router.urlTo` instead of `urlTo` and `Router.HasPath` instead of `HasPath` – Marc Scholten Jan 07 '22 at 06:20
  • @MarcScholten Brilliant! That is the solution. Should have thought of that! – stephenbenedict Jan 07 '22 at 07:41
  • If I may ask, what does `ConfigProvider context` do? Removing it does not affect the functionality. – stephenbenedict Jan 07 '22 at 07:45
  • 1
    `?context::context` is an implicit parameter. These are enabled as aHaskell extension. They are a way of emulating dynamic binding of variables using the type system so that certain "global" configuration information comes in to scope in your function. `ConfigProvider context` is a typeclass constraint that means you can call `getFrameworkConfig` on the `?context` to access a number of app configuration properties from within that function. IHP makes use of Implicit parameters in a few places e.g. `(?modelContext :: ModelContext)` to pass around config params and database connection urls etc. – Montmorency Jan 07 '22 at 20:55

1 Answers1

2

(Answer by @pedrofurla and @MarcScholten)

  1. Import IHP.RouterPrelude:
import qualified IHP.RouterPrelude as Router
  1. Change the HTML component function to look like:
button :: (?context :: context, ConfigProvider context, Router.HasPath action) => action -> Text -> Html
button action label = [hsx|<a href={Router.urlTo action}>{label}</a>|]
glennsl
  • 28,186
  • 12
  • 57
  • 75