Nagare Tutorial, learning concepts#
A major feature of Nagare is its ability to easily reuse existing code.
Part 4. Re-use components#
An application with 2 counters:
Rename the
app.pymodule tocounter.pyand create a newapp.pyfile with the following code:from nagare import component, presentation 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(self, h, *args): h << self.counter1 h << h.hr h << self.counter2 return h.root # factory app = App
appis now a composite application with two independentCountercomponents, each with its own state.Don’t think about a Nagare application as a set of HTML pages reachable though URL. But instead model it as a tree of components which is modified then rendered when navigating.
Multiviews
Several views can be bound to a component. For example, here we add a new
freezednamed view to ourCountercomponents:@presentation.render_for(Counter, model='freezed') def render(counter, h, *args): return h.h1(counter.val)
Then, we can tell
counter1to use thisfreezedview as its default one:... class App(object): def __init__(self): self.counter1 = component.Component(Counter(), model='freezed') self.counter2 = component.Component(Counter()) ...
The application now displays two counters with two different views
Navigating
Now, we would like to switch between views at runtime. To achieve that, we just need to replace the inner object of the
counter1component with the exact same object but with a different model:... self.counter1.becomes(self.counter1, model='freezed') ...
That can be done via a callback registered in the
Counterdefault view:@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(comp.becomes, model='freezed') return h.root
As you can see one of the optional arguments is
comp, the component wrapping thecounterobject.In this example we used the
becomes()method to only change the default view of a component. Butbecomes()can actually swap the whole inner object to a new one. This is in fact how navigating into an application is done in Nagare.Going async
With Nagare, a component can be rendered synchronously (default) or asynchronously without any change to its code.
First, note the statement we used to add a counter view to the DOM tree:
... h << self.counter1 ...
is in fact a shortcut for:
... h << self.counter1.render(h) ...
Using this full method call, we can now create and pass an asynchronous renderer instead of
h:... h << self.counter1.render(h.AsyncRenderer()) ...
This way
counter1is rendered asynchronously whereascounter2is rendered synchronously. When you look at the generated html page you can see that forcounter1links are disabled (attributehrefset to#) and some javascript is added (attribute`onclickadded with a call to thenagare_getAndEval()javascript function).