Client Action:
In Odoo, client actions play a crucial role in customizing and enhancing the user experience within the Odoo web client. They are predefined sets of actions implemented on the client side using JavaScript and XML, enabling developers to extend or modify the default behavior of Odoo. Client actions can be associated with various triggers like button clicks, view changes, and form submissions, among others. They empower developers to define specific operations, such as creating or updating records, validating form inputs, dynamically updating field values, and implementing custom workflow actions. By leveraging client actions, businesses can tailor Odoo to their unique requirements, delivering a more intuitive and streamlined user experience.
To continue, add a menu to the views/views.xml file in the view's directory.
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="employee_dashboard_action" model="ir.actions.client">
<field name="name">Employee Dashboard</field>
<field name="tag">employee_dashboard</field>
</record>
<menuitem name="Employee Dashboard" id="employee_detail_dashboard"
action="employee_dashboard_action"/>
</odoo>
I am creating an Employee Dashboard in the ir.actions.client model (we can choose any desired name). Additionally, when the menu is clicked, I have added "employee_dashboard" to the tag box. This tag is used in the widget to load or call the specified action as defined in the widget. The tag facilitates the loading or calling of the action's JavaScript file.
The target field can be utilized to modify the view size (Client Action), execute other actions, or open the action as a pop-up window. I will provide a completely new configuration for it when it is received. Consequently, the client action will be displayed as a pop-up window.
OWL JS:
/**@odoo-module */
const { Component, onMounted, useState } = owl;
import { registry } from "@web/core/registry";
const actionRegistry = registry.category("actions");
const rpc = require('web.rpc');
export class EmployeeDashboard extends Component {
setup(){
super.setup(...arguments);
this.employeeDashboard = useState({ data: [] })
onMounted(()=>{
this.loadData();
})
}
loadData(){
let self = this;
let arguments = 'your-arguments'
rpc.query({
model: 'employee.dashboard',
method: 'get_time_off',
args:[arguments]
}).then(function(data){
self.employeeDashboard.data = data;
});
}
}
EmployeeDashboard.template = "EmployeeDashboard";
actionRegistry.add("employee_dashboard", EmployeeDashboard);
Here, we are extending the base component of Owl to define a class, which is then registered in the action registry using the tag from the previously created XML file. The template is also added to the class using the ‘EmployeeDashboard.template’ keyword.
The onMounted function triggers the loadData function, which in turn calls the Python get_time_off function in the employee.dashboard model. This function retrieves the data, which is then accessed in the then function. The data is returned to the data parameter in the useState function, which updates the XML templates whenever useState.data is updated.
We must now specify the Qweb template as well as the Python function file that the RPC will use. So, initially, I'm going to make a Python file (models/filename.py).
from odoo import fields, models, api
class EmployeeDashboard(models.Model):
_name = 'employee.dashboard'
_description = 'Employee Dashboard'
some_field = fields.Many2one()
another_field = fields.Char()
@api.model
def get_time_off(self):
data = self.env['employee.dashboard'].search([])
return data.read()
Here, I am building a new model called employee.dashboard (make sure to provide the model with appropriate security settings) and defining a function that searches the entire model and returns the data to JavaScript. Please ensure that you add the read() method, as objects are not directly accessible in JavaScript.
As a result, this data will be accessible over RPC (Remote Procedure Call), and it will be provided to the Qweb template.
Let's begin by defining the template in static/src/xml.
<?xml version="1.0" encoding="UTF-8" ?>
<templates id="template">
<t t-name="EmployeeDashboard" owl="1">
<div class="oh_dashboards" style="margin-top: 20px;">
<div class="container-fluid o_pj_dashboard">
<div class="container h-100">
<div class="row h-100 justify-content-center align-items-center">
<div class="col-12">
<h2 class="text-center">Employee Dashboard</h2>
</div>
</div>
</div>
<br/>
<div class="container">
<div class="row">
<div class="col-md-6">
<form class="shadow">
<div class="title">
<div class="form-row align-items-center">
<h4 class="text-center">Employee Payslips</h4>
</div>
</div>
<div class="body">
<table class="table table-attendance" t-ref="employee-data"
t-on-click="attendanceBackend" style="cursor: pointer;">
<tr>
<th>Some Field</th>
<th>Another Field</th>
</tr>
<tr t-foreach="employeeDashboard.data"
t-as="data" t-key="data_index"
t-att-data-value="data.id">
<td t-out="data.some_field"/>
<td t-out="data.another_field"/>
</tr>
</table>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</t>
</templates>
Here, we can directly access employeeDashboard.data, which contains multiple sets of data. We can use a t-foreach function in the Owl template to utilize it. Remember to include the 't-key' attribute, as it is required in a t-foreach function within the Owl template.