Reputation: 3747
The following refer to Odoo v9 enterprise version.
Task: When opening the timesheet form from Main Menu -> timesheets, send a .click() event on the Details tab so that the details tab opens.
Problem: When I use the selector to select the element I get nothing in return. ( I have confirmed that the selector I use is correct for the dom element that interests me)
In accordance with the official documentation for the odoo web client, I have extended the web.FormView
widget, and overriden it's start method. From taking a look at the examples, it seems to me that when the start
method is invoked the DOM
has already been rendered.
When I use console.log(this)
from within the start method I can see an object that has the DOM in the $el
variable.
I am trying to make a selection using a jquery selector but I am unable to get my object.
My custom widget js:
odoo.define('t9397.form_override', function(require) {
"use strict";
var core = require('web.core');
var web_widget = require('web.FormView')
var FormWidgetOverride = web_widget.extend({
start : function(record) {
console.log('overridden')
console.log(this)
this.$("a[data-toggle='tab']:contains('Details')").click()
$("a[data-toggle='tab']:contains('Details')").click()// trying both
return this._super()
}
})
core.view_registry.add('form', FormWidgetOverride);
});
The DOM
object I want to send a click event to:
< a data-toggle="tab" disable_anchor="true" role="tab" href="#notebook_page_22">Details< /a >
My knowledge of promises, Jquery
, and especially the web client of odoo
is somewhat rather limited. Any help will be much appreciated.
Upvotes: 0
Views: 1755
Reputation: 467
start()
may perform rendering tasks including asynchronous procedures, so it's necessary to wait while it finishes it's execution. As per documentation:
A widget is not guaranteed to work correctly until its start() method has finished executing. The widget's parent/creator must wait for a widget to be fully started before interacting with it.
Normally, start should return a Deferred() jQuery object, and if start() itself is implemented properly in super, than you can wait it using the Deferred object received from it's call:
First case to use for a simple code as yours:
start : function() {
var sup_ready = this._super();
sup_ready.done(function(){
//your code:
console.log('overridden');
console.log(this);
this.$("a[data-toggle='tab']:contains('Details')").click();
$("a[data-toggle='tab']:contains('Details')").click(); // trying both
});
return $.when( sup_ready );
}
});
Second case, to use for asynchronous procedures and more complicated code:
start : function() {
var sup_ready = this._super();
var me_ready = $.Deferred();
. . .
sup_ready.done(function(){
. . .
. . .
//finally Resolve or Reject your deferred object:
//Resovle:
me_ready.resolve(); //use it if all go ok
// *OR* Reject (in case something go wong) to indicate failure:
// me_ready.reject();
});
. . .
return $.when( sup_ready, me_ready );
});
Note that I put me_ready.resolve()
inside sup_ready.done()
but it is NOT absolutely necessary and in general it may be other way around i.e. you can Reject or Resolve me_ready
outside of this sup_ready.done()
, you can resolve or reject me_ready
deferred object anywhere in your code.
The second case above does not apply to your current issue, but it's a pitfall to avoid in the future, just in case.
As an alternative to the start()
way you choose, consider also an events
property of the widget and check if you can apply it to your case...
Upvotes: 1