OWL
forms
Date Time Field
Odoo 19 OWL component — Date Time Field (views)
Live preview
Interactive
Source excerpt
web/static/src/views/fields/datetime/datetime_field.js
import { Component, onWillRender, useEffect, useRef, useState } from "@odoo/owl";
import { useDateTimePicker } from "@web/core/datetime/datetime_picker_hook";
import { areDatesEqual, deserializeDate, deserializeDateTime, today } from "@web/core/l10n/dates";
import { _t } from "@web/core/l10n/translation";
import { evaluateBooleanExpr } from "@web/core/py_js/py";
import { registry } from "@web/core/registry";
import { ensureArray } from "@web/core/utils/arrays";
import { exprToBoolean } from "@web/core/utils/strings";
import { FIELD_WIDTHS } from "@web/views/list/column_width_hook";
import { formatDate, formatDateTime } from "../formatters";
import { standardFieldProps } from "../standard_field_props";
const { DateTime } = luxon;
function getFormattedPlaceholder(value, type, options) {
if (value instanceof luxon.DateTime) {
return type === "date" ? formatDate(value, options) : formatDateTime(value, options);
}
return value || "";
}
/**
* @typedef {luxon.DateTime} DateTime
*
* @typedef {import("../standard_field_props").StandardFieldProps & {
* endDateField?: string;
* maxDate?: string;
* minDate?: string;
* placeholder?: string;
* required?: boolean;
* rounding?: number;
* startDateField?: string;
* warnFuture?: boolean;
* showSeconds?: boolean;
* showTime?: boolean;
* numeric?: boolean;
* minPrecision?: string;
* maxPrecision?: string;
* }} DateTimeFieldProps
*
* @typedef {import("@web/core/datetime/datetime_picker").DateTimePickerProps} DateTimePickerProps
*/
/** @extends {Component<DateTimeFieldProps>} */
export class DateTimeField extends Component {
static props = {
...standardFieldProps,
endDateField: { type: String, optional: true },
maxDate: { type: String, optional: true },
minDate: { type: String, optional: true },
alwaysRange: { type: Boolean, optional: true },
placeholder: { type: String, optional: true },
required: { type: Boolean, optional: true },
rounding: { type: Number, optional: true },
startDateField: { type: String, optional: true },
numeric: { type: Boolean, optional: true },
warnFuture: { type: Boolean, optional: true },
showSeconds: { type: Boolean, optional: true },
showTime: { type: Boolean, optional: true },
minPrecision: {
type: String,
optional: true,
validate: (props) => ["days", "months", "years", "decades"].includes(props),
},
maxPrecision: {
type: String,
optional: true,
validate: (props) => ["days", "months", "years", "decades"].includes(props),
},
};
static defaultProps = {
showSeconds: false,
showTime: true,
numeric: false,
};
static template = "web.DateTimeField";
//-------------------------------------------------------------------------
// Getters
//-------------------------------------------------------------------------
get endDateField() {
return this.relatedField ? this.props.endDateField || this.props.name : null;
}
get field() {
return this.props.record.fields[this.props.name];
}
get relatedField() {
return this.props.startDateField || this.props.endDateField;
}
get startDateField() {
return this.props.startDateField || this.props.name;
}
get values() {
return ensureArray(this.state.value);
}
//-------------------------------------------------------------------------
// Lifecycle
//-------------------------------------------------------------------------
setup() {
const getPickerProps = () => {
const value = this.getRecordValue();
/** @type {DateTimePickerProps} */
const pickerProps = {
value,
type: this.field.type,
range: this.isRange(value),
showRangeToggler:
this.relatedField && !this.props.required && !this.props.alwaysRange,
onToggleRange,
};
if (this.props.maxDate) {
pickerProps.maxDate = this.parseLimitDate(this.props.maxDate);
Registry / API
- Registry name
DateTimeField- Category
—- Module
web- Slug
date-time-field- Nav group
forms