[IMP] merged documentation in the wiki with web client documentation

bzr revid: nicolas.vanhoren@openerp.com-20121108112356-zl99m2qod2e1fdk8
This commit is contained in:
niv-openerp 2012-11-08 12:23:56 +01:00
parent 7c3d2a37b5
commit 7ec48c2d26
3 changed files with 118 additions and 0 deletions

View File

@ -11,12 +11,15 @@ Contents:
.. toctree::
:maxdepth: 1
presentation
changelog-7.0
async
rpc
widget
qweb
search-view
list-view

View File

@ -0,0 +1,36 @@
Presentation
============
Prerequisites
-------------
Prerequisites to code addons for the OpenERP Web Client:
- Html
- Css
- Javascript
- jQuery
Once you know all this, that's only the beginning. Most usages of Javascript/jQuery are small hacks to make a web page nicer. The OpenERP Client Web is different: it's a web application, not a web site. It doesn't have multiple pages generated by a server side code. Only one unique empty page is loaded and all the html is generated by Javascript code, the page is never reloaded. If you never developed that kind of application you still have lot of good practices to learn.
Recommendations
---------------
First, here are the 5 golden rules when you create web 2.0 applications:
* **Do not use ids**. Html ids are evil, the key anti-feature that makes your components non-reusable. You want to identify a dom part? Save a jQuery object over that dom element. If you really need to use ids, use _.uniqueId(), but 99% of the time you don't need to, classes are sufficient.
* **Do not use predictable css class names** like "content" or "navigation", ten other developers will have the same idea than you and there will be clashes. A simple way to avoid this is to use prefixes. For example, if you need a css class for the button named "new" that is contained in the form view which is itself contained in the OpenERP application, name it "oe-form-view-new-button".
* **Do not use global selectors** like *$(".my-class")*, you never know if your component will be instantiated multiple times. Limit the selector with a context, like *$(".my-class", this.$el)*.
* As a general advice, **Never assume you own the page**. When you create a component, it is never unique and is always surrounded by a bunch of crazy html. You have to do with it.
* **Learn how to use jQuery's deferreds** [1]_. That concept may seem over-complicated, but the experience tell us that it is nearly impossible to create big-size javascript applications without that.
More recommendations related to the specific case of the OpenERP Web Client:
* Your components should inherit from the *Widget* class.
* Use QWeb templates for html rendering.
* Use *Widget* 's methods (*appendTo*, *replace*,...) to insert your component and its content into the dom.
* All css classes should have the prefix *oe-* .
* Functions that call rpc() should return a deferred, even if it calls it indirectly. So a function that calls a function that calls a function that calls rpc() should return a deferred too.
.. [1] http://api.jquery.com/category/deferred-object/

79
addons/web/doc/qweb.rst Normal file
View File

@ -0,0 +1,79 @@
QWeb Cookbook
=============
QWeb is the template engine used by the OpenERP Web Client. It is a home made engine create by OpenERP developers. There are a few things to note about it:
* Template are rendered in javascript on the client-side, the server does nothing.
* It is an xml template engine, like Facelets_ for example. The source file must be a valid xml.
* Templates are not interpreted. There are compiled to javascript. This makes them a lot faster to render, but sometimes harder to debug.
* Most of the time it is used through the Widget class, but you can also use it directly using *openerp.web.qweb.render()* .
.. _Facelets: http://en.wikipedia.org/wiki/Facelets
Here is a typical QWeb file:
::
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="Template1">
<div>...</div>
</t>
<t t-name="Template2">
<div>...</div>
</t>
</templates>
A QWeb file contains multiple templates, they are simply identified by a name.
Here is a sample QWeb template:
::
<t t-name="UserPage">
<div>
<p>Name: <t t-esc="widget.user_name"/></p>
<p>Password: <input type="text" t-att-value="widget.password"/></p>
<p t-if="widget.is_admin">This user is an Administrator</p>
<t t-foreach="widget.roles" t-as="role">
<p>User has role: <t t-esc="role"/></p>
</t>
</div>
</t>
*widget* is a variable given to the template engine by Widget sub-classes when they decide to render their associated template, it is simply *this*. Here is the corresponding Widget sub-class:
::
UserPageWidget = openerp.base.Widget.extend({
template: "UserPage",
init: function(parent) {
this._super(parent);
this.user_name = "Xavier";
this.password = "lilo";
this.is_admin = true;
this.roles = ["Web Developer", "IE Hater", "Steve Jobs Worshiper"];
},
});
It could output something like this:
::
<div>
<p>Name: Xavier</p>
<p>Password: <input type="text" value="lilo"/></p>
<p>This user is an Administrator</p
<p>User has role: Web Developer</p>
<p>User has role: IE Hater</p>
<p>User has role: Steve Jobs Worshiper</p>
</div>
A QWeb template should always contain one unique root element to be used effectively with the Widget class, here it is a *<div>*. QWeb only react to *<t>* elements or attributes prefixed by *t-*. The *<t>* is simply a null element, it is only used when you need to use a *t-* attribute without outputting an html element at the same time. Here are the effects of the most common QWeb attributes:
* *t-esc* outputs the result of the evaluation of the given javascript expression
* *t-att-ATTR* sets the value of the *ATTR* attribute to the result of the evaluation of the given javascript expression
* *t-if* outputs the element and its content only if the given javascript expression returns true
* *t-foreach* outputs as many times as contained in the list returned by the given javascript expression. For each iteration, a variable with the name defined by *t-as* contains the current element in the list.