跳至内容
菜单
此问题已终结
1 回复
137 查看

Hi All,

I have created two boolean fields in stock.picking model.

is_incharge_sign = fields.Boolean(default=False)

is_accountant_sign = fields.Boolean(default=False)

using these fields to show the signature modal in a web form

<div class="mb-4">

​<t t-if="not picking.dispatch_signature and picking.is_incharge_sign">

​<h4>Dispatch In-Charge</h4>

​<a class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal_dispatch">
​​Accept &amp; Sign
​​</a>

​</t>

</div>

<div class="mb-4">

​<t t-if="not picking.accountant_signature and picking.is_accountant_sign">

​<h4>Accountant</h4>

​<a role="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal_accountant">

​Accept &amp; Sign

​</a>

​</t>

</div>


now I want to give some validation to the web form and I need the boolean value in js.

How can I get the boolean values in the js that has been stored in the model?

形象
丢弃
最佳答案

To retrieve boolean field values (like is_incharge_sign and is_accountant_sign) from the stock.picking model in JavaScript, you need to pass the values from the backend to the frontend, as you cannot directly access model data in JavaScript.

In the QWeb template, add the boolean values as data attributes:

<div id="picking_data"

     t-att-data-is_incharge_sign="picking.is_incharge_sign"

     t-att-data-is_accountant_sign="picking.is_accountant_sign">

</div>

In your JavaScript file, you can now access these attributes:

odoo.define('custom_module.picking_sign', function (require) {

    "use strict";


    var publicWidget = require('web.public.widget');


    publicWidget.registry.PickingSignature = publicWidget.Widget.extend({

        selector: '#picking_data',

        start: function () {

            var isInchargeSign = this.$el.data('is_incharge_sign');

            var isAccountantSign = this.$el.data('is_accountant_sign');


            console.log('Incharge Sign:', isInchargeSign);

            console.log('Accountant Sign:', isAccountantSign);

        },

    });


    return publicWidget.registry.PickingSignature;

});


Why this works:


The boolean values are passed from the template to the frontend as data-* attributes, which can be easily accessed using jQuery in the JavaScript file. That avoids the need for making RPC calls and is a simple solution for handling form validation or dynamic behavior based on model data.

 

形象
丢弃
编写者

I tried it already and got below error

Odoo Client Error

UncaughtClientError > TypeError
Uncaught Javascript Error > Cannot read properties of undefined (reading 'data')

Occured on localhost:8069 on 2025-10-29 07:45:12 GMT

TypeError: Cannot read properties of undefined (reading 'data')
at Object.submitHandler (http://localhost:8069/web/assets/1/debug/web.assets_frontend_lazy.js:106170:47)
at d (http://localhost:8069/abcl_sale/static/src/js/jquery.validate.min.js:4:1008)
at HTMLFormElement.<anonymous> (http://localhost:8069/abcl_sale/static/src/js/jquery.validate.min.js:4:1194)
at HTMLFormElement.dispatch (http://localhost:8069/web/assets/1/debug/web.assets_frontend_lazy.js:19605:27)
at HTMLFormElement.<anonymous> (http://localhost:8069/web/assets/1/debug/web.assets_frontend_lazy.js:19409:28)

Hello,
this.$el.data() can only be accessed after the element is rendered and this.$el is defined. The availability depends on the component lifecycle. So you need to check inside the current object(this) by debugging JS code.

编写者

I'm getting undefined in console where as in data the value is true

Incharge Sign: undefined
Accountant Sign: undefined

Can you share the console code and assigned t-att-data in template here?

编写者

below is the div

<div class="row m-2">
<!-- Dispatch Signature -->
<div class="col-md-6">
<t t-if="picking.dispatch_signature" t-att-data-is_incharge_sign="picking.is_incharge_sign">
<div class="col-sm-6" id="dispatch_signature_container">
<h5>Dispatch In-Charge</h5>
<img t-att-src="image_data_uri(picking.dispatch_signature)" style="max-height: 6rem; max-width: 100%;"/>
<p class="mt-2 mb-0">
<t t-out="picking.dispatch_signed_by or ''"/>
</p>
</div>
</t>
<div id="dispatch_content">
<div class="mb-4">
<t t-if="not picking.dispatch_signature and picking.is_incharge_sign">
<h4>Dispatch In-Charge</h4>
<a class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal_dispatch">Accept &amp; Sign</a>
</t>
</div>

<div role="dialog" class="modal fade" id="modal_dispatch" tabindex="-1">
<div class="modal-dialog">
<div id="accept_dispatch" method="POST" class="modal-content">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<header class="modal-header">
<h4 class="modal-title">Dispatch In-Charge Signature</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"/>
</header>
<main class="modal-body" id="sign-dialog-dispatch">
<span>
By signing, you confirm acceptance for delivery order
<b t-out="picking.name"/>.
</span>
<!-- Signature must be inside form -->
<t t-call="portal.signature_form">
<t t-set="call_url" t-value="'/dispatch_checklist/%s/accept/dispatch' % access_token"/>
<t t-set="default_name" t-value="picking.user_id.name or ''"/>
<t t-set="button_text" t-value="'Sign as In-charge'"/>
<t t-set="success_text" t-value="'Signed'"/>
</t>
</main>
</div>

</div>
</div>

</div>
</div>

<!-- Accountant Signature -->
<div class="col-md-6 text-end">
<t t-if="picking.accountant_signature" t-att-data-is_accountant_sign="picking.is_accountant_sign">
<div class="text-end" id="accountant_signature_container">
<h5>Accountant</h5>
<img t-att-src="image_data_uri(picking.accountant_signature)" style="max-height: 6rem; max-width: 100%;"/>
<p class="mt-2 mb-0">
<t t-out="picking.accountant_signed_by or ''"/>
</p>
</div>
</t>
<div id="accountant_content" t-if="not picking.accountant_signature and picking.is_accountant_sign">
<div class="mb-4">
<t t-if="not picking.accountant_signature ">
<h4>Accountant</h4>
<a role="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal_accountant">
Accept &amp; Sign
</a>
</t>
</div>

<div role="dialog" class="modal fade" id="modal_accountant">
<div class="modal-dialog">
<div id="accept_accountant" method="POST" class="modal-content">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<header class="modal-header">
<h4 class="modal-title">Accountant Signature</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"/>
</header>
<main class="modal-body" id="sign-dialog-accountant">
<span>
By signing, you confirm acceptance for delivery order
<b t-out="picking.name"/>.
</span>
<t t-call="portal.signature_form">
<t t-set="call_url" t-value="'/dispatch_checklist/%s/accept/accountant' % access_token"/>
<t t-set="default_name" t-value="picking.finance_user_id.name or ''"/>
<t t-set="button_text" t-value="'Sign as Accountant'"/>
<t t-set="success_text" t-value="'Signed'"/>
</t>
</main>
</div>
</div>
</div>
</div>
</div>
</div>

below is the JS code

start: function () {
const isInchargeSign = this.$el.data("is_incharge_sign");
const isAccountantSign = this.$el.data("is_accountant_sign");
console.log("Incharge Sign:", isInchargeSign);
console.log("Accountant Sign:", isAccountantSign);

and below output from console after loading.

Incharge Sign: undefined
Accountant Sign: undefined

You need to write t-att-data in div or span tag. as "t" tag never actually rendered in HTML.
Try below:
<div class="col-md-6" t-att-data-is_incharge_sign="picking.is_incharge_sign">

编写者

I already tried this

<div class="col-md-6" t-att-data-is_incharge_sign="picking.is_incharge_sign">

but the result still undefined.
very confused what to do?

The only way to know the issue is debugging the JS code.

编写者

Doing that, Thanks for the help so far

I've the code related to this:
<template id="product_review_form" inherit_id="website_sale.product" priority="20">
<form id="valid_review" t-attf-action="/submit_review/#{product.id}" method="POST" class="mt-2">

<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="email" class="form-control email_submit" name="email_product" required=""
data-fill-with="email"/>
<button type="button" t-att-data="product.id" name="send_email" class="btn btn-primary mt-2">Send Email</button>

JS:
publicWidget.registry.AdvanceFormSwitcher = publicWidget.Widget.extend({
selector: '#valid_review',
events: {
'submit': '_onSubmitForm',
'click button[name="send_email"]': '_sendEmail',
'click .o_priority_star': '_onClickStar',
'mouseenter .o_priority_star': '_onMouseHover',
'mouseleave .o_priority_star': '_onMouseLeave',
},

start() {
this._super(...arguments);

const product_id = parseInt(ev.currentTarget.getAttribute('data'))

Hope it is helpful..

相关帖文 回复 查看 活动
1
7月 24
2469
0
4月 24
1902
1
10月 25
306
2
10月 25
426
0
9月 25
336