Search code examples
javascriptpythonodooqwebodoo-13

Best way to dynamically re-render a template in Odoo 13


I'm trying to re-render a template after something has changed on a QWeb webpage (onchange event on an element) with a set of new data. I'm used to working with JS frameworks like Vue and I have a problem with updating values on the QWeb webpage.

I don't see a clear explanation of how to do this in the docs and while searching the internet and the source code I saw many different answers presumably for different Odoo versions. But both do not work.

I saw 2 main ways of doing this:

  • inside Python controller
  • inside JavaScript widget

And inside Python controller I saw different syntaxes and I'm not sure when to use what. For example:

# First method
@http.route('/test', type='json' auth='user', website=True)
def object(self, **kw):
    return http.request.render('template.name', {
        'value': kw.get('value', 0),
    })

# Second method
@http.route('/test', type='json' auth='user', website=True)
def object(self, **kw):
    return request.env['ir.ui.view'].render_template('template.name', {
        'value': kw.get('value', 0),
    })

Is there any difference between them? Also for some reason, it does not render anything while calling it from JavaScript and using type='json'. It only renders when I use type='http' and go there directly from the browser - and I need a JS event to cause re-rendering.

I also saw that it is possible to render template from JavaScript like this:

_onChange: function () {
    console.log("something changed!");

    return this._rpc({
        route: '/test',
        params: {
            value: 1,
        }
    }).then(function (data) {
        this.$el.html(QWeb.render('template.name', {
            value: data.value
        }));
    });
},

But for some reason I get error Template 'template.name' not found.

I'm pretty stuck at this point and don't know what to do next. I can send data to and from the controller. But I have no idea how to update variables on the QWeb. Please help.


Solution

  • I managed to render template by using second method in python:

    return request.env['ir.ui.view'].render_template("konfigurator.listing", {
                'test': kw.get('value', 0),
    })
    

    And then use returned value inside JS in self.$el.html(data):

    return this._rpc({
        route: '/calculate_order',
        params: {
            value: 4,
        }
    }).then(function (data) {
        self.$el.html(data);
    });
    

    But now I think it is much better to change this approach and use JavaScript to render content dynamically instead of rendering whole template again.