diff --git a/Guide/htmx-and-hyperscript.markdown b/Guide/htmx-and-hyperscript.markdown index d2a8448ba..35c80fb76 100644 --- a/Guide/htmx-and-hyperscript.markdown +++ b/Guide/htmx-and-hyperscript.markdown @@ -63,7 +63,7 @@ data CounterController deriving (Eq, Show, Data) ``` -Instead of using the `render` function, htmx routes are better used with `respondHtml` to avoid the layout being shipped as part of the response. The same function can be used for initializing the view as well as upating. +Instead of using the `render` function, htmx routes are better used with `renderHtmlPartial` to avoid the layout being shipped as part of the response. The same function can be used for initializing the view as well as upating. ```haskell module Web.Controller.Counter where @@ -83,12 +83,12 @@ instance Controller CounterController where action IncrementCountAction{counterId} = do counter <- fetch counterId updatedCounter <- counter |> incrementField #count |> updateRecord - respondHtml $ counterView updatedCounter + renderHtmlPartial $ counterView updatedCounter action DecrementCountAction{counterId} = do counter <- fetch counterId updatedCounter <- counter |> decrementField #count |> updateRecord - respondHtml $ counterView updatedCounter + renderHtmlPartial $ counterView updatedCounter ``` We define the `CounterView` like this, separating the `counterView` function into a function that can be used be the initial view as well as the updater routes (`IncrementCountAction` and `DecrementCountAction`). diff --git a/IHP/Controller/Render.hs b/IHP/Controller/Render.hs index 7c36aef88..4beb747eb 100644 --- a/IHP/Controller/Render.hs +++ b/IHP/Controller/Render.hs @@ -67,6 +67,16 @@ renderHtml !view = do pure boundHtml {-# INLINABLE renderHtml #-} +-- | Renders an HTML partial without the layout. +-- This is useful when you want to render a view inside another view, for example with htmx. +renderHtmlPartial :: (?context :: ControllerContext) => Html -> IO () +renderHtmlPartial htmlPartial = do + frozenContext <- Context.freeze ?context + let ?context = frozenContext + let boundHtml = let ?context = frozenContext in htmlPartial + respondHtml boundHtml +{-# INLINABLE renderHtmlPartial #-} + renderFile :: (?context :: ControllerContext) => String -> ByteString -> IO () renderFile filePath contentType = respondAndExit $ responseFile status200 [(hContentType, contentType)] filePath Nothing {-# INLINABLE renderFile #-}