MFlow  Create and maintain dynamic Web applications as easy and fast as console applications
Thou shall not write request handlers
 This release: 11/06/2014.  agocorona@gmail.com (@agocorona) <>< . issues & bugs .  Mflow Source code,     source code of this site




More tools for single page apps: witerate and dField

witerate,  is a new primitive that permits to iterate the presentation of data and/or input fields and widgets within an web page that does not change. The placeholders are created with dField.  Both are widget modifiers: The latter gets a widget and create a placeholder in the page that is updated via ajax. The content of the update is the rendering of the widget at each iteration. The former gets a widget which contains dField elements and permit the iteration. Whenever a link or a form within the witerate widget is activated, the result is the placeholders filled with the new  html content.  This content can be data, a input field, a link or a widget. No navigation happens.

This permits even faster updates than autoRefresh.  since the latter refresh the whole widget and it does not permits modifications of the layout at runtime. When edTemplate or template is used on top of witerate, the result is editable at runtime, and the span placeholders generated, that are updated via ajax can be relocated within the layout of the template. 

Additionally, contrary to some javascript frameworks, the pages generated with this mechanism are searchable by web crawlers.

This example below, taken from the runtime templates example, shows how template, witerate and dField work together. The example iterates the presentation of a list of results fby displaying four of them each time. The list can be navigated forward and backward. (see the example  running and the full source code here).

The snippet is as such
page $ edTemplate "edituser" "enterallnames"  $ pageFlow "iter" $ witerate $ do
              NextReg ind <- getSessionData `onNothing` return (NextReg 0)
              dField (getData ind     len allnames) <++ br
              dField (getData (ind+1) len allnames) <++ br
              dField (getData (ind+2) len allnames) <++ br
              dField (getData (ind+3) len allnames) <++ br
              setSessionData . NextReg $ next ind len
              r <- wlink True  << b << "next" <++ fromStr " "
                    <|>
                    wlink False << b << "prev"
              when (r== False) $ setSessionData . NextReg $  prev ind len
The pageFlow call has been added in order to fix the naming sequence of the ids in the widget. This way the placeholder ids generated will not change if the widget is relocated, since pageFlow assures that the generated ids will stay the same. This is important since the template, that will contain the placeholders is static.
The HTML code generated, besides the javascript necessary for the dynamic refreshing of the placeholder is:
<div id="p0iter"> <span id="p1iter">a</span><br> <span id="p2iter">b</span><br> <span id="p3iter">c</span><br> <span id="p4iter">d</span><br> <a href="/noscript/templat....stnames/itertrue"><b>next</b></a> <a href="/noscript/templa....stnames/iterfalse"><b>prev</b></a> </div> 
The four dField  elements creates four span placeholder elements labeled with ids. However, this HTML can be edited. edTemplate adds a wysiwyg editor when the user is "edituser" in this case. The modified template becomes the new presentation of the widget.


You see in the image that the code has  a title and dot decoration elements that are not part of the code. They have been added with the WYSIWYG editor.  

Here the sequence index is set using session data . the next and prev links are inside the block managed by
witerate. When the links are pressed, the next iteration will present the next four elements.

Note that the template can be edited to generate more radical changes in the presentation of the data. As long as the placeholders are maintained, any kind of change is possible. 
Note that if a fifth dField in the code and a new placeholder is  added in the HTML template, the application will work fine presenting five elements.

This mechanism is not only for data presentation, but also for input widgets. The same example includes a page for entering registers. There is a counter of registers added that is updated automatically. 

The source code is:
              pagem  $ edTemplate "edituser" "enterallnames"
                     $ pageFlow "enter" $ witerate (
                        do  name <- dField (getString Nothing `validate` jsval)
                                      <** submitButton "ok" <++ br
                            -- store the register in the cache
                            -- Later will be written by the default persistence automatically
                            liftIO . atomically . newDBRef $ MyData name   
                        **> do
                             n <- countRegisters
                             dField (wraw $ b << show n) <++ fromStr " registers added ")
                   **> wlink () << b << "exit"

See the page and the full source code here
One dField encloses the getString input. The other encloses the number of registers entered.  If the getString does not validate the input (in the example, it validates for a name with less than 10 characters) the validation message appears and the execution is interrupted (that is how the View monad works, see this). If it passes the validation, a new database register is created with newDBRef.  In any case, the applicative operator **>  executes the second element which count the registers and update the number of elements in the template.  
A further optimization would be to substitute **>  by *>, since the second does not execute the second term if the first does not execute sucessfully, so when a validation failure occur or the field is empry, we avoid updating the number of registers, but for editing the template the first time it is good to have the both parts of the widget rendered fully.
The source code produced is
<div id="p0enter">
    <form action="/noscript/wiki/templates/runtimetemplates/newname" method="post">
       <span id="p1enter"><input type="text" name="p2enter" value=""></span>
       <input type="submit" name="p3enter" value="ok">
       <span id="p4enter"><b>36</b></span> registers added 
     </form>
</div> 
<a href="/noscript/wiki/templates/runtimetemplates/newname/enter()"><b>exit</b></a>
   
The template has been edited to include added literals and formatting. A title and some line breaks

See the page and the full source code here

comments powered by Disqus