OWL
data_display
Search Bar
Odoo 19 OWL component — Search Bar (search)
Live preview
Interactive
Source excerpt
web/static/src/search/search_bar/search_bar.js
import { Domain } from "@web/core/domain";
import { serializeDate, serializeDateTime } from "@web/core/l10n/dates";
import { registry } from "@web/core/registry";
import { KeepLast } from "@web/core/utils/concurrency";
import { useAutofocus, useBus, useChildRef, useService } from "@web/core/utils/hooks";
import { DomainSelectorDialog } from "@web/core/domain_selector_dialog/domain_selector_dialog";
import { fuzzyTest } from "@web/core/utils/search";
import { _t } from "@web/core/l10n/translation";
import { SearchBarMenu } from "../search_bar_menu/search_bar_menu";
import { Component, status, useRef, useState } from "@odoo/owl";
import { useDropdownState } from "@web/core/dropdown/dropdown_hooks";
import { hasTouch } from "@web/core/browser/feature_detection";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { useNavigation } from "@web/core/navigation/navigation";
const parsers = registry.category("parsers");
const parseValue = (value, fieldType) => {
const parser = parsers.contains(fieldType) ? parsers.get(fieldType) : (str) => str;
switch (fieldType) {
case "date": {
return serializeDate(parser(value));
}
case "datetime": {
return serializeDateTime(parser(value));
}
case "many2one": {
return value;
}
default: {
return parser(value);
}
}
};
const CHAR_FIELDS = ["char", "html", "many2many", "many2one", "one2many", "text", "properties"];
const FOLDABLE_TYPES = ["properties", "many2one", "many2many"];
let nextItemId = 1;
const SUB_ITEMS_DEFAULT_LIMIT = 8;
export const DROPDOWN_CLOSE_DELAY = 10;
export class SearchBar extends Component {
static template = "web.SearchBar";
static components = {
SearchBarMenu,
Dropdown,
DropdownItem,
};
static props = {
autofocus: { type: Boolean, optional: true },
slots: {
type: Object,
optional: true,
shape: {
default: { optional: true },
"search-bar-additional-menu": { optional: true },
},
},
toggler: {
type: Object,
optional: true,
},
};
static defaultProps = {
autofocus: true,
};
setup() {
this.dialogService = useService("dialog");
this.fields = this.env.searchModel.searchViewFields;
this.searchItemsFields = this.env.searchModel.getSearchItems((f) => f.type === "field");
this.root = useRef("root");
this.ui = useService("ui");
this.visibilityState = useState(this.props.toggler?.state || { showSearchBar: true });
// core state
this.state = useState({
expanded: [],
query: "",
subItemsLimits: {},
});
// derived state
this.items = useState([]);
this.subItems = {};
this.facetContainerRef = useRef("facetContainerRef");
this.menuRef = useChildRef();
this.setupFacetNavigation();
this.inputDropdownState = useDropdownState();
this.inputDropdownNavOptions = this.getDropdownNavigation();
this.searchBarDropdownState = useDropdownState();
this.orm = useService("orm");
this.keepLast = new KeepLast();
this.inputRef =
this.env.config.disableSearchBarAutofocus || !this.props.autofocus
? useRef("autofocus")
: useAutofocus({ mobile: this.ui.isSmall }); // only force the focus on touch devices on small screens
useBus(this.env.searchModel, "focus-search", () => {
this.inputRef.el.focus();
});
useBus(this.env.searchModel, "update", this.render);
}
/**
* @param {number} id
* @param {Object}
*/
getSearchItem(id) {
return this.env.searchModel.searchItems[id];
Registry / API
- Registry name
SearchBar- Category
—- Module
web- Slug
search-bar- Nav group
data_display