Hi guys,
In this tutorial I will learn you how to create an on_change event that automatically updates a field when another field changes. In this sample I will create two new fields under sales > products in the tab ‘Procurements’. When a value changes on one of the two fields a third field will be updated with the total of the other two fields.
1. Creating new fields
The first step is to create new fields in the Python file. For example:
1 2 3 4 5 6 7 8 9 10 |
# -*- coding: utf-8 -*- from openerp import models, fields, api class on_change_function(models.Model): #Inhertis the model product.template _inherit = 'product.template' #Creates two new fields (CostPrice and ShippingCost) in the model product.template CostPrice = fields.Float('Buy price') ShippingCost = fields.Float('Shipping Cost') |
This adds two fields (CostPrice and ShippingCost) to the model product.template, which I first inherited. Both these fields are for numbers. After adding your new fields you need to add them to the view.
2. Add fields to view
In case you’re coding in the current module you can simply add the fields like this:
1 2 |
<field name="CostPrice" on_change="on_change_price(CostPrice,ShippingCost)"/> <field name="ShippingCost" on_change="on_change_price(CostPrice,ShippingCost)"/> |
In case you have a new view you can simply add them but if you want to add them to an existing view you will need to inherit the record from the other module, just like in my sample. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<openerp> <data> <record id="view_product_form_inherit" model="ir.ui.view"> <field name="name">product.template.common.form.inherit</field> <field name="model">product.template</field> <field name="inherit_id" ref="product.product_template_form_view"/> <field name="arch" type="xml"> <xpath expr="//field[@name='standard_price']" position="before"> <field name="CostPrice" on_change="on_change_price(CostPrice,ShippingCost)"/> <field name="ShippingCost" on_change="on_change_price(CostPrice,ShippingCost)"/> </xpath> </field> </record> </data> </openerp> |
3. On_change function
Noticing anything in this code? I’ve already added the on_change event in the view like this:
1 |
on_change="on_change_price(CostPrice,ShippingCost)" |
This will search for the function on_change_price in your module and sends two values to the function, CostPrice and ShippingCost. This are the two fields that will contain the values and in these variables are now the values from the two fields. We’re almost there now, the only thing you need to do now is create the function on_change_price in your Python file. Return to your Python file and add the following code:
1 2 3 4 5 6 7 8 9 10 11 12 |
#This method will be called when either the field CostPrice or the field ShippingCost changes. def on_change_price(self,cr,user,ids,CostPrice,ShippingCost,context=None): #Calculate the total total = CostPrice + ShippingCost res = { 'value': { #This sets the total price on the field standard_price. 'standard_price': total } } #Return the values to update it in the view. return res |
In the variables CostPrice and ShippingCost are the values that the user has entered. The variable total simply contains the sum of CostPrice and ShippingCost and this should now be filled in to our third field, which is named standard_price. After the value is calculated and added to the new field it should be returned so that the user can see it.
The result:
As you can see in this image the third field will be automatically calculated with the values from the field CostPrice and the field ShippingCost. The only thing you need to do for the on_change event to go off is to enter, tab or click anywhere else.
Want to see this module in action? You can download / view it on my Github.
If you want to you can also work with @api.onchange, which is specifically for Odoo 8.
Interesting!
Is it possible do the same thing with datetime fields?
Look here: https://www.odoo.com/forum/help-1/question/v8-how-to-add-timestamp-to-a-processed-order-and-calculate-the-time-85758
I’m trying to calculate the time (expressed in minutes) passed from the order creation till his delivery.
I know how to do it on Python starting from a string but I didn’t figured out how to do it on Odoo using directly the fields. Do you have any clue?
Thanks!
Hi Federico,
This is absolutely possible! Supply the date(time) fields in the on_change function so they get passed on in to the Python code. From there on you can start calculating times / dates / .. anything you’d like since you have the ‘variables’ available.
Why ma last post was deleted? 🙁
I can’t output any result, the field is always null.
If you like to see it, my code is here:
https://www.odoo.com/forum/help-1/question/v8-use-on-change-to-calculate-a-timedate-field-86240
Thanks!
Hi Frederico,
I’m sorry it might have ended up in spam or trash! I’ll have a look at your help question tommorow, I’m currently travelling.
It’s really hard find an help like you’re offering here. Thanks!
hello,
onchange function doesn’t work.please help me. my code :
py:
_columns = {
‘toplam’:fields.float(‘Toplam TL’),
‘kar_yuzde’:fields.float(‘Kar’),
‘kar_tutar_tl’:fields.float(‘kar tl’),
}
def on_change_toplamkar(self, cr, uid, ids, kar_yuzde,toplam context=None):
toplam_kar=kar_yuzde*toplam
res={‘value’:{‘kar_tutar_tl’:toplam_kar}}
return res
xml:
Hi buket,
I don’t see a problem in the code that I see but a part is cut off too. Please provide more details about what goes wrong or what the error is, otherwise I can’t really help you.
Hi Yenthe. I know that we can return warning in onchange method. But can we return confirm message?
Hi Harkediansa,
Why not make a wizard that shows a confirmation dialog? Something along the lines of this: https://www.odoo.com/fr_FR/forum/aide-1/question/confirmation-dialog-box-in-odoo-94807
error message ??????
res = {
^
IndentationError: unexpected indent
Hi Bono,
This mean you didn’t indent your Python code correctly. Please double check all your Python code that everything is correctly indented.