I tried implementing custom search provider. But when I search, the element is not being highlighted, and also as I hover on the search results list, it gives error:
Cannot read properties of undefined (reading 'id')
TypeError: Cannot read properties of undefined (reading 'id')
at http://localhost:3005/static/js/bundle.js:65545:77
at Array.filter (<anonymous>)
Code for:
- CustomSearchProvider:
export default class CustomSearchPadProvider {
constructor(searchPad, eventBus, elementRegistry ) {
this.searchPad = searchPad;
this.eventBus = eventBus;
this.elementRegistry = elementRegistry;
// Register the provider
searchPad.registerProvider(this);
}
/**
* Define how search entries are filtered or modified.
* @param {String} pattern - The search pattern entered by the user.
* @returns {Array} List of elements matching the pattern.
*/
find(pattern) {
console.log("Searching for:", pattern);
if (!pattern) return [];
const allElements = this.elementRegistry.getAll();
// Filter elements based on search pattern
const matchingElements = allElements
.filter((element) => {
return (
element.businessObject &&
element.businessObject.name &&
element.businessObject.name.toLowerCase().includes(pattern.toLowerCase())
);
})
.map((element) => {
const name = element.businessObject.name;
const id = element.id;
const type = element.type;
// Preserve all original properties
const newElement = {
id,
type,
businessObject: element.businessObject, // Ensure businessObject is not lost
};
// Highlight matched part in primaryTokens
const primaryTokens = [];
const lowerName = name.toLowerCase();
const lowerPattern = pattern.toLowerCase();
let startIndex = lowerName.indexOf(lowerPattern);
if (startIndex !== -1) {
if (startIndex > 0) {
primaryTokens.push({ normal: name.substring(0, startIndex) });
}
primaryTokens.push({ matched: name.substring(startIndex, startIndex + pattern.length) });
if (startIndex + pattern.length < name.length) {
primaryTokens.push({ normal: name.substring(startIndex + pattern.length) });
}
} else {
primaryTokens.push({ normal: name });
}
return {
element: newElement, // Store the new element object separately
primaryTokens, // Properly formatted primaryTokens
secondaryTokens: [{ normal: id }], // Ensure secondaryTokens follow the correct format
};
});
return matchingElements;
}
}
CustomSearchPadProvider.$inject = ["searchPad", "eventBus", "elementRegistry"];
This is registered as additional module in modeler while loading flow modeler.
- CustomSearchPad:
export default class CustomSearchPad {
constructor(eventBus, elementRegistry, canvas, overlays) {
this.eventBus = eventBus;
this.elementRegistry = elementRegistry;
this.canvas = canvas;
this.overlays = overlays;
this.highlightElements = this.highlightElements.bind(this);
console.log("CustomSearchPadProvider initialized"); // Debugging log
}
find(pattern) {
if (!pattern) return [];
// Get all elements from the registry
const allElements = this.elementRegistry.getAll();
// Filter elements based on search pattern
const matchingElements = allElements.filter(element => {
return element.businessObject &&
element.businessObject.name &&
element.businessObject.name.toLowerCase().includes(pattern.toLowerCase());
});
return matchingElements;
}
}
CustomSearchPad.$inject = ['eventBus', 'elementRegistry', 'canvas', 'overlays'];
This file is passed into CustomModule, which has following:
const CustomModule = {
__init__: ['customContextPad', 'customSearchPad'],
customContextPad: ['type', CustomContextPad],
customSearchPad: ['type', CustomSearchPad]
};
@philippfromme can you please help!!