I am trying to create dynamic links using the Heist templating system. The problem is that the links are appearing as text rather than being interpreted as html. Is there a specific method to create dyamic lists like this with Heist?
The function where the link is constructed:
renderCategories :: Monad m => Db.Category -> I.Splice m
renderCategories (Db.Category catid catname catdesc) =
I.runChildrenWithText [ ("categoryId", T.concat $ ["<a href='http://localhost:8000/thread_home?cateid=", T.pack . show $ catid, "'>", T.pack . show $ catid, "</a>"])
, ("categoryName", catname)
, ("categoryDesc", catdesc)]
The tag appears as "http://localhost:8000/thread_home?cateid=1'>1" text on the webpage. And the source shows it as follows:
<a href='http://localhost:8000/thread_home?cateid=1'>1</a>
I figure that I need to have it print the actual < and > but I am not sure how to achieve this. As I am currently running runChildrenWithText to populate this Heist template changing to just runChildrenWith requires splices instead of text and so instead of attempting this I am hoping there is some way to runChildrenWithText without the '<' and '>' being converted to '<' and '>'. Any help is appreciated!
EDIT
I am trying to manually create the link using:
renderCategories :: Monad m => Db.Category -> I.Splice m
renderCategories (Db.Category catid catname catdesc) =
I.runChildrenWith [ ("categoryId", return $ X.Element "a"[("href", "http://localhost")] $ X.TextNode (T.pack $ show catid))]
However I am encountering two errors:
Couldn't match type `X.Node' with `[X.Node]'
Expected type: I.Splice m
Actual type: heist-0.11.1:Heist.Types.HeistT m m X.Node
In the expression:
return
$ X.Element "a" [("href", "http://localhost")]
$ X.TextNode (T.pack $ show catid)
and
Couldn't match expected type `[X.Node]' with actual type `X.Node'
In the return type of a call of `X.TextNode'
In the second argument of `($)', namely
`X.TextNode (T.pack $ show catid)'
I do not really understand these errors at the moment and any help is appreciated.
Working function for both returning the link and normal text:
renderCategories :: Monad m => Db.Category -> I.Splice m
renderCategories (Db.Category catid catname catdesc) =
I.runChildrenWith [( "categoryId", return $ [X.Element "a" [("href", T.concat $ ["http://localhost:8000/thread_home?cateid=", T.pack $ show catid] )] [X.TextNode (T.pack $ show catid)] ] )
, ("categoryName", I.textSplice catname)
, ("categoryDesc", I.textSplice catdesc)]
The behavior you are seeing is exactly what is intended. The reason you are having problems is because you're using runChildrenWithText
which is a higher level function designed for situations where you are returning text nodes. It is meant for when you want that actual text on your page. What you are seeing is the correct way to achieve that.
A splice is a computation that returns a list of nodes.
type Splice n = HeistT n n [Node]
Node
is a representation of the DOM as Haskell types, so if you want to return a link, you should do something like this:
return $ [Element "a" [("href", "http://localhost")] [TextNode (T.pack $ show catid)]]
To use this kind of a splice, you'll need to use runChildrenWith
instead of runChildrenWithText
.
If this manual creation of Node
s seems ugly to you, there's also a more convenient option. If you import the module Text.Blaze.Renderer.XmlHtml, you'll find functions there that let you generate Node
trees using blaze-html syntax.