Create a Data Table with Search and Pagination
In this section, I will use odoo_search_read and odoo_call_kw to fetch data from the Odoo server and create a table with search and pagination features.
See the example file index6.html below.
Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Odoo API Data Display with Pagination & Search</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.search-container {
text-align: right;
margin-bottom: 10px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th, td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
th {
background-color: #f4f4f4;
}
tr:hover {
background-color: #f0f0f0;
cursor: pointer;
}
.edit-input {
display: none;
}
.pagination {
margin-top: 20px;
text-align: center;
}
.pagination button {
padding: 10px;
margin: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Odoo Data</h2>
<div class="search-container">
<input type="text" id="searchInput" placeholder="Search Name or Description..." onkeyup="searchData()">
</div>
<table id="data-table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Date Start</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- Data will be inserted here dynamically -->
</tbody>
</table>
<div class="pagination">
<button onclick="prevPage()">Previous</button>
<span id="page-info"></span>
<button onclick="nextPage()">Next</button>
</div>
<script>
var odoo_url_api = "http://192.168.5.33/api";
var token = null;
var limit = 2;
var currentPage = 1;
var totalRecords = 0;
var totalPages = 0;
var domain=[]
async function login_odoo(login_param) {
if (!login_param) return;
try {
let response = await fetch(`${odoo_url_api}/login`, {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"username": login_param.username,
"password": login_param.password,
"dbname": login_param.database
}),
});
let data = await response.json();
if (data.error?.code) throw data;
return data.data;
} catch (error) {
console.error("Login failed", error);
}
}
async function odoo_search_read(params) {
return fetch(`${odoo_url_api}/search_read`, {
method: "POST",
headers: {
"Authorization": token,
"Content-Type": "application/json"
},
body: JSON.stringify(params)
})
.then(response => response.json())
.then(result => result.error?.code ? Promise.reject(result) : result)
.catch(error => console.error("Search read failed", error));
}
async function odoo_call_kw(params) {
return fetch(`${odoo_url_api}/call_kw`, {
method: "POST",
headers: {
"Authorization": token,
"Content-Type": "application/json"
},
body: JSON.stringify(params)
})
.then(response => response.json())
.then(result => result.error?.code ? Promise.reject(result) : result)
.catch(error => console.error("Call KW failed", error));
}
async function fetchAndDisplayData() {
const auth = await login_odoo({
username: 'admin_hr',
password: 'password',
database: 'hieu_hr'
});
token = auth?.access_token;
if (!token) {
console.error("Failed to authenticate.");
return;
}
//get total pages on new domain
let countRes = await odoo_call_kw({
"model": "simple.model",
"method": "search_count",
"args": [domain],
"kwargs": {}
});
totalRecords = countRes.data;
totalPages = Math.ceil(totalRecords / limit);
loadPage(currentPage);
}
async function loadPage(page) {
if (page < 1 || page > totalPages) return;
let offset = (page - 1) * limit;
let res = await odoo_search_read({
"model": "simple.model",
"domain": domain,
"fields": ["name", "date_start", "description"],
"limit": limit,
"offset": offset,
"sort": ""
});
displayData(res.data);
currentPage = page;
document.getElementById("page-info").innerText = `Page ${currentPage} of ${totalPages}`;
}
function displayData(data) {
const tableBody = document.querySelector("#data-table tbody");
tableBody.innerHTML = "";
data.forEach(item => {
let row = document.createElement("tr");
row.innerHTML = `
<td>${item.id}</td>
<td>${item.name}</td>
<td>${item.date_start}</td>
<td id="desc-${item.id}">${item.description}</td>
<td>
<button onclick="showEditInput(${item.id})">Edit</button>
<input type="text" id="input-${item.id}" class="edit-input" value="${item.description}">
<button onclick="updateDescription(${item.id})" class="edit-input" id="save-${item.id}">Save</button>
</td>
`;
tableBody.appendChild(row);
});
}
function prevPage() {
if (currentPage > 1) {
loadPage(currentPage - 1);
}
}
function nextPage() {
if (currentPage < totalPages) {
loadPage(currentPage + 1);
}
}
function showEditInput(id) {
document.getElementById(`desc-${id}`).style.display = "none";
document.getElementById(`input-${id}`).style.display = "inline-block";
document.getElementById(`save-${id}`).style.display = "inline-block";
}
async function updateDescription(id) {
let newDescription = document.getElementById(`input-${id}`).value;
const res = await odoo_call_kw({
"args": [[id], { "description": newDescription }],
"model": "simple.model",
"method": "write",
"kwargs": {}
});
if (res) {
document.getElementById(`desc-${id}`).innerText = newDescription;
document.getElementById(`desc-${id}`).style.display = "block";
document.getElementById(`input-${id}`).style.display = "none";
document.getElementById(`save-${id}`).style.display = "none";
alert("Save success");
} else {
console.error("Failed to update description.");
}
}
async function searchData() {
let query = document.getElementById("searchInput").value.trim();
domain = query ? ["|", ["name", "ilike", query], ["description", "ilike", query]] : [];
currentPage = 1;
try {
let [countRes, dataRes] = await Promise.all([
odoo_call_kw({
"model": "simple.model",
"method": "search_count",
"args": [domain],
"kwargs": {}
}),
odoo_search_read({
"model": "simple.model",
"domain": domain,
"fields": ["name", "date_start", "description"],
"limit": limit,
"offset": 0,
"sort": ""
})
]);
totalRecords = countRes.data;
totalPages = Math.ceil(totalRecords / limit);
document.getElementById("page-info").innerText = `Page ${currentPage} of ${totalPages}`;
displayData(dataRes.data); // Hiển thị dữ liệu ngay
} catch (error) {
console.error("Error fetching search results:", error);
}
}
document.addEventListener('DOMContentLoaded', fetchAndDisplayData);
</script>
</body>
</html>
odoo_search_read ;odoo_call_kw ; rest api; odoo
Like
Reply