Skip to Content
Odoo मेन्यू
  • Sign in
  • मुफ़्त में आज़माएं
  • ऐप्लिकेशन
    फ़ाइनेंस
    • अकाउंटिंग
    • इनवॉइसिंग
    • एक्सपेंस
    • स्प्रेडशीट (बीआई)
    • डॉक्यूमेंट्स
    • साइन
    सेल्स
    • सीआरएम
    • सेल्स
    • पीओएस शॉप
    • पीओएस रेस्टोरेंट
    • सब्सक्रिप्शन
    • रेंटल
    वेबसाइट
    • वेबसाइट बिल्डर
    • ई-कॉमर्स
    • ब्लॉग
    • फ़ोरम
    • लाइव चैट
    • ई-लर्निंग
    सप्लाई चेन
    • इन्वेंट्री
    • मैन्युफ़ैक्चरिंग
    • पीएलएम
    • परचेज़
    • मेंटेनेंस
    • क्वालिटी
    मानव संसाधन
    • कर्मचारी
    • रिक्रूटमेंट
    • टाइम ऑफ़
    • अप्रेज़ल
    • रेफ़रल
    • फ़्लीट
    मार्केटिंग
    • सोशल मार्केटिंग
    • ईमेल मार्केटिंग
    • एसएमएस मार्केटिंग
    • इवेंट
    • मार्केटिंग ऑटोमेशन
    • सर्वे
    सेवाएं
    • प्रोजेक्ट
    • टाइमशीट
    • फ़ील्ड सर्विस
    • हेल्पडेस्क
    • प्लानिंग
    • अपॉइंटमेंट
    प्रॉडक्टिविटी
    • डिस्कस
    • अप्रूवल
    • आईओटी
    • वीओआईपी
    • नॉलेज
    • WhatsApp
    तीसरे पक्ष के ऐप्लिकेशन Odoo स्टूडियो Odoo क्लाउड प्लेटफ़ॉर्म
  • इंडस्ट्री
    रीटेल
    • बुक स्टोर
    • क्लोदिंग स्टोर
    • फ़र्नीचर स्टोर
    • ग्रॉसरी स्टोर
    • हार्डवेयर स्टोर
    • टॉय स्टोर
    Food & Hospitality
    • बार और पब
    • रेस्टोरेंट
    • फ़ास्ट फ़ूड
    • Guest House
    • बेवरिज डिस्ट्रीब्यूटर
    • होटल
    रियल एस्टेट
    • Real Estate Agency
    • आर्किटेक्चर फ़र्म
    • कंसट्रक्शन
    • एस्टेट मैनेजमेंट
    • गार्ड्निंग
    • प्रॉपर्टी ओनर असोसिएशन
    कंसल्टिंग
    • अकाउंटिंग फ़र्म
    • Odoo पार्टनर
    • मार्केटिंग एजेंसी
    • लॉ फ़र्म
    • टैलेंट ऐक्विज़िशन
    • ऑडिट & सर्टिफ़िकेशन
    मैन्युफ़ैक्चरिंग
    • टेक्सटाइल
    • Metal
    • फ़र्नीचर
    • फ़ूड
    • Brewery
    • कॉर्पोरेट गिफ़्ट
    हेल्थ & फिटनेस
    • स्पोर्ट्स क्लब
    • आईवियर स्टोर
    • फिटनेस सेंटर
    • वेलनेस प्रैक्टिशनर
    • फॉर्मेसी
    • हेयर सैलून
    Trades
    • Handyman
    • आईटी हॉर्डवेयर और सपोर्ट
    • Solar Energy Systems
    • Shoe Maker
    • Cleaning Services
    • HVAC Services
    अन्य
    • Nonprofit Organization
    • एन्वायरमेंटल एजेंसी
    • बिलबोर्ड रेंटल
    • फ़ोटोग्राफी
    • बाइक लीजिंग
    • सॉफ़्टवेयर रीसेलर
    Browse all Industries
  • कम्यूनिटी
    सीखें
    • ट्यूटोरियल्स
    • दस्तावेज़
    • सर्टिफ़िकेशन
    • ट्रेनिंग
    • ब्लॉग
    • पॉडकास्ट
    शिक्षा को बढ़ावा दें
    • एजुकेशन प्रोग्राम
    • स्केल अप! बिजनेस गेम
    • Odoo के ऑफ़िस में आएं
    सॉफ़्टवेयर पाएं
    • डाउनलोड
    • वर्शन की तुलना करें
    • रिलीज़
    साथ मिलकर काम करें
    • Github
    • फ़ोरम
    • इवेंट
    • अनुवाद
    • पार्टनर बनें
    • Services for Partners
    • अपना अकाउंटिंग फ़र्म रजिस्टर करें
    सेवाएं पाएं
    • पार्टनर ढूंढें
    • अकाउंटेंट खोजें
    • सलाहकार की मदद लें
    • इम्प्लिमेंटेशन सेवाएं
    • कस्टमर रेफ़रेंस
    • सहायता
    • अपग्रेड
    Github Youtube Twitter Linkedin Instagram Facebook Spotify
    +1 (650) 691-3277
    डेमो देखें
  • कीमत
  • सहायता

Odoo is the world's easiest all-in-one management software.
It includes hundreds of business apps:

  • सीआरएम
  • e-Commerce
  • लेखांकन
  • इन्वेंटरी
  • PoS
  • प्रोजेक्ट
  • MRP
All apps
You need to be registered to interact with the community.
All Posts People Badges
टैग (View all)
odoo accounting v14 pos v15
About this forum
You need to be registered to interact with the community.
All Posts People Badges
टैग (View all)
odoo accounting v14 pos v15
About this forum
Help

Issue with understanding how Owl template integrate in odoo 14

Subscribe

Get notified when there's activity on this post

This question has been flagged
javascriptdevelopmentowlodooV14
1 Reply
1630 Views
Avatar
Daniel Palumbo

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?



0
Avatar
Discard
Daniel Palumbo
Author

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!

Avatar
D Enterprise
Best Answer

Hii,


Here is updated code 


my_module/views/timeline_templates.xml


<odoo>

  <!-- Register the template -->

  <template id="My2ChildTimelineComponent">

    <t t-name="my_module.My2ChildTimelineComponent" owl="1">

      <div class="timeline-list">

        <t t-if="state.loading">

          <div class="text-center py-2">Loading more...</div>

        </t>

      </div>

    </t>

  </template>

</odoo>


Update __manifest__.py

Make sure this is included:


'qweb': [

    'views/timeline_templates.xml',

],


JavaScript Component


odoo.define('my_module.My2ChildTimeline', function (require) {

    "use strict";


    const { Component } = owl;

    const { useState, onWillStart, onMounted } = owl.hooks;

    const ajax = require("web.ajax");


    class ChildTimeline extends Component {

        setup() {

            this.state = useState({

                loading: false,

                offset: 0,

                limit: 10,

                hasMoreRecords: true,

            });


            onWillStart(() => this.loadMore());

            onMounted(() => window.addEventListener('scroll', this.onScroll.bind(this)));

        }


        async loadMore() {

            this.state.loading = true;

            const res = await ajax.jsonRpc(`/somewhere`, "call", {

                offset: this.state.offset,

                limit: this.state.limit,

            });


            const container = this.el.querySelector('.timeline-list');

            const tempDiv = document.createElement('div');

            tempDiv.innerHTML = res.html;

            [...tempDiv.children].forEach(el => container.appendChild(el));


            this.state.offset += this.state.limit;

            this.state.hasMoreRecords = res.has_more_records;

            this.state.loading = false;

        }


        onScroll() {

            const nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 100;

            if (!this.state.loading && this.state.hasMoreRecords && nearBottom) {

                this.loadMore();

            }

        }

    }


    ChildTimeline.template = "my_module.My2ChildTimelineComponent";


    odoo.__ready.then(() => {

        const target = document.getElementById("timeline-root");

        const script = document.getElementById("timeline-data");


        if (target && script) {

            const props = JSON.parse(script.textContent);

            owl.mount(ChildTimeline, { target, props });

        }

    });


    return ChildTimeline;

});


In views/assets.xml:

<odoo>

  <template id="assets_frontend" inherit_id="web.assets_frontend" name="Timeline Assets">

    <xpath expr="." position="inside">

      <script type="module" src="/my_module/static/src/components/timeline/My2ChildTimeline.js"/>

    </xpath>

  </template>

</odoo>

And include assets.xml in __manifest__.py under data.


i hope it is use full

0
Avatar
Discard
Enjoying the discussion? Don't just read, join in!

Create an account today to enjoy exclusive features and engage with our awesome community!

Sign up
Related Posts Replies Views Activity
How can I use my only web url domain using odoo?
javascript development
Avatar
Avatar
1
सित॰ 25
1409
How to Load Related Many2Many Data (pos.ticket.type) into the Frontend?
javascript development
Avatar
0
जून 25
1752
Odoo 18 POS - Discount Button Group Permissions Not Working
javascript development
Avatar
Avatar
2
जून 25
1940
¿Cómo puedo crear un Dashboard con KPIs y gráficos con Chart.js?
javascript development
Avatar
0
अप्रैल 25
1921
Odoo icon change Solved
javascript development
Avatar
Avatar
2
जन॰ 25
2462
कम्यूनिटी
  • ट्यूटोरियल्स
  • दस्तावेज़
  • फ़ोरम
ओपन सोर्स
  • डाउनलोड
  • Github
  • रनबॉट
  • अनुवाद
सेवाएं
  • Odoo.sh Hosting
  • सहायता
  • अपग्रेड
  • कस्टम डेवलपमेंट्स
  • शिक्षा
  • अकाउंटेंट खोजें
  • पार्टनर ढूंढें
  • पार्टनर बनें
हमारे बारे में
  • हमारी कंपनी
  • ब्रांड ऐसेट
  • संपर्क करें
  • नौकरियां
  • इवेंट
  • पॉडकास्ट
  • ब्लॉग
  • ग्राहक
  • लीगल • गोपनीयता
  • सुरक्षा
الْعَرَبيّة Català 简体中文 繁體中文 (台灣) Čeština Dansk Nederlands English Suomi Français Deutsch हिंदी Bahasa Indonesia Italiano 日本語 한국어 (KR) Lietuvių kalba Język polski Português (BR) română русский язык Slovenský jazyk slovenščina Español (América Latina) Español ภาษาไทย Türkçe українська Tiếng Việt

Odoo, बिज़नेस से जुड़े ऐप्लिकेशन का एक कलेक्शन है जो ओपन सोर्स पर आधारित है. इसमें आपकी कंपनी की हर ज़रूरत के लिए ऐप्लिकेशन हैं. जैसे, सीआरएम, ई-कॉमर्स, अकाउंटिंग, इन्वेंट्री, पॉइंट ऑफ़ सेल, प्रोजेक्ट मैनेजमेंट वगैरह.

Odoo की सबसे बड़ी खासियत है कि यह इस्तेमाल करने में बहुत आसान है और यह पूरी तरह से इंटिग्रेट किया हुआ है.

Website made with

Odoo Experience on YouTube

1. Use the live chat to ask your questions.
2. The operator answers within a few minutes.

Live support on Youtube
Watch now