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




Callbacks to implement a counter

A callback is an action that is executed when a widget receives valid input. MFlow has 'waction's (see this example)  

waction :: (FormInput view, Monad m) => View view m a -> (a -> FlowM view m b) -> View view m b

They execute a sequence of pages when invoked. When the flow action is finished,  the execution return to the original page, to execute further actions or to return the result of the page form. A waction takes complete control of the navigation.

But it would be nice to execute a flow in each widget in the page simultaneously. Each widget in the page can have dynamic behaviors without using JavaScript. Seaside is an incredible web framework developed in a very nice language: Smalltalk. It has such functionality.

wcallback does that:

wcallback :: Monad m => View view m a -> (a -> View view m b) -> View view m b

it does change the rendering of a particular widget by other rendering when the widget is validated.

In this example (see code below) wcallback call the same counter recursively when one of the two links are pressed, with the parameter increased or decreased.

This seaside widget counter is replicated five times in the same page:

http://www.seaside.st/about/examples/multicounter

The multicounter example in this site reuses this very same widget. 

unlike the multicounter example, this example does not use autoRefresh, therefore the whole page is refreshed. Note that the counter state is reflected in the URL. Each counter state has its own REST URL.
"

Running example

(in the light red box):

This example emulates the

seaside counter example

This widget uses a "callback" that permit an independent

execution flow for each widget. Multicounter instantiate various counter widgets

But while the seaside case the callback update the widget object, in this case

the callback recursively generates a new copy of the counter with the value modified.

0

++ --

exit



Source code:

{-# OPTIONS -XCPP -XDeriveDataTypeable #-} 
module Counter ( counter, counterWidget) where
import Data.Monoid
import Data.String
import Data.Typeable

-- #define ALONE -- to execute it alone, uncomment this

#ifdef ALONE
import MFlow.Wai.Blaze.Html.All
main= runNavigation "" $ step counter
#else
import MFlow.Wai.Blaze.Html.All hiding(page)
import Menu
#endif

attr= fromString 
text= fromString

counter= do
   page  $ explain
       ++> pageFlow "c" (counterWidget 0)
       <++ br
       <|> wlink () << p << "exit"
   where
   explain= do   -- using the blaze-html monad
        p << "This example emulates the"
        a ! href (attr "http://www.seaside.st/about/examples/counter") << "seaside counter example"
        p << "This widget uses a \"callback\" that permit an independent"
        text " execution flow for each widget. "
        a ! href (attr "/noscript/multicounter") << "Multicounter"
        text " instantiate various counter widgets"
        p << "But while the seaside case the callback update the widget object, in this case"
        p << "the callback recursively generates a new copy of the counter with the value modified."

counterWidget n=
      (h2 << show n
       ++> wlink "i" << b << " ++ "
       <|> wlink "d" << b << " -- ")
      `wcallback`
        \op -> case op  of
          "i" -> counterWidget (n + 1)
          "d" -> counterWidget (n - 1)

comments powered by Disqus