There aren't any good guides for using AttrSplices from Heist. The tutorial from the Snap website fails to show how to bind them, and the only public code I can find that uses them is Digestive Functors Heist.
type AttrSplice m = Text -> RuntimeSplice m [(Text, Text)]
The AttrSplice
type signature says that it takes a Text
and returns a Monad containing a list of tuples of Text
. The first argument would only be used if you're planning on using it as a point of comparison within the template, as shown in the Attribute Splices Tutorial (n.b. the type signature listed here is slightly different, this might reflect an older version of Heist):
autocheckedSplice :: Text -> StateT Text IO [(Text, Text)]
autocheckedSplice v = do
val <- get -- app-specific retrieval of the appropriate value here
let checked = if v == val
then [("checked","")]
else []
return $ ("value", v) : checked
In this case, when the autoCheckedSplice
is bound to the autocheck
attribute, it will receive the value of the autocheck attribute from your template (eg. red, green, or blue). If you're using an empty attribute (ie. an attribute without a value like checked
), this will be a zero length value (eg. an empty string).
For cases where you aren't interested in the value from the template, you might want to pass in a specific value elsewhere. Here is an example AttrSplice
that accepts a Bool and returns an AttrSplice that ignores the passed in Text argument:
checkedSplice :: Monad m => Bool -> AttrSplice m
checkedSplice True = const $ return [("checked", "checked")]
checkedSplice _ = mempty
When you bind attribute splices, you do so without arguments. Heist will pass the value in later. In the following example, I am binding the checkedSplice
to the isFeatured
attribute. From there, the binding is a little more verbose than normal, since you'll have to use localHS
in combination with bindAttributeSplices
.
imageSplice :: Monad m => Image.Image -> Splice m
imageSplice i =
let
attrSplices = do
"autocheck" ## autocheckedSplice
-- ^ no arguments here for autocheckedSplice
"isFeatured" ## checkedSplice (Image.featured i)
-- ^ passing in a value to an AttrSplice that discards the attribute value
in localHS (bindAttributeSplices attrSplices) $ runChildrenWith $ imageSplices i
-- ^ binding it to the HeistState
If you find that you're using this pattern pretty often, you may want to create a helper function for that:
foo :: Monad m => Splices (AttrSplice m) -> Splices (Splice m) -> Splice m
foo attrSplices splices = localHS (bindAttributeSplices attrSplices) $ runChildrenWith splices
If you just have a one-off page that needs to have attribute splices added, you can bind them like this:
heistLocal (bindAttributeSplices attrSplices) $ render "mytemplate"