This time the form generator does not generate a page refresh each time that a option on the menu is pressed
. The exception of this rule is when a new widget is added to the page, since in this case it is necessary to store the new version of the form generated and update the edition with the new version. As a rule, ever that an option on a widget modify the presentation of other widget, it is necessary a page navigation. Unless we want to use push widgets (see Push Samples on the demos).
To see a detailed explanation of how it works follow the the explanations fo the two previous versions of the form generator:
Form generator with undo
If you want to force a page navigation inside a autoRefresh widget, add to the option an atribute noAutoRefresh
Also, the generated form present the results in the page with no page refresh, by using witerate and dField
See the previous examples for a detailed explanation of the rest of the code.
The first is done using autoRefresh in the menu. In fact there are two nested auto refreshes. This time chooseWidget has an autoRefresh :
chooseWidget= autoRefresh $
(p $ a ! At.class_ "_noAutoRefresh" ! At.href "/" $ "home/reset" )
And as in the previous version, chooseWidget call getOptions for generating combo boxes and checkboxes. getOptions now also has a autoRefresh:
getOptions pf = autoRefresh $ do
(op,_) <- (,)<$> getString Nothing <! [("size","8"),("placeholder","option")]
Otherwise, the code of this new version is almost the same than in the previous ond, with the above exceptions and the fact that now a new option has been added to chooseWidget. That is a widget that has a button and show the results. In the previous versions, the button is added after the edition. now it can be added as part of the edition process, but it is also automatically added at the end of the edition if that has not been done by the user:
The genElem for the new result widget is:
genElem ShowResults = Result <$> do
xs <- getSessionData `onNothing` return 
pageFlow "" (allOf (map genElem (xs \\ [ShowResults]))) <|> return 
`wcallback` (\r -> pageFlow "button" $
**> h2 "Result:"
++> dField(wraw $ b << show r)
**> return ())
It gets the identifiers of the widgets of the page (Line 1). Then evaluate the rest of the widgets except itself (Line 2).
Then it drops out the rendering of these widgets and get only the result, and present it below the submitButton that triggers the form submit in the first place when it is rendered. That is done in the wcallback code. wcallback drops out the rendering generated before him.
Another detail: all the presentations of the genElem elements have a dField prefix:
genElem Intv = Result <$> dField (getInt Nothing)
genElem Stringv= Result <$> dField (getString Nothing)
genElem TextArea= Result <$> dField (getMultilineText "")
That is because now the presentation of the form results and the widget updates and validation mesages is trough AJAX, with no page navigation. dField tell MFlow about which portions of the page will be refreshed this way.
generateForm title xs=
input ! At.type_ "hidden" ! name "p0" ! value "()"
++> (div ! At.id "p0"
<<< input ! type_ "hidden" ! name "p0" ! value"()"
++> ( template title . pageFlow "" . witerate . pageFlow "" . allOf $ map genElem xs))
These are the two main changes in relation with the previous version.
Also, the form generated display the result of the inputs, the validation and the content without changing the whole page. Thus the layout and the text can be as complicated and extensive as we like since there would be no penality for the dimamic changes.
In fact we have created a general application for the creation of active web pages. Since the menu can contain wathever widget we like, including active widgets, links to other dynamically generated pages and so on.