catalog.fn.suggest()
Provides autocomplete suggestions for an attribute. Returns the distinct values that match the user input, with the keys of the items that have each value, for search-as-you-type and autocomplete.
Syntax
list.catalog.fn.suggest(options)Parameters
attributestringRequired- The attribute to get suggestions for. A dotted path such as 'brand.name' resolves through the reference
valuestring | numberRequired- The search term. A bare string is a case-insensitive prefix match; wrap it in slashes ('/pattern/') for a regular expression; '' returns every value (up to max)
regexFlagsstringOptional- Flags for a '/pattern/' value, e.g. 'i' for case-insensitive. Ignored for any other value; invalid flags return no suggestions
maxnumberOptional- Maximum number of suggestions to return (default: 20)
transform('lowercase' | 'removeWhitespace' | 'trim')[]Optional- Normalize values before matching
calculateResultKeysbooleanOptional- Include item keys in results (default: true)
excludeUndefinedsbooleanOptional- Exclude undefined values (default: true)
excludeNullsbooleanOptional- Exclude null values (default: true)
relevantData'filtered' | 'all' | 'excludeQuery'Optional- Which items to suggest from: 'filtered' (default, the list's current result), 'all' (ignore the query), or 'excludeQuery' (the current query without excludeQuery)
excludeQueryPartial<DcuplQuery | DcuplQueryGroup>Optional- Condition or group (e.g. { groupKey: 'category' }) to leave out of the query when relevantData is 'excludeQuery'
Return type
Returns an array of Suggestion objects:
// Can be imported from @dcupl/common
type Suggestion = {
value: string; // The raw value: typed string; at runtime a number or boolean for numeric and boolean attributes, the ISO string for dates
keys: string[]; // Item keys with this value ([] if calculateResultKeys: false)
}Usage notes
- A bare string matches the start of the value, ignoring case: 'lap' suggests "Laptop Pro" but not "Gaming Laptop"
- Wrap the term in slashes ('/pro/') to match it anywhere; the pattern is case-sensitive unless you set regexFlags: 'i' (flags never go after the closing slash: '/pro/i' is not a regex, just a plain prefix). Escape regex characters in user input
- Empty search term returns all unique values (up to max)
- Dotted paths work: attribute: "brand.name" suggests the names of the referenced brands, with the keys of the items that reference them
- Suggestions respect current query filters by default (relevantData: "filtered")
- Use transform options for flexible matching (lowercase, removeWhitespace, trim)
- Performance: Set calculateResultKeys: false when you only need values, not item references
- Performance: Use max parameter to limit results - default is 20
- Performance: Avoid regex patterns for simple prefix matching - prefix is faster
- Troubleshooting: Use relevantData: "all" if you want suggestions regardless of current filters
Related methods
catalog.fn.facets()— Get all unique values with counts for building filterscatalog.query.addCondition()— Apply filters based on selected suggestioncatalog.query.many()— Get the items behind the result keys
Related guides/docs
Examples
Product search autocomplete
Basic autocomplete implementation with prefix matching and transform options.
const productList = dcupl.lists.create({ modelKey: 'Product' });
function handleSearchInput(inputValue: string) {
const suggestions = productList.catalog.fn.suggest({
attribute: 'name',
value: inputValue,
max: 10,
transform: ['lowercase', 'trim'],
});
// Render suggestions
const dropdown = document.getElementById('suggestions')!;
dropdown.innerHTML = suggestions
.map((s) => '<div class="suggestion">' + s.value + ' (' + s.keys.length + ')</div>')
.join('');
}
// Attach to input
document.getElementById('search')!.addEventListener('input', (e) => {
handleSearchInput((e.target as HTMLInputElement).value);
});Category filter suggestions
Get all category values for a filter dropdown, showing counts based on current filters.
const productList = dcupl.lists.create({ modelKey: 'Product' });
// An empty search term returns every value (up to max)
const categories = productList.catalog.fn.suggest({
attribute: 'category',
value: '', // Empty = all values
max: 50, // default is 20
relevantData: 'filtered', // Respect current filters
});
// Build filter options with counts
const filterOptions = categories.map((s) => ({
label: s.value,
count: s.keys.length,
}));
console.log('Available Categories:');
filterOptions.forEach((opt) => {
console.log(' ' + opt.label + ' (' + opt.count + ')');
});Brand search with icons
Enrich suggestions with additional metadata like counts and custom icons.
const productList = dcupl.lists.create({ modelKey: 'Product' });
// Brand icon mapping
const brandIcons: Record<string, string> = {
Nike: '👟',
Apple: '🍎',
Samsung: '📱',
Sony: '🎮',
};
function searchBrands(query: string) {
const suggestions = productList.catalog.fn.suggest({
attribute: 'brand',
value: query,
max: 8,
transform: ['lowercase'],
});
return suggestions.map((s) => ({
brand: s.value,
count: s.keys.length,
icon: brandIcons[s.value] || '🏷️',
}));
}
const results = searchBrands('s');
results.forEach((r) => {
console.log(r.icon + ' ' + r.brand + ' (' + r.count + ' products)');
});Color suggestions with mapping
Map color suggestions to hex codes or other visual representations.
const productList = dcupl.lists.create({ modelKey: 'Product' });
const colorHex: Record<string, string> = {
red: '#FF0000',
blue: '#0000FF',
green: '#00FF00',
black: '#000000',
white: '#FFFFFF',
};
function getColorSuggestions(query: string) {
const suggestions = productList.catalog.fn.suggest({
attribute: 'color',
value: query,
transform: ['lowercase'],
});
return suggestions.map((s) => ({
name: s.value,
hex: colorHex[s.value.toLowerCase()] || '#CCCCCC',
count: s.keys.length,
}));
}
const colors = getColorSuggestions('bl');
colors.forEach((c) => {
console.log(c.hex + ' ' + c.name + ' (' + c.count + ')');
});Country suggestions with flags
Enrich country suggestions with flag emojis for visual display.
const customerList = dcupl.lists.create({ modelKey: 'Customer' });
const countryFlags: Record<string, string> = {
'United States': '🇺🇸',
Germany: '🇩🇪',
Japan: '🇯🇵',
France: '🇫🇷',
'United Kingdom': '🇬🇧',
};
function searchCountries(query: string) {
const suggestions = customerList.catalog.fn.suggest({
attribute: 'country',
value: query,
max: 10,
transform: ['trim'],
});
return suggestions.map((s) => ({
country: s.value,
flag: countryFlags[s.value] || '🏳️',
customers: s.keys.length,
}));
}
const results = searchCountries('un');
results.forEach((r) => {
console.log(r.flag + ' ' + r.country + ' - ' + r.customers + ' customers');
});Course title with full item lookup
Use suggestion keys to fetch complete item details for rich autocomplete.
const courseList = dcupl.lists.create({ modelKey: 'Course' });
// suggest() and query.one() are synchronous
function searchCourses(query: string) {
const suggestions = courseList.catalog.fn.suggest({
attribute: 'title',
value: query,
max: 5,
calculateResultKeys: true,
});
// Look up the first matching course of each suggestion
return suggestions.map((s) => {
const course = courseList.catalog.query.one({ itemKey: s.keys[0] });
return {
title: s.value,
instructor: course?.instructor,
duration: course?.duration,
rating: course?.rating,
matchCount: s.keys.length,
};
});
}
const results = searchCourses('java');
results.forEach((c) => {
console.log(c.title);
console.log(' By: ' + c.instructor + ' | ' + c.duration + 'h | ⭐' + c.rating);
});Hashtag suggestions
Handle special characters in input by preprocessing before suggestion.
const postList = dcupl.lists.create({ modelKey: 'Post' });
function suggestHashtags(input: string) {
// Remove # prefix if present
const query = input.startsWith('#') ? input.slice(1) : input;
const suggestions = postList.catalog.fn.suggest({
attribute: 'hashtags',
value: query,
max: 10,
transform: ['lowercase', 'removeWhitespace'],
});
return suggestions.map((s) => ({
tag: '#' + s.value,
posts: s.keys.length,
}));
}
const tags = suggestHashtags('#java');
tags.forEach((t) => {
console.log(t.tag + ' (' + t.posts + ' posts)');
});Campaign code suggestions (uppercase)
Prefix matching ignores case, so lowercase input finds uppercase codes without any transform.
const campaignList = dcupl.lists.create({ modelKey: 'Campaign' });
function suggestCampaignCodes(input: string) {
// A bare string is a case-insensitive prefix match
const suggestions = campaignList.catalog.fn.suggest({
attribute: 'code',
value: input,
max: 10,
});
return suggestions.map((s) => ({
code: s.value,
usageCount: s.keys.length,
}));
}
const codes = suggestCampaignCodes('sum');
codes.forEach((c) => {
console.log(c.code + ' (used ' + c.usageCount + ' times)');
});
// Typing "sum" matches codes like SUMMER2024 and SUMMERSALESubstring suggestions (regex + regexFlags)
Wrap the term in slashes to match it anywhere in the value. The pattern is case-sensitive; set regexFlags for flags.
const productList = dcupl.lists.create({ modelKey: 'Product' });
const escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\]\\]/g, (char) => '\\' + char);
function suggestContaining(input: string) {
return productList.catalog.fn.suggest({
attribute: 'name',
value: `/${escapeRegExp(input.trim())}/`,
regexFlags: 'i', // flags go here: '/phone/i' is not a regex (plain prefix text)
max: 10,
});
}
// '/phone/' matches "Smartphone Case"; with regexFlags 'i' also "Galaxy Phone"
const results = suggestContaining('phone');
console.log(results.map((s) => s.value));// Basic suggestions for productName attribute
const suggestions = list.catalog.fn.suggest({
attribute: 'productName',
value: '/pro/', // regex for 'pro' anywhere in the value
max: 10,
transform: ['lowercase'],
});[]