跳至内容
Odoo 菜单
  • 登录
  • 免费试用
  • 应用程序
    财务
    • 会计
    • 发票
    • 费用
    • 电子表格 (BI)
    • 文档
    • 电子签名
    销售
    • 客户关系管理
    • 销售
    • POS 销售点管理-零售
    • POS 销售点管理 - 餐厅
    • 订阅
    • 租赁
    网站
    • 网站设计
    • 电子商务
    • 博客
    • 论坛
    • 在线客服
    • 在线学习
    供应链
    • 库存
    • 制造
    • 产品生命周期
    • 采购
    • 维护保养
    • 品控
    人力资源
    • 员工
    • 招聘
    • 休假
    • 评价
    • 内部推荐
    • 车队
    营销
    • 社媒营销
    • 电邮营销
    • 短信营销
    • 近期活动
    • 营销自动化
    • 网上调查
    服务
    • 项目管理
    • 工时单
    • 现场服务
    • 服务台
    • 排期
    • 预约
    生产力
    • 讨论
    • 批核
    • IoT物联网
    • VoIP
    • 知识库
    • WhatsApp
    第三方应用软件 Odoo 定制 Odoo云端平台
  • 行业
    零售
    • 书店
    • 服装店
    • 家具店
    • 食品杂货店
    • 五金店
    • 玩具店
    餐饮与酒店服务
    • 酒吧及酒馆
    • 餐厅
    • 快餐
    • 民宿
    • 饮品分销商
    • 酒店
    房地产
    • 房地产代理
    • 建筑师事务所
    • 建造业
    • 地产管理
    • 园艺
    • 业主协会
    咨询
    • 会计师事务所
    • Odoo合作伙伴
    • 市场推广公司
    • 律师事务所
    • 人才招聘
    • 审核 & 认证
    制造
    • 纺织
    • 金属
    • 家具
    • 食品
    • 啤酒厂
    • 企业礼品
    保健与健身
    • 体育俱乐部
    • 眼镜店
    • 健身中心
    • 健康从业者
    • 药房
    • 发型屋
    商贸服务
    • 维修人员
    • IT 硬件及支持
    • 太阳能系统
    • 鞋匠
    • 清洁服务
    • 暖通空调服务
    其他
    • 非营利组织
    • 环境机构
    • 广告牌租赁
    • 摄影服务
    • 自行车租赁
    • 软件经销商
    浏览所有行业
  • 社区
    学习
    • 教学视频
    • 文档
    • 认证
    • 培训
    • 博客
    • 播客
    赋能教育
    • 教育计划
    • Scale Up! 商业游戏
    • 参观Odoo
    获取软件
    • 下载
    • 版本对比
    • 发布
    合作
    • Github
    • 论坛
    • 近期活动
    • 翻译
    • 成为合作伙伴
    • 合作伙伴服务
    • 注册您的会计事务所
    获取服务
    • 寻找合作伙伴
    • 查找会计服务
    • 预约顾问咨询
    • 安装及推行服务
    • 客户参考
    • 支持
    • 升级
    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
只限注册用戶才可与社群互动。
所有帖文 人 徽章
标签 (查看所有)
odoo accounting v14 pos v15
关于此论坛区
只限注册用戶才可与社群互动。
所有帖文 人 徽章
标签 (查看所有)
odoo accounting v14 pos v15
关于此论坛区
帮助

owl component: render to qweb templates via json, possible?

订阅

此帖文有活动时,接收通知

此问题已终结
portalon-premise18.0
3 回复
1019 查看
形象
start@adjunto.fr

I have a small sample app that correctly renders an owl component.  I'm trying to incorporate the component into a larger app made with qweb templates and widgets.

For the small program that works... the controller:

class MyController(http.Controller):

    @http.route('/owlg1/portal_page', type='http', auth='public', website=True)

    def render_portal_page(self):

        _logger.info ("render_portal_page(self), start...")

        html_content = request.render('owlg1.portal_page')

        _logger.info("render_portal_page : Rendered HTML content: %s", html_content)

        return html_content

...the template

<template id="portal_page" name="My Portal Page">
<t t-call="portal.frontend_layout">
        <div id="wrap">
                <div class="container">
                    <h4>My Portal</h4>
                    <owl-component name="owlg1.ChatComponent"/>
                </div>
        </div>
    </t>
</template>

and last, part of the manifest:

    'depends': ['web', 'website', 'im_livechat', 'mail'],
    'assets': {
        'web.assets_frontend': [ ... widget, owl component, owl component template ],
    },
    'data': [
        'views/portal_page.xml',
    ],


The owl component, the main widget and the owl template are all small, generic pieces. (I can post them if you wish)


In my larger app I would like to incorporate the same component into a page controlled by widgets and templates.  The template holding the owl component is not immediately on the page when the user goes there.  The user has to click on a few links to drill down to the template with the owl component is.  The source code is like this:

The widget that renders various part of the page, and the method in question:

const PortalDashboardWidget = publicWidget.Widget.extend({
    selector...
    events... (but nothing related to the button in the own component)
    ... methods...

_setupSubjectDetail: async function(in_userSubjectId) {
    const userSubjectResult = await rpc(
     urlBase + '/dashboard/usersubject/chatbutton',   
                    { userSubject_id: in_userSubjectId }
      );
    $('#chat-block').html(chatButtonResult.html);

});

publicWidget.registry.PortalDashboardWidget = PortalDashboardWidget;
export default PortalDashboardWidget;
The controller:

@http.route(WebsiteController._routes['base'] + '/dashboard/usersubject/chatbutton', type='json', auth='user')

def getChatButton(self, userSubject_id=None, **_kw):
    ... get the chat id from the db, livechat_channel_session.id  (this part works)
    html_content = request.env['ir.ui.view']._render_template(
      "myapp.chat-button-content", { 'chat_session_id': livechat_channel_session.id
    })
    html_content = str(html_content)
    return {'html': html_content}

... and finally part of the manifest:

   'depends': ['base_setup',
        'base',
        'web',
        'portal',
        'project',
        'mail',
        'website',
        'im_livechat',
    ],
    'installable': True,
    'application': True,
    'data': [
        'security/ir.model.access.csv',
...templates... except the owl-component template
        'data/website_data.xml',
...
    ],
'assets': {
    'web.assets_frontend': [
        'myapp/static/src/js/chat/chat_service.js', #owl service, component, template     
'myapp/static/src/js/chat/chat_component.js',
        'myapp/static/src/xml/chat/chat_template.xml',
        ... scss, images, widget javascript
    ],
},


chat-block is a template that is not immediately rendered when the user goes to the page.  The user has to click to "drill-down" to the template where the chat button is.

The above code works well for all of my other templates and widgets, but in this case, when the teamplate is rendered by the controller, <owl-component>... is in the rendered html, and it is inserted into the web page and sits there, inert.


If I move the owl component to a higher level template, one rendered as shown in my sample code, with a controller using type='http',  and "render(...)", it works.  So I believe the component itself is ok. 


I belive I have to alter the widget javascript and the python controller, but have no idea how.  I've modified both files in various ways but have not succeeded.  One idea I had was to make the controller method type='http' so get the rendering correct, and then somehow change it's http response into a json response to work with the widget.  Mostly I either get <owl-component> in my rendered html, and it does not activate, or I get empty json.


Any help/examples would be greatly appreciated.  If you could provide the "import... " lines in your answer that would help.  Thanks!






0
形象
丢弃
形象
Samad Alimadadi
最佳答案

.

0
形象
丢弃
形象
start@adjunto.fr
编写者 最佳答案

Hello CTS, definitely better... but not quite working.

I'm getting this error message:


OwlError: Missing template: "adjuntohub.ChatContentTemplate" (for component "ChatComponent")


Which I find strange, because when I put <owl-component> on the main page it finds the template.  So I'm pretty sure the manifest is ok


here is the component:

/** @odoo-module **/

import { useService } from "@web/core/utils/hooks";

import { Component } from "@odoo/owl";  

import { registry } from "@web/core/registry";


export class ChatComponent extends Component {


    static template = 'adjuntohub.ChatContentTemplate';

    static props = {

        sessionId: { type: String, optional: true },  // chat session id as string

    };


    setup() {

        console.info("ChatComponent(), setup(), start...");

        this.mail_store_service = useService("adjuntohub.ChatService");

        this.chat_id = parseInt(this.props.sessionId);

        console.info("ChatComponent(), setup(), chat_id is %d.  End.", this.chat_id);

    }


    async onClickChat(ev) {

        ev.preventDefault();

        if (!this.props.sessionId) {

            console.warn("ChatComponent.onClickChat(): sessionId not provided as prop, hard coding to 20 (subject 1336-sv) for testing");

            this.props.sessionId = "20";

        }

        const chat_id = parseInt(this.props.sessionId);

        console.info("ChatComponent.onClickChat(chat_id=%d) start...", chat_id);  // chat_id -> channel_id


        if (chat_id) {

            console.info("  chat_id present, try to open the chat");

            await this.mail_store_service.open_specific_chat(chat_id);

        } else {

            console.warn("chat_id not present");

        }

        console.info("ChatComponent.onClickChat(chat_id=%d) end", chat_id);


    }

}


registry.category("public_components").add("adjuntohub.ChatComponent", ChatComponent);



Here is the component template:


<?xml version="1.0" encoding="UTF-8"?>

<templates xml:space="preserve" >


    <t t-name="adjuntohub.ChatContentTemplate" >  <!-- owl="1" didn't change anything -->

        <p> OWL component adjunto_hub.ChatContent</p>

        <button t-on-click="onClickChat"

            id="chat-button"

            t-att-data-chat-id="chat_id"

            class="btn btn-primary">

            Open Chat

        </button>

        <p>chat_session_id=<t t-esc="chat_session_id"/> </p>

    </t>

</templates>



Here is the crucial part I didn't have in my widget, mounting the component:

// Dynamically mount the OWL component
// Find the <owl-component> element inside the inserted HTML
const owlEl = $chatBlock[0].querySelector('owl-component');
if (owlEl) {
  const cc = registry.category("public_components").get("adjuntohub.ChatComponent");
    mount(cc, { target: owlEl }); 
}

So the controller renders the html and the javascript correctly places it.  And then this code tries to mount it.

What I don't see is any sign of the component being initialized.  I did see that when I had the component on my main page (the page rendered with http).  But I removed the component from that page. 

Things I've tried:
adding owl="1" attribute to the template
using components instead of public_components
I tried a few variations of mountComponent but still got the same error.

And, I don't know if this makes a difference, but I couldn't find this._rpc(...) so I used just rpc(...)

Any ideas?  Maybe look at cc, see if is has a template?
Thank for your help, much obliged.







0
形象
丢弃
形象
Cybrosys Techno Solutions Pvt.Ltd
最佳答案

Hi,


You need to:


    Return the template HTML via JSON as you do.

    After inserting the HTML, manually mount the OWL component using @web/owl utilities.

Step 1: Import necessary OWL modules in your widget JS


/** chat_widget.js **/

import { registry } from "@web/core/registry";

import { Component } from "@odoo/owl";

import { mount } from "@odoo/owl";

import { publicWidget } from "web.public.widget";


Step 2: Update your widget _setupSubjectDetail method


_setupSubjectDetail: async function(in_userSubjectId) {

    // Fetch the template HTML via RPC

    const chatButtonResult = await this._rpc({

        route: "/dashboard/usersubject/chatbutton",

        params: { userSubject_id: in_userSubjectId },

    });


    // Insert HTML into the DOM

    const $chatBlock = $('#chat-block');

    $chatBlock.html(chatButtonResult.html);


    // Dynamically mount the OWL component

    // Find the <owl-component> element inside the inserted HTML

    const owlEl = $chatBlock[0].querySelector('owl-component');


    if (owlEl) {

        const ChatComponent = registry.category("components").get("myapp.ChatComponent");

        mount(ChatComponent, { target: owlEl });

    }

}


Step 3: Ensure your OWL component is registered


/** chat_component.js **/

import { Component } from "@odoo/owl";

import { registry } from "@web/core/registry";


export class ChatComponent extends Component {

    static template = "myapp.ChatComponentTemplate";

}


registry.category("components").add("myapp.ChatComponent", ChatComponent);


* ChatComponentTemplate is your OWL template ID in XML (chat_template.xml).

* Ensure the template is loaded via assets (web.assets_frontend).


Step 4: Controller remains type='json'


No need to change the Python controller. Your current setup works:


@http.route('/dashboard/usersubject/chatbutton', type='json', auth='user')

def getChatButton(self, userSubject_id=None, **_kw):

    # Prepare the template HTML

    html_content = request.env['ir.ui.view']._render_template(

        "myapp.chat-button-content",

        {'chat_session_id': livechat_channel_session.id}

    )

    return {'html': str(html_content)}


- OWL does not auto-initialize components inserted via AJAX/JSON.

- After inserting the HTML, you must mount the OWL component manually.

- Use registry to fetch the component and mount from @odoo/owl.

- Keep controller type='json' for AJAX loading — no need to convert to http.


Hope it helps

0
形象
丢弃
start@adjunto.fr
编写者

Yes, I got closer, thanks! But it's still not working. I put the details in another reply, yesterday. I didn't see the comment button.

喜欢讨论吗?不要只阅读,加入进来!

立即创建账户,享受专属功能,与我们的精彩社区互动!

注册
相关帖文 回复 查看 活动
Adding Front-end/Website Theme to Odoo 18 Not Working
theme website on-premise 18.0
形象
1
1月 25
3430
Trying to replace default “Invoices & Bills” breadcrumb in Odoo portal
portal
形象
形象
1
11月 25
395
How To Hide Action Report By Picking Type Code ?
18.0
形象
形象
形象
3
11月 25
601
Dynamically update cart icon after adding products from a reorder popup in Custom Odoo portal
portal
形象
形象
1
11月 25
304
How do I set up budget management / planning 已解决
18.0
形象
形象
2
8月 25
1091
社区
  • 教学视频
  • 文档
  • 论坛
开源
  • 下载
  • Github
  • Runbot
  • 翻译
服务
  • Odoo.sh 托管
  • 支持
  • 升级
  • 自定义开发服务
  • 教育
  • 查找会计服务
  • 寻找合作伙伴
  • 成为合作伙伴
关于我们
  • 我们的公司
  • 品牌资产
  • 联系我们
  • 招聘
  • 近期活动
  • 播客
  • 博客
  • 客户
  • 法律 • 隐私
  • 安全
الْعَرَبيّة 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进行数字化升级。通过一系列全业务链覆盖、高度集成、简单易用的商业应用,助力企业实现信息化改革、降本增效并释放公司增长潜力。

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