services
data_display
view
Odoo 19 services — view (views)
Live preview
Interactive
Source excerpt
web/static/src/views/view_service.js
import { rpcBus } from "@web/core/network/rpc";
import { registry } from "@web/core/registry";
import { UPDATE_METHODS } from "@web/core/orm_service";
/**
* @typedef {Object} IrFilter
* @property {[number, string] | false} user_id
* @property {string} sort
* @property {string} context
* @property {string} name
* @property {string} domain
* @property {number} id
* @property {boolean} is_default
* @property {string} model_id
* @property {[number, string] | false} action_id
* @property {number | false} embedded_action_id
* @property {number | false} embedded_parent_res_id
*/
/**
* @typedef {Object} ViewDescription
* @property {string} arch
* @property {number|false} id
* @property {number|null} [custom_view_id]
* @property {Object} [actionMenus] // for views other than search
* @property {IrFilter[]} [irFilters] // for search view
*/
/**
* @typedef {Object} LoadViewsParams
* @property {string} resModel
* @property {[number, string][]} views
* @property {Object} context
*/
/**
* @typedef {Object} LoadViewsOptions
* @property {number|false} actionId
* @property {boolean} loadActionMenus
* @property {boolean} loadIrFilters
*/
export const viewService = {
dependencies: ["orm"],
async: ["loadViews"],
start(env, { orm }) {
rpcBus.addEventListener("RPC:RESPONSE", (ev) => {
const { model, method } = ev.detail.data.params;
if (["ir.ui.view", "ir.filters"].includes(model)) {
if (UPDATE_METHODS.includes(method)) {
rpcBus.trigger("CLEAR-CACHES", "get_views");
}
}
});
/**
* Loads various information concerning views: fields_view for each view,
* fields of the corresponding model, and optionally the filters.
*
* @param {LoadViewsParams} params
* @param {LoadViewsOptions} [options={}]
* @returns {Promise<ViewDescriptions>}
*/
async function loadViews(params, options = {}) {
const { context, resModel, views } = params;
const loadViewsOptions = {
action_id: options.actionId || false,
embedded_action_id: options.embeddedActionId || false,
embedded_parent_res_id: options.embeddedParentResId || false,
load_filters: options.loadIrFilters || false,
toolbar: (!context?.disable_toolbar && options.loadActionMenus) || false,
};
for (const key in options) {
if (
![
"actionId",
"embeddedActionId",
"embeddedParentResId",
"loadIrFilters",
"loadActionMenus",
].includes(key)
) {
loadViewsOptions[key] = options[key];
}
}
if (env.isSmall) {
loadViewsOptions.mobile = true;
}
if (env.debug) {
loadViewsOptions.debug = true;
}
const filteredContext = Object.fromEntries(
Object.entries(context || {}).filter(
([k, v]) => k == "lang" || k.endsWith("_view_ref")
)
);
const result = await orm.cache({ type: "disk" }).call(resModel, "get_views", [], {
context: filteredContext,
views,
options: loadViewsOptions,
});
const viewDescriptions = {
fields: result.models[resModel].fields,
relatedModels: result.models,
views: {},
};
for (const viewType in result.views) {
const { arch, toolbar, id, filters, custom_view_id } = result.views[viewType];
const viewDescription = { arch, id, custom_view_id };
if (toolbar) {
viewDescription.actionMenus = toolbar;
}
if (filters) {
viewDescription.irFilters = filters;
}
viewDescriptions.views[viewType] = viewDescription;
}
return viewDescriptions;
}
Registry / API
- Registry name
view- Category
services- Module
web- Slug
view- Nav group
data_display