OWL
forms
Domain Field
Odoo 19 OWL component — Domain Field (views)
Live preview
Interactive
Source excerpt
web/static/src/views/fields/domain/domain_field.js
import { Component, useState } from "@odoo/owl";
import { Domain, InvalidDomainError } from "@web/core/domain";
import { DomainSelector } from "@web/core/domain_selector/domain_selector";
import { useGetDefaultLeafDomain } from "@web/core/domain_selector/utils";
import { DomainSelectorDialog } from "@web/core/domain_selector_dialog/domain_selector_dialog";
import { _t } from "@web/core/l10n/translation";
import { rpc } from "@web/core/network/rpc";
import { EvaluationError } from "@web/core/py_js/py_builtin";
import { registry } from "@web/core/registry";
import { domainContainsExpressions } from "@web/core/tree_editor/domain_contains_expressions";
import { useBus, useOwnedDialogs, useService } from "@web/core/utils/hooks";
import { useRecordObserver } from "@web/model/relational_model/utils";
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
import { standardFieldProps } from "../standard_field_props";
export class DomainField extends Component {
static template = "web.DomainField";
static components = {
DomainSelector,
};
static props = {
...standardFieldProps,
context: { type: Object, optional: true },
editInDialog: { type: Boolean, optional: true },
resModel: { type: String, optional: true },
isFoldable: { type: Boolean, optional: true },
countLimit: { type: Number, optional: true },
allowExpressions: { type: Boolean, optional: true },
};
static defaultProps = {
editInDialog: false,
isFoldable: false,
countLimit: 10000,
allowExpressions: false,
};
setup() {
this.orm = useService("orm");
this.notification = useService("notification");
this.treeProcessor = useService("tree_processor");
this.getDefaultLeafDomain = useGetDefaultLeafDomain();
this.addDialog = useOwnedDialogs();
this.state = useState({
isValid: null,
recordCount: null,
hasLimitedCount: null,
folded: this.props.isFoldable,
facets: [],
});
this.debugDomain = null;
useRecordObserver(async (record, nextProps) => {
nextProps = { ...nextProps, record };
if (this.debugDomain && this.props.readonly !== nextProps.readonly) {
this.debugDomain = null;
}
if (this.debugDomain) {
this.state.isValid = await this.quickValidityCheck(nextProps);
if (!this.state.isValid) {
this.state.recordCount = 0;
nextProps.record.setInvalidField(nextProps.name);
}
} else {
this.checkProps(nextProps); // not awaited
}
if (nextProps.isFoldable) {
this.loadFacets(nextProps);
}
});
useBus(this.props.record.model.bus, "NEED_LOCAL_CHANGES", async (ev) => {
if (this.debugDomain) {
const props = this.props;
const handleChanges = async () => {
await props.record.update({ [props.name]: this.debugDomain });
const isValid = await this.quickValidityCheck(props);
if (isValid) {
this.debugDomain = null; // will allow the count to be loaded if needed
} else {
this.state.isValid = false;
this.state.recordCount = 0;
props.record.setInvalidField(props.name);
}
};
ev.detail.proms.push(handleChanges());
}
});
}
allowExpressions(props) {
return props.allowExpressions;
}
getContext(props = this.props) {
return props.context;
}
getDomain(props = this.props) {
return props.record.data[props.name] || "[]";
}
getEvaluatedDomain(props = this.props) {
const domainStringRepr = this.getDomain(props);
const evalContext = this.getContext(props);
if (domainContainsExpressions(domainStringRepr)) {
const allowExpressions = this.allowExpressions(props);
if (domainStringRepr !== this.lastDomainChecked) {
this.lastDomainChecked = domainStringRepr;
this.notification.add(
allowExpressions
? _t("The domain involves non-literals. Their evaluation might fail.")
: _t("The domain should not involve non-literals")
);
}
if (!allowExpressions) {
return { isInvalid: true };
}
}
try {
Registry / API
- Registry name
DomainField- Category
—- Module
web- Slug
domain-field- Nav group
forms