OWL
data_display
Kanban Record Quick Create
Odoo 19 OWL component — Kanban Record Quick Create (views)
Live preview
Interactive
Source excerpt
web/static/src/views/kanban/kanban_record_quick_create.js
import { _t } from "@web/core/l10n/translation";
import { parseXML } from "@web/core/utils/xml";
import { useHotkey } from "@web/core/hotkeys/hotkey_hook";
import { useOwnedDialogs, useService } from "@web/core/utils/hooks";
import {
Component,
onMounted,
onWillStart,
useExternalListener,
useRef,
useState,
useSubEnv,
} from "@odoo/owl";
import { RPCError } from "@web/core/network/rpc";
import { extractFieldsFromArchInfo } from "@web/model/relational_model/utils";
import { formView } from "../form/form_view";
import { getDefaultConfig } from "../view";
import { FormViewDialog } from "../view_dialogs/form_view_dialog";
const DEFAULT_QUICK_CREATE_VIEW = {
// note: the required modifier is written in the format returned by the server
arch: /* xml */ `
<form>
<field name="display_name" placeholder="Title" required="True" />
</form>`,
};
const DEFAULT_QUICK_CREATE_FIELDS = {
display_name: { string: "Display name", type: "char" },
};
const ACTION_SELECTORS = [
".o_kanban_quick_add",
".o_kanban_load_more button",
".o-kanban-button-new",
];
export class KanbanQuickCreateController extends Component {
static props = {
Model: Function,
Renderer: Function,
Compiler: Function,
resModel: String,
onValidate: Function,
onCancel: Function,
fields: { type: Object },
context: { type: Object },
archInfo: { type: Object },
};
static template = "web.KanbanQuickCreateController";
setup() {
super.setup();
this.uiService = useService("ui");
this.rootRef = useRef("root");
this.state = useState({ disabled: false });
this.addDialog = useOwnedDialogs();
const { activeFields, fields } = extractFieldsFromArchInfo(
this.props.archInfo,
this.props.fields
);
const modelServices = Object.fromEntries(
this.props.Model.services.map((servName) => [servName, useService(servName)])
);
modelServices.orm = useService("orm");
const config = {
resModel: this.props.resModel,
resId: false,
resIds: [],
fields,
activeFields,
isMonoRecord: true,
mode: "edit",
context: this.props.context,
};
this.model = useState(new this.props.Model(this.env, { config }, modelServices));
onWillStart(async () => {
await this.model.load();
this.model.whenReady.resolve();
});
onMounted(() => {
this.uiActiveElement = this.uiService.activeElement;
});
// Close on outside click
useExternalListener(window, "mousedown", (/** @type {MouseEvent} */ ev) => {
// This target is kept in order to impeach close on outside click behavior if the click
// has been initiated from the quickcreate root element (mouse selection in an input...)
this.mousedownTarget = ev.target;
});
useExternalListener(
window,
"click",
(/** @type {MouseEvent} */ ev) => {
if (this.uiActiveElement !== this.uiService.activeElement) {
// this component isn't in the current active element -> do nothing
return;
}
const target = this.mousedownTarget || ev.target;
// accounts for clicking on datetime picker and legacy autocomplete
const gotClickedInside =
target.closest(".o_datetime_picker") ||
target.closest(".ui-autocomplete") ||
this.rootRef.el.contains(target);
if (!gotClickedInside) {
let force = false;
for (const selector of ACTION_SELECTORS) {
const closestEl = target.closest(selector);
if (closestEl) {
force = true;
break;
}
}
this.cancel(force);
}
this.mousedownTarget = null;
},
Registry / API
- Registry name
KanbanRecordQuickCreate- Category
—- Module
web- Slug
kanban-record-quick-create- Nav group
data_display