wiki:NagareTutorial4

Version 1 (modified by jlcarre, 8 years ago) (diff)

--

Nagare Tutorial, learning concepts

One interesting thing in Nagare is the ability to reuse simply your existing code.

Part3, re-use components

  1. An application with 2 counters:

Move app.py module to counter.py and create a new one with the following code:

from counter import Counter

class App(object):

    def __init__(self):
        self.counter1 = component.Component(Counter())
        self.counter2 = component.Component(Counter())

     #
     @presentation.render_for(App)
     def render(app, h, *args):
         h << self.counter1
         h << h.hr
         h << self.counter2

         return h.root

# factory
app = App

app is now an application with two Nagare components. These components wrap counters object, each one as its own state.

  1. Multiview

When you define browsing in a Nagare application, you should not see your application as a list of HTML pages reachable through URL, but as component tree that is modified and rendered.

For example, change the way to display counter1, in counter.py module, we bind a new view to the Counter class:

@presentation.render_for(Counter, model='freezed')
def render(counter, h, *args):
    h << h.h1(counter.val)
        return h.root

This view is registered as the 'freezed' view for a counter. And then, we tell counter1 to use freeze as its default view:

...
class App(object):

    def __init__(self):
        self.counter1 = component.Component(Counter(), model='freeze')
        self.counter2 = component.Component(Counter())
...

The application displays two counters with two different views. That is how Nagare has multiple view for a component.

  1. Browsing

Now, we would like to switch between view at runtime. To achieve that, we just need to replace the inner object of counter1 with the exact same object but a different model, it is done this way:

...
self.counter1.becomes(self.counter1, model='freeze')
...

That can be done with a callback registered in Counter default view (you have to remove the model keyword when creating counter1 too):

@presentation.render_for(Counter)
def render(counter, h, comp, *args):
    h << h.div('Value: ', counter.val)

    h << h.a('++').action(counter.increase)
    h << '|'
    h << h.a('--').action(counter.decrease)
    h << h.br
    h << h.a('freeze').action(lambda: comp.becomes(counter, model='freeze')
    return h.root

As you can see one of the optional arguments is comp, that is the Nagare component where as counter is the inner object that is wrapped. Here we use becomes to change the model, but becomes can actually change the whole inner object by a new one. you can find an example of how to use this to create a tabbed menu on this blog post .

  1. Going async

With Nagare, a component can be asked to render synchronously (default) or asynchronously without any change in component code.

In fact, the code to add counter view in DOM tree:

...
h << self.counter1
...

Is a shortcut for:

...
h << self.counter1.render(h, model=None)
...

h is the renderer which is synchronous by default. This renderer can be replaced by an asynchronous one:

from nagare.namespaces import xhtml
...
h << self.counter1.render(xhtml.AsyncRenderer(h), model=None)
...

This way counter1 is rendered asynchronously whereas counter2 is rendered synchronously. When you look a the generated html page you can see that for counter1 links a disabled (attibute href set to #) and javascript is added (attribute onclick is added and calls nagare_getAndEval function.

That's all folks, if you'd like to learn more, feel free to join us on IRC Freenode #nagare, Nagare blog and Nagare users group .

Previous