OWL
forms
Many2 X Autocomplete
Odoo 19 OWL component — Many2 X Autocomplete (views)
Live preview
Interactive
Source excerpt
web/static/src/views/fields/relational_utils.js
import { AutoComplete } from "@web/core/autocomplete/autocomplete";
import { makeContext } from "@web/core/context";
import { Dialog } from "@web/core/dialog/dialog";
import { Domain } from "@web/core/domain";
import { _t } from "@web/core/l10n/translation";
import { RPCError } from "@web/core/network/rpc";
import { evaluateBooleanExpr } from "@web/core/py_js/py";
import {
useBus,
useChildRef,
useForwardRefToParent,
useOwnedDialogs,
useService,
} from "@web/core/utils/hooks";
import { createElement, parseXML } from "@web/core/utils/xml";
import { extractFieldsFromArchInfo, useRecordObserver } from "@web/model/relational_model/utils";
import { FormArchParser } from "@web/views/form/form_arch_parser";
import { loadSubViews, useFormViewInDialog } from "@web/views/form/form_controller";
import { FormRenderer } from "@web/views/form/form_renderer";
import { computeViewClassName, isNull } from "@web/views/utils";
import { ViewButton } from "@web/views/view_button/view_button";
import { executeButtonCallback, useViewButtons } from "@web/views/view_button/view_button_hook";
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
/**
* @typedef {Object} RelationalActiveActions {
* @property {"x2m"} type
* @property {boolean} create
* @property {boolean} createEdit
* @property {boolean} delete
* @property {boolean} [link]
* @property {boolean} [unlink]
* @property {boolean} [write]
* @property {Function | null} onDelete
*
* @typedef {import("services").Services} Services
*/
import {
Component,
onWillUpdateProps,
status,
useComponent,
useEffect,
useEnv,
useState,
useSubEnv,
} from "@odoo/owl";
import { KeepLast } from "@web/core/utils/concurrency";
import { highlightText, odoomark } from "@web/core/utils/html";
import { deepEqual } from "@web/core/utils/objects";
//
// Commons
//
export function useSelectCreate({ resModel, activeActions, onSelected, onCreateEdit, onUnselect }) {
const addDialog = useOwnedDialogs();
function selectCreate({ domain, context, filters, title }) {
addDialog(SelectCreateDialog, {
title: title || _t("Select records"),
noCreate: !activeActions.create,
multiSelect: "link" in activeActions ? activeActions.link : false, // LPE Fixme
resModel,
context,
domain,
onSelected,
onCreateEdit: () => onCreateEdit({ context }),
dynamicFilters: filters,
onUnselect,
});
}
return selectCreate;
}
const STANDARD_ACTIVE_ACTIONS = ["create", "createEdit", "delete", "link", "unlink", "write"];
/**
* FIXME: this should somehow be merged with 'getActiveActions' (@web/views/utils.js)
* Also I don't think storing a function in a collection of booleans is a good idea...
*
* @param {Object} params
* @param {string} params.fieldType
* @param {Record<string, boolean>} [params.subViewActiveActions={}]
* @param {Object} [params.crudOptions={}]
* @param {(props: Record<string, any>) => Record<any, any>} [params.getEvalParams=() => ({})]
* @returns {RelationalActiveActions}
*/
export function useActiveActions({
fieldType,
subViewActiveActions = {},
crudOptions = {},
getEvalParams = () => ({}),
}) {
const compute = ({ evalContext = {}, readonly = true }) => {
/** @type {RelationalActiveActions} */
const result = { type: fieldType, onDelete: null };
const evalAction = (actionName) => evals[actionName](evalContext);
// We need to take care of tags "control" and "create" to set create stuff
result.create = !readonly && evalAction("create");
result.createEdit = !readonly && result.create && crudOptions.createEdit; // always a boolean
result.edit = crudOptions.edit; // always a boolean
result.delete = !readonly && evalAction("delete");
result.write = (isMany2Many || !readonly) && evalAction("write");
if (isMany2Many) {
result.link = !readonly && evalAction("link");
result.unlink = !readonly && evalAction("unlink");
}
if (result.unlink || (!isMany2Many && result.delete)) {
result.onDelete = crudOptions.onDelete;
}
return result;
};
const props = useComponent().props;
Registry / API
- Registry name
Many2XAutocomplete- Category
—- Module
web- Slug
many2-x-autocomplete- Nav group
forms