The overall process for using a widget is:
- Create a single instance of the widget (or compound widget), to be used throughout the program
- Pass this instance from the controller to a template
- In the template, call the widget to display it. Parameters can be passed at display time, and this is commonly used for the value of the widget.
For this tutorial we are going to create a star rating widget which utilizes ajax to store the user response and return a request back to the browser to update the user’s view.
Before we start using our widget we need to install it. For the time being, this widget has not been released to pypi so we need to install from the trunk.
import the widget into your project
from tw.rating import Ratings
Create the widget inside your controllers definitions.
my_rating = Rating(id='my_rating', action='rating', label_text='')
Create a new controller method to share our widget
@expose('genshi:myproject.templates.widget') def testing(self, **kw): tmpl_context.widget = my_rating return dict()
In the template, call the widget to display it.
Here is what the resulting widget looks like:
Now, star widget doesn’t do any good without some kind of server interaction. For this tutorial we are going to just simply keep track of the average as the user’s click the stars in memory. This could be later modified to support some sort of crafty database interaction.
First, lets initialize our “database” of star-click averages:
sum_ratings = 0 num_ratings = 0
Then we make a newly exposed method which shares the same name as the “action” which is sent into the Widget.
@expose('json') def rating(self, rating): global sum_ratings global num_ratings rating = int(rating) sum_ratings += rating num_ratings += 1 rating = float(sum_ratings)/float(num_ratings) return dict(num_ratings=num_ratings, avg_rating=rating)
Now, this is not a terribly interesting example until you start to handle the response that comes back. To do that, you just add an “on_click” parameter to the widget definition.
First we modify the template to give a place to hold the data that comes back from the server.
rating = Rating(id='my_rating', action='rating', label_text='', on_click="""$('#avg_stars').textContent='The average is now: '+response.avg_rating""")