[IMP] developer: document how to create standalone owl apps
Since we've introduced Owl, developers want more and more to create
standalone Owl applications outside of the webclient. This commit
introduces a How-to for doing just that.
task-3580007
closes odoo/documentation#6553
X-original-commit: 1fc36ffa82
Related: odoo/odoo#143073
Signed-off-by: Samuel Degueldre (sad) <sad@odoo.com>
This commit is contained in:
parent
4219829976
commit
16e10c53db
@ -12,6 +12,7 @@ How-to guides
|
|||||||
howtos/javascript_field
|
howtos/javascript_field
|
||||||
howtos/javascript_view
|
howtos/javascript_view
|
||||||
howtos/javascript_client_action
|
howtos/javascript_client_action
|
||||||
|
howtos/standalone_owl_application
|
||||||
howtos/web_services
|
howtos/web_services
|
||||||
howtos/company
|
howtos/company
|
||||||
howtos/create_reports
|
howtos/create_reports
|
||||||
@ -42,6 +43,12 @@ How-to guides
|
|||||||
|
|
||||||
Learn how to create client actions in the Odoo JavaScript web framework.
|
Learn how to create client actions in the Odoo JavaScript web framework.
|
||||||
|
|
||||||
|
.. card:: Create a standalone Owl application
|
||||||
|
:target: howtos/standalone_owl_application
|
||||||
|
|
||||||
|
Learn how to create a public-facing Owl application outside of the web client using a
|
||||||
|
controller and the Odoo JavaScript framework.
|
||||||
|
|
||||||
.. card:: Web services
|
.. card:: Web services
|
||||||
:target: howtos/web_services
|
:target: howtos/web_services
|
||||||
|
|
||||||
|
172
content/developer/howtos/standalone_owl_application.rst
Normal file
172
content/developer/howtos/standalone_owl_application.rst
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
===================================
|
||||||
|
Create a standalone Owl application
|
||||||
|
===================================
|
||||||
|
|
||||||
|
For any number of reasons, you may want to have a standalone Owl application that isn't a part of
|
||||||
|
the web client. One example in Odoo is the self-ordering application, that lets customers order
|
||||||
|
food from their phone. In this chapter we will go into what's required to achieve something like this.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
To have a standalone Owl app, a few things are required:
|
||||||
|
|
||||||
|
- a root component for the application
|
||||||
|
- some setup code to start the services and mount the component
|
||||||
|
- an assets bundle that contains the setup code
|
||||||
|
- a QWeb view that calls the assets bundle
|
||||||
|
- a controller that renders the view
|
||||||
|
|
||||||
|
1. Root component
|
||||||
|
=================
|
||||||
|
|
||||||
|
To keep things simple, let's start with a very straightforward component that just renders
|
||||||
|
"Hello, World!". This will let us know at a glance if our setup is working.
|
||||||
|
|
||||||
|
First, create the template in :file:`/your_module/static/src/standalone_app/root.xml`.
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
<t t-name="your_module.Root">
|
||||||
|
Hello, World!
|
||||||
|
</t>
|
||||||
|
</templates>
|
||||||
|
|
||||||
|
Then create the JavaScript file for that component in :file:`/your_module/static/src/standalone_app/root.js`.
|
||||||
|
|
||||||
|
.. code-block:: js
|
||||||
|
|
||||||
|
/** @odoo-module */
|
||||||
|
import { Component } from "@odoo/owl";
|
||||||
|
|
||||||
|
export class Root extends Component {
|
||||||
|
static template = "your_module.Root";
|
||||||
|
static props = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
:ref:`Owl components reference<frontend/components>`.
|
||||||
|
|
||||||
|
2. Setting up the environment and mounting the application
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
An Owl application needs an environment, and the Odoo JavaScript framework needs that environment to
|
||||||
|
contain the :ref:`services<frontend/services>`.
|
||||||
|
Starting the services is also required to load the translations, which we need to do before mounting
|
||||||
|
our Owl application, so that we can give Owl a working translation function.
|
||||||
|
|
||||||
|
Create the JavaScript file that will mount the app in :file:`/your_module/static/src/standalone_app/app.js`.
|
||||||
|
|
||||||
|
.. code-block:: js
|
||||||
|
|
||||||
|
/** @odoo-module */
|
||||||
|
import { whenReady } from "@odoo/owl";
|
||||||
|
import { mountComponent } from "@web/env";
|
||||||
|
import { Root } from "./root";
|
||||||
|
|
||||||
|
whenReady(() => mountComponent(Root, document.body));
|
||||||
|
|
||||||
|
|
||||||
|
3. Creating an assets bundle containing our code
|
||||||
|
================================================
|
||||||
|
|
||||||
|
In the manifest of your module, create a new :ref:`assets bundle<reference/assets_bundle>`.
|
||||||
|
It should include the `web._assets_core` bundle, which contains the Odoo JavaScript
|
||||||
|
framework and the core libraries it needs (e.g. Owl and luxon), after which you can have a
|
||||||
|
glob that adds all the files for your application in the bundle.
|
||||||
|
|
||||||
|
.. code-block:: py
|
||||||
|
:emphasize-lines: 9-10
|
||||||
|
|
||||||
|
{
|
||||||
|
# ...
|
||||||
|
'assets': {
|
||||||
|
'your_module.assets_standalone_app': [
|
||||||
|
('include', 'web._assets_helpers'),
|
||||||
|
'web/static/src/scss/pre_variables.scss',
|
||||||
|
'web/static/lib/bootstrap/scss/_variables.scss',
|
||||||
|
('include', 'web._assets_bootstrap'),
|
||||||
|
('include', 'web._assets_core'),
|
||||||
|
'your_module/static/src/standalone_app/**/*',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The other lines are bundles and scss files that are required to make Bootstrap work. They are
|
||||||
|
mandatory, as the components of the web framework use bootstrap classes for their styling and
|
||||||
|
layout.
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
Make sure that the files for your standalone app are only added to this bundle, if you already
|
||||||
|
have a definition for `web.assets_backend` or `web.assets_frontend` and they have globs, make
|
||||||
|
sure these globs don't match the files for your standalone app, otherwise the startup code for
|
||||||
|
your app will conflict with the existing startup code in those bundles.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
:ref:`Module manifest reference<reference/module/manifest>`.
|
||||||
|
|
||||||
|
4. XML view that calls the assets bundle
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Now that we have created our assets bundle, we need to create a
|
||||||
|
:ref:`QWeb view<reference/view_architecture/qweb>` that uses that assets bundle.
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<template id="your_module.standalone_app"><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var odoo = {
|
||||||
|
csrf_token: "<t t-nocache="The csrf token must always be up to date." t-esc="request.csrf_token(None)"/>",
|
||||||
|
debug: "<t t-out="debug"/>",
|
||||||
|
__session_info__: <t t-esc="json.dumps(session_info)"/>,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<t t-call-assets="your_module.assets_standalone_app" />
|
||||||
|
</head>
|
||||||
|
<body/>
|
||||||
|
</html>
|
||||||
|
</template>
|
||||||
|
</odoo>
|
||||||
|
|
||||||
|
This template only does two things: it initializes the `odoo` global variable, then calls the assets
|
||||||
|
bundle we just defined. Initializing the `odoo` global variable is a necessary step. This variable
|
||||||
|
should be an object that contains the following:
|
||||||
|
|
||||||
|
- The CSRF token, which is required to interact with HTTP controllers in many cases.
|
||||||
|
- The debug value, which is used in many places to add additional logging or developer-friendly checks.
|
||||||
|
- `__session_info__`, that contains information from the server that is always needed and for which
|
||||||
|
we don't want to perform an additional request. More on this in the next section.
|
||||||
|
|
||||||
|
5. Controller that renders the view
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Now that we have the view, we need to make it accessible to the user. For that purpose, we will create
|
||||||
|
an :ref:`HTTP controller<reference/controllers>` that renders that view and returns it to the user.
|
||||||
|
|
||||||
|
.. code-block:: py
|
||||||
|
|
||||||
|
from odoo.http import request, route, Controller
|
||||||
|
|
||||||
|
class YourController(Controller):
|
||||||
|
@route("/your_module/standalone_app", auth="public")
|
||||||
|
def standalone_app(self):
|
||||||
|
return request.render(
|
||||||
|
'your_module.standalone_app',
|
||||||
|
{
|
||||||
|
'session_info': request.env['ir.http'].get_frontend_session_info(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Notice how we're giving the template `session_info`. We get it from the `get_frontend_session_info`
|
||||||
|
method, and it will end up containing information used by the web framework, such as the current
|
||||||
|
user's ID if they are logged in, the server version, the Odoo edition, etc.
|
||||||
|
|
||||||
|
At this point, if you open the url `/your_module/standalone_app` in your brower, you should
|
||||||
|
see a blank page with the text "Hello, World!". At this point, you can start actually writing the
|
||||||
|
code for your app.
|
Loading…
Reference in New Issue
Block a user