Introduction
IHP views are usually represented as HTML, but can also be represented as JSON or other formats. The HTML templating is implemented on top of the well-known blaze-html Haskell library. To quickly build HTML views, IHP supports a JSX-like syntax called HSX. HSX is type-checked and compiled to Haskell code at compile-time. The controller provides the view with a key-value map calledControllerContext. The ControllerContext provides the view information it might need to render, without always explicitly passing it. This is usually used to pass e.g. the current HTTP request, logged-in user, flash messages, the layout, etc.
Usually, a view consists of a data structure and a View instance. E.g. like this:
Layouts
By default when rendering an HTML view, IHP uses the default application layout to render your view. It’s defined atdefaultLayout in Web.View.Layout.
A layout is just a function taking a view and returning a new view:
Adding a new layout
To add a new layout, add a new function to theWeb.View.Layout:
appLayout to the export list of the module header:
Using a layout inside a single view
To use the layout inside a view, callsetLayout from the beforeRender:
Using a layout for a complete controller
When all views of a controller use a custom layout place thesetLayout call in the beforeAction of the controller:
Layout Variables
Sometimes you want to pass values to the layout without always having to specify them manually inside therender MyView { .. } calls.
Here’s some examples:
- Your business application wants to display the user’s company name as part of the layout on every page
- The site’s navigation is built dynamically based on a
navigation_itemstable in the database - The layout should show unread notifications
- The current logged in user
?context variable during the request response lifecycle.
Open Web/FrontController.hs and customize it like this:
initContext is called on every request, just before the action is executed. The initCompanyContext fetches the current user’s company and then calls putContext company to store it inside the controller context.
Next we’ll read the company from the Layout.hs:
fromFrozenContext function.
Common View Tasks
Accessing the Request
UsetheRequest to access the current WAI request.
Passing JSON to the View
You might need to pass JSON values to the view, so later you could have a JS script to read it. You should use Aeson’stoJSON function to convert your data to JSON and then pass it to the view.
Highlighting the current active link
UseisActiveAction to check whether the current request URL matches a given action:
isActivePath:
isActiveController.
Breadcrumbs
When using the code generator for a new Controller or View, we get Breadcrumbs pre-configured. You can change them, with three helper functions. All those functions can get a simple text for the label (e.g."Posts") or even HTML opening the door the using SVG or font icons.
Here are a few common examples:
breadcrumbLink "Posts" PostsAction- Show “Posts” label with link to the Posts index page.breadcrumbLink [hsx|<i class="fas fa-home"></i>|] HomepageAction- Using HTML to show a “Home” fonts-awesome icon.breadcrumbText "Show Post"- Showing text or HTML, without a link. Normally that would be for the last breadcrumb.breadcrumbLinkExternal "Back to Portal" "https://example.com"- Breadcrumb link to an external site.
SEO
Setting the Page Title
You can override the default page title by callingsetTitle inside the beforeRender function of your view:
setTitle from the controller action if needed:
Layout.hs is using pageTitleOrDefault:
OG Meta Tags
To dynamically manage meta tags like<meta property="og:description" content="dynamic content"/> add this to your Layout.hs:
beforeRender function within your view:
JSON
Views that are rendered by calling therender function can also respond with JSON.
Let’s say we have a normal HTML view that renders all posts for our blog app. We can add a JSON output for all blog posts by adding a json function:
ToJSON instance which describes how the Post record is going to be transformed to JSON:
Getting JSON responses
When you open thePostsAction at /Posts in your browser you will still get the HTML output. This is because IHP uses the browser Accept header to respond in the best format for the browser which is usually HTML.
JavaScript
From JavaScript you can get the JSON usingfetch:
curl
You can usecurl to check out the new JSON response from the terminal:
Advanced: Rendering JSON directly from actions
When you are building an API and your action is only responding with JSON (so no HTML is expected), you can respond with your JSON directly from the controller usingrenderJson:
renderJson is used instead of the normal render function.