Hello,
I am fairly new to developing on odoo with owl. I am currently working on a project that use odoo 14 and owl 1.4
I am trying to implement a component that will render in a page renderer by the backend controller. I have this timeline.js file
odoo.define('my_module.My2ChildTimeline', ['web.ajax'], function (require) {
"use strict";
const { Component } = owl;
const { useState, onWillStart, onMounted } = owl.hooks;
const ajax = require("web.ajax");
/**
* ChildTimeline component for displaying a timeline of records related to a specific child.
*/
class ChildTimeline extends Component {
setup() {
...
onWillStart(async () => {
try {
console.info("Loading initial records for ChildTimeline"); // Debug
await this.loadMore();
} catch (error) {
console.error("Error loading initial records:", error);
this.state.loading = false;
}
});
onMounted(() => {
window.addEventListener('scroll', this.onScroll.bind(this));
});
}
onScroll() {
const nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 100;
if (!this.state.loading && this.state.hasMoreRecords && nearBottom) {
this.loadMore();
}
}
async loadMore() {
this.state.loading = true;
const res = await ajax.jsonRpc(`/somewhere`, "call", {
offset: this.state.offset,
limit: this.state.limit,
});
console.info("Loaded more records:", res); // Debug
const tempDiv = document.createElement('div');
tempDiv.innerHTML = res.html;
const newItems = [...tempDiv.children];
const container = this.el.querySelector('.timeline-list');
if (container) {
newItems.forEach(el => container.appendChild(el));
}
this.state.offset += this.state.limit;
this.state.hasMoreRecords = res.has_more_records;
this.state.loading = false;
}
};
ChildTimeline.template = "my_module.My2ChildTimelineComponent";
// Mount immediately when DOM is ready
if (document.getElementById("timeline-root")) {
const dataScript = document.getElementById("timeline-data");
const props = JSON.parse(dataScript.textContent);
owl.mount(ChildTimeline, {
target: document.getElementById("timeline-root"),
props,
});
}
return ChildTimeline;
});
and an xml component
<templates xml:space="preserve">
<t t-name="my_module.My2ChildTimelineComponent" owl="1">
<div class="timeline-list">
<t t-foreach="state.records" t-as="record" t-key="record.id">
<div class="timeline-card d-flex">
<t t-if="record.model == 'sponsorship_gift'">
<My2ChildTimelineRecordGiftComponent record="record"/>
</t>
<t t-elif="record.model == 'correspondence'">
<My2ChildTimelineRecordCorrespondenceComponent record="record"/>
</t>
<t t-else="">
<div>This record type is not supported in the timeline.</div>
</t>
</div>
</t>
<t t-if="state.loading">
<div class="text-center py-2">Loading more...</div>
</t>
</div>
</t>
</templates>
The script will be called in a my2_child_timeline.xml page
...
<div class="mb-3">
<div id="timeline-root">
<script type="application/json" id="timeline-data">
<t t-raw="json.dumps({
'child_id': child.id,
'records': records,
'pageable': pageable,
})"/>
</script>
<script type="module" src="/my_module/static/src/components/timeline/My2ChildTimeline.js"></script>
</div>
</div>
...
The issue is that it does not find the My2ChildTimelineComponent and I cannot figure it out what is the issue. Is there somebody who could help me?
Thanks for sharing! It got better but I had to change a few things like
odoo.__ready.then
does not exist in odoo 14. But I got over it and unfortunately the template is recognized but not used by the system. There is another underlying problem. After so many hours spend on it, I talked to my senior and we decided to go vanilla js for our use case and maybe later go back to owl as we will upgrade to odoo 17 probably
Thanks anyway!