OWL
data_display
Search Panel
Odoo 19 OWL component — Search Panel (search)
Live preview
Interactive
Source excerpt
web/static/src/search/search_panel/search_panel.js
import { Dropdown } from "@web/core/dropdown/dropdown";
import { useBus } from "@web/core/utils/hooks";
import {
Component,
onMounted,
onWillStart,
onWillUpdateProps,
reactive,
useEffect,
useRef,
useState,
} from "@odoo/owl";
import { browser } from "@web/core/browser/browser";
import { exprToBoolean } from "@web/core/utils/strings";
import { useSetupAction } from "@web/search/action_hook";
//-------------------------------------------------------------------------
// Helpers
//-------------------------------------------------------------------------
const isFilter = (s) => s.type === "filter";
const isActiveCategory = (s) => s.type === "category" && s.activeValueId;
/**
* @param {Map<string | false, Object>} values
* @returns {Object[]}
*/
const nameOfCheckedValues = (values) => {
const names = [];
for (const [, value] of values) {
if (value.checked) {
names.push(value.display_name);
}
}
return names;
};
/**
* Search panel
*
* Represent an extension of the search interface located on the left side of
* the view. It is divided in sections defined in a "<searchpanel>" node located
* inside of a "<search>" arch. Each section is represented by a list of different
* values (categories or ungrouped filters) or groups of values (grouped filters).
* Its state is directly affected by its model (@see SearchModel).
*/
export class SearchPanel extends Component {
static template = "web.SearchPanel";
static props = {};
static components = {
Dropdown,
};
static subTemplates = {
section: "web.SearchPanel.Section",
category: "web.SearchPanel.Category",
filtersGroup: "web.SearchPanel.FiltersGroup",
};
setup() {
this.keyExpandSidebar = `search_panel_expanded,${this.env.config.viewId},${this.env.config.actionId}`;
this.state = useState({
active: {},
expanded: {},
sidebarExpanded: true,
});
this.hasImportedState = false;
this.root = useRef("root");
this.scrollTop = 0;
this.dropdownStates = {};
this.width = "10px";
this.importState(this.env.searchPanelState);
const sidebarExpandedPreference = browser.localStorage.getItem(this.keyExpandSidebar);
if (sidebarExpandedPreference !== null) {
this.state.sidebarExpanded = exprToBoolean(sidebarExpandedPreference);
}
useBus(this.env.searchModel, "update", async () => {
await this.env.searchModel.sectionsPromise;
this.updateActiveValues();
this.render();
});
useEffect(
(el) => {
if (el && this.hasImportedState) {
el.style["min-width"] = this.width;
el.scroll({ top: this.scrollTop });
}
},
() => [this.root.el]
);
useSetupAction({
getGlobalState: () => ({
searchPanel: this.exportState(),
}),
});
onWillStart(async () => {
await this.env.searchModel.sectionsPromise;
this.expandDefaultValue();
this.expandValues();
this.updateActiveValues();
});
onWillUpdateProps(async () => {
await this.env.searchModel.sectionsPromise;
this.updateActiveValues();
});
onMounted(() => {
this.updateGroupHeadersChecked();
});
}
//---------------------------------------------------------------------
// Getters
//---------------------------------------------------------------------
Registry / API
- Registry name
SearchPanel- Category
—- Module
web- Slug
search-panel- Nav group
data_display