[FIX] web_editor: fix the linktools editing behaviour

Steps to reproduce:

- Go to website (Homepage) > Switch to "Edit" mode.
- double-click the "Contact Us" button in the header or keep clicking it
many times > Traceback: Cannot read properties of undefined (reading
'find')...

After converting the `linktools` widget to Owl in [1], the DOM element
of the component [2] was retrieved in an async process after it was
mounted, (some legacy code can trigger the instantiation of the
`linktools` when its parent component is not in the DOM and
`this.linkComponentWrapperRef.el` won't be returned, see: `Link` >
`onMounted`).

When double-clicking the link, This implementation will lead to a race
condition where the `onWillUpdateProps()` (mainly triggered by the click
to focus the URL input...) will try to access the DOM element from [2]
before being correctly set in `onMounted()`.

The goal of this commit is to fix this behaviour by simply waiting for
`onMounted` changes to be done before doing any adaptation on the
`linktools` DOM.

[1]: https://github.com/odoo/odoo/commit/d7245d2abf528d093226c80e40975e63d61e8997

opw-3706902

closes odoo/odoo#155418

Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
Mehdi Outagant (MOU)
2024-03-08 12:48:57 +00:00
parent 5d6dd7f0a0
commit cf7c78c9cb
2 changed files with 9 additions and 3 deletions
@@ -48,6 +48,9 @@ export class Link extends Component {
];
setup() {
this.state = useState({});
// We need to wait for the `onMounted` changes to be done before
// accessing `this.$el`.
this.mountedPromise = new Promise(resolve => this.mountedResolve = resolve);
onWillStart(() => this._updateState(this.props));
let started = false;
@@ -82,8 +85,10 @@ export class Link extends Component {
this.$el.find('[name="url"]').on('change', this._onURLInputChange.bind(this));
await this.start();
this.mountedResolve();
});
onWillUpdateProps((newProps) => {
onWillUpdateProps(async (newProps) => {
await this.mountedPromise;
this._updateState(newProps);
this.state.url = newProps.link.getAttribute('href') || '';
this._setUrl({ shouldFocus: newProps.shouldFocusUrl });
@@ -182,7 +187,7 @@ export class Link extends Component {
* Focuses the url input.
*/
focusUrl() {
const urlInput = this.linkComponentWrapperRef.el.querySelector('input[name="url"]');
const urlInput = this.$el[0].querySelector('input[name="url"]');
urlInput.focus();
urlInput.select();
}
@@ -52,7 +52,8 @@ export class LinkTools extends Link {
setup() {
super.setup(...arguments);
onWillUpdateProps((newProps) => {
onWillUpdateProps(async (newProps) => {
await this.mountedPromise;
this.$link = newProps.link ? $(newProps.link) : this.link;
this._setSelectOptionFromLink();
this._updateOptionsUI();