Using checkboxes with Suave.Io
The Suave.IO web library for F# adopts two ways of rendering html.
By using Suave.form/Suave.html the page is represented as a native F# list, which basically consists in html elements, or nodes, and forms which are defined by specific records. Invalid html page is impossible in this way because the syntax check is strict.
Suave.dotliquid instead adopts old fashion html text + some variable substitution at server side.
However, Suve.Form/Suave.html misses support for checkboxes yet.
We can't do the following stuff to render a checkbox form, whereas we can do if we used other supported types for html widget (see https://theimowski.gitbooks.io/suave-music-store/content/en/form_module.html)
Defining the form.
type UserEdit = {
Enabled: bool
CanVoidOrder: bool
CanManageAllorders: bool
CanChangeThePrices: bool
}
let userEdit: Form
Form ( [
Checkbox ((fun f -> <@ f.Enabled @>), [])
Checkbox ((fun f -> <@ f.CanVoidOrder @>), [])
Checkbox ((fun f -> <@ f.CanManageAllorders @>), [])
Checkbox ((fun f -> <@ f.CanChangeThePrices @>), [])
],[])
REnd the form in the ui:
renderForm
{ Form = Form.userEdit
Fieldsets =
[ { Legend = "Modify user"
Fields =
[
{ Label = "enabled"
Html = Checkbox (fun f -> <@ f.Enabled @>) ["value", true] )
}
]
[
{ Label = "can manage all orders"
Html = Checkbox (fun f -> <@ f.CanVoidOrder @>) ["value", true] )
}
]
[
{ Label = "can void order"
Html = Checkbox (fun f -> <@ f.CanManageAllorders @>)["value", true] )
}
]
[
{ Label = "can change the prices"
Html = Checkbox (fun f -> <@ f.CanChangeThePrices @>)["value", false] )
}
]
]
SubmitText = "modify" }
This is probably how it will be possible in the future, but is not possible yet. bool and chekbox are not supported.
So I needed dotliquid templating to overcome, where any html is valid, because it is actual html plain text code.
A recap of checkboxes in html:
<form method="post">
<input name="myName1" nbsp="" type="checkbox" />myValue1</input>
<input name="myName2" nbsp="" type="checkbox" />myValue2</input>
<input type="submit" update="" />
In posting this form, it evaluates myName1 to myValue1 if checked, and myValue2 to myValue2 if checked.
So what I we can do to use dotliquid forms for checkboxes is using option types. I don't really care about the value passed, but only if they are passed or not. For that reason option types fit the purpose.
type UserEdit = {
Enabled: string option
CanVoidOrder: string option
CanManageAllorders: string option
CanChangeThePrices: string option
}
//wa can leave the following empty (no validators an so on)..
let userEdit: Form
Form ( [
],
[])
So the code in App.fs would be like:
type modelForLiquid = {name: string} // how to pass parameters to the template, if needed
let manageUser (Db.user) =
choose [
GET >=>
let o = {name = "yourname"}
DotLiquid.page("template.html") o
POST >=>
bindToForm Form.userEdit (fun form ->
let ctx = db.getContext()
let isEnabled = form.Enabled.isSome
let canVoidOrder = form.CanVoidOrder.isSome
......
Db.UpdateUser user.UserId isEnabled canVoidOrder ... ctx
]
Something similar should be needed for radiobuttons.
What we need to be sure about is that we use POST rather than GET in the form, and how html pass the parameters. Basically they are a list of name value pairs.
The POST part of our code in the controller (App.fs usually) can handle them in a straightforward way as seen in the code above.
Can be good to know, just in case ;-)
No comments:
Post a Comment