Feel free to share demo-related thoughts here.
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Thank you for the feedback!
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Backend API
<template>
<div id="selectbox-demo">
<div class="widget-container">
<div class="dx-fieldset">
<div class="dx-fieldset-header">SearchBox</div>
<div class="dx-field">
<div class="dx-field-label">Product</div>
<div class="dx-field-value">
<DxSelectBox
:search-enabled="true"
:data-source="products"
:input-attr="{ 'aria-label': 'Product' }"
:search-mode="searchModeOption"
:search-expr="searchExprOption"
:search-timeout="searchTimeoutOption"
:min-search-length="minSearchLengthOption"
:show-data-before-search="showDataBeforeSearchOption"
display-expr="Name"
value-expr="ID"
/>
</div>
</div>
</div>
<div class="dx-fieldset">
<div class="dx-fieldset-header">EditBox</div>
<div class="dx-field">
<div class="dx-field-label">Product</div>
<div class="dx-field-value">
<DxSelectBox
v-model:selectedItem="editBoxValue"
:value="product"
:input-attr="{ 'aria-label': 'Simple Product' }"
:accept-custom-value="true"
:data-source="productsDataSource"
display-expr="Name"
value-expr="ID"
@customItemCreating="customItemCreating($event)"
/>
</div>
</div>
<div class="dx-field current-product">
Current product:
<span
v-if="editBoxValue"
class="current-value"
>
{{ editBoxValue.Name }} (ID: {{ editBoxValue.ID }})
</span>
<span
v-else
class="current-value"
> Not selected </span>
</div>
</div>
</div>
<div class="options">
<div class="caption">SearchBox Options</div>
<div class="option">
<div>Search Mode</div>
<DxSelectBox
v-model:value="searchModeOption"
:input-attr="{ 'aria-label': 'Search Mode' }"
:items="['contains', 'startswith']"
/>
</div>
<div class="option">
<div>Search Expression</div>
<DxSelectBox
v-model:value="searchExprOption"
:items="searchExprItems"
:input-attr="{ 'aria-label': 'Search Expression' }"
display-expr="name"
value-expr="value"
/>
</div>
<div class="option">
<div>Search Timeout</div>
<DxNumberBox
v-model:value="searchTimeoutOption"
:min="0"
:max="5000"
:show-spin-buttons="true"
:step="100"
:input-attr="{ 'aria-label': 'Search Timeout' }"
/>
</div>
<div class="option">
<div>Minimum Search Length</div>
<DxNumberBox
v-model:value="minSearchLengthOption"
:min="0"
:max="5"
:show-spin-buttons="true"
:input-attr="{ 'aria-label': 'Minimum Search Length' }"
/>
</div>
<div class="option">
<DxCheckBox
v-model:value="showDataBeforeSearchOption"
text="Show Data Before Search"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { DxSelectBox } from 'devextreme-vue/select-box';
import { DxNumberBox } from 'devextreme-vue/number-box';
import { DxCheckBox } from 'devextreme-vue/check-box';
import DataSource from 'devextreme/data/data_source';
import { products, simpleProducts } from './data.ts';
const productsDataSource = new DataSource({
store: {
data: simpleProducts,
type: 'array',
key: 'ID',
},
});
const editBoxValue = ref(simpleProducts[0]);
const product = ref(simpleProducts[0].ID);
const searchModeOption = ref('contains');
const searchExprOption = ref('Name');
const searchTimeoutOption = ref(200);
const minSearchLengthOption = ref(0);
const showDataBeforeSearchOption = ref(false);
const searchExprItems = [
{
name: "'Name'",
value: 'Name',
},
{
name: "['Name', 'Category']",
value: ['Name', 'Category'],
},
];
function customItemCreating(data) {
if (!data.text) {
data.customItem = null;
return;
}
const productIds = simpleProducts.map((item) => item.ID);
const incrementedId = Math.max.apply(null, productIds) + 1;
const newItem = {
Name: data.text,
ID: incrementedId,
};
data.customItem = productsDataSource
.store()
.insert(newItem)
.then(() => productsDataSource.load())
.then(() => newItem)
.catch((error) => {
throw error;
});
}
</script>
<style scoped>
.widget-container {
margin-right: 320px;
}
.current-product {
padding-top: 11px;
}
.current-value {
font-weight: bold;
}
.options {
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 260px;
}
.caption {
font-weight: 500;
font-size: 18px;
}
.option {
margin-top: 10px;
}
</style>
window.exports = window.exports || {};
window.config = {
transpiler: 'plugin-babel',
meta: {
'*.vue': {
loader: 'vue-loader',
},
'*.ts': {
loader: 'demo-ts-loader',
},
'*.svg': {
loader: 'svg-loader',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
},
paths: {
'root:': '../../../../',
'npm:': 'https://unpkg.com/',
},
map: {
'vue': 'npm:vue@3.2.47/dist/vue.esm-browser.js',
'vue-loader': 'npm:dx-systemjs-vue-browser@1.1.1/index.js',
'demo-ts-loader': 'root:utils/demo-ts-loader.js',
'svg-loader': 'root:utils/svg-loader.js',
'mitt': 'npm:mitt/dist/mitt.umd.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign@1.1.0',
'devextreme': 'npm:devextreme@24.1.5/cjs',
'devextreme-vue': 'npm:devextreme-vue@24.1.5/cjs',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.10/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.56/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme-vue': {
main: 'index.js',
},
'devextreme': {
defaultExtension: 'js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.13/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
},
};
System.config(window.config);
export const simpleProducts = [
{ Name: 'HD Video Player', ID: 0 },
{ Name: 'SuperHD Video Player', ID: 1 },
{ Name: 'SuperPlasma 50', ID: 2 },
{ Name: 'SuperLED 50', ID: 3 },
{ Name: 'SuperLED 42', ID: 4 },
{ Name: 'SuperLCD 55', ID: 5 },
{ Name: 'SuperLCD 42', ID: 6 },
{ Name: 'SuperPlasma 65', ID: 7 },
{ Name: 'SuperLCD 70', ID: 8 },
{ Name: 'Projector Plus', ID: 9 },
{ Name: 'Projector PlusHT', ID: 10 },
{ Name: 'ExcelRemote IR', ID: 11 },
{ Name: 'ExcelRemote Bluetooth', ID: 12 },
{ Name: 'ExcelRemote IP', ID: 13 },
];
export const products = [{
ID: 1,
Name: 'HD Video Player',
Price: 330,
Current_Inventory: 225,
Backorder: 0,
Manufacturing: 10,
Category: 'Video Players',
ImageSrc: '../../../../images/products/1.png',
}, {
ID: 2,
Name: 'SuperHD Video Player',
Price: 400,
Current_Inventory: 150,
Backorder: 0,
Manufacturing: 25,
Category: 'Video Players',
ImageSrc: '../../../../images/products/2.png',
}, {
ID: 3,
Name: 'SuperPlasma 50',
Price: 2400,
Current_Inventory: 0,
Backorder: 0,
Manufacturing: 0,
Category: 'Televisions',
ImageSrc: '../../../../images/products/3.png',
}, {
ID: 4,
Name: 'SuperLED 50',
Price: 1600,
Current_Inventory: 77,
Backorder: 0,
Manufacturing: 55,
Category: 'Televisions',
ImageSrc: '../../../../images/products/4.png',
}, {
ID: 5,
Name: 'SuperLED 42',
Price: 1450,
Current_Inventory: 445,
Backorder: 0,
Manufacturing: 0,
Category: 'Televisions',
ImageSrc: '../../../../images/products/5.png',
}, {
ID: 6,
Name: 'SuperLCD 55',
Price: 1350,
Current_Inventory: 345,
Backorder: 0,
Manufacturing: 5,
Category: 'Televisions',
ImageSrc: '../../../../images/products/6.png',
}, {
ID: 7,
Name: 'SuperLCD 42',
Price: 1200,
Current_Inventory: 210,
Backorder: 0,
Manufacturing: 20,
Category: 'Televisions',
ImageSrc: '../../../../images/products/7.png',
}, {
ID: 8,
Name: 'SuperPlasma 65',
Price: 3500,
Current_Inventory: 0,
Backorder: 0,
Manufacturing: 0,
Category: 'Televisions',
ImageSrc: '../../../../images/products/8.png',
}, {
ID: 9,
Name: 'SuperLCD 70',
Price: 4000,
Current_Inventory: 95,
Backorder: 0,
Manufacturing: 5,
Category: 'Televisions',
ImageSrc: '../../../../images/products/9.png',
}, {
ID: 10,
Name: 'DesktopLED 21',
Price: 175,
Current_Inventory: null,
Backorder: 425,
Manufacturing: 75,
Category: 'Monitors',
ImageSrc: '../../../../images/products/10.png',
}, {
ID: 12,
Name: 'DesktopLCD 21',
Price: 170,
Current_Inventory: 210,
Backorder: 0,
Manufacturing: 60,
Category: 'Monitors',
ImageSrc: '../../../../images/products/12.png',
}, {
ID: 13,
Name: 'DesktopLCD 19',
Price: 160,
Current_Inventory: 150,
Backorder: 0,
Manufacturing: 210,
Category: 'Monitors',
ImageSrc: '../../../../images/products/13.png',
}, {
ID: 14,
Name: 'Projector Plus',
Price: 550,
Current_Inventory: null,
Backorder: 55,
Manufacturing: 10,
Category: 'Projectors',
ImageSrc: '../../../../images/products/14.png',
}, {
ID: 15,
Name: 'Projector PlusHD',
Price: 750,
Current_Inventory: 110,
Backorder: 0,
Manufacturing: 90,
Category: 'Projectors',
ImageSrc: '../../../../images/products/15.png',
}, {
ID: 16,
Name: 'Projector PlusHT',
Price: 1050,
Current_Inventory: 0,
Backorder: 75,
Manufacturing: 57,
Category: 'Projectors',
ImageSrc: '../../../../images/products/16.png',
}, {
ID: 17,
Name: 'ExcelRemote IR',
Price: 150,
Current_Inventory: 650,
Backorder: 0,
Manufacturing: 190,
Category: 'Automation',
ImageSrc: '../../../../images/products/17.png',
}, {
ID: 18,
Name: 'ExcelRemote Bluetooth',
Price: 180,
Current_Inventory: 310,
Backorder: 0,
Manufacturing: 0,
Category: 'Automation',
ImageSrc: '../../../../images/products/18.png',
}, {
ID: 19,
Name: 'ExcelRemote IP',
Price: 200,
Current_Inventory: 0,
Backorder: 325,
Manufacturing: 225,
Category: 'Automation',
ImageSrc: '../../../../images/products/19.png',
}];
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
<!DOCTYPE html>
<html lang="en">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.1.5/css/dx.light.css" />
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" />
<script type="module">
import * as vueCompilerSFC from "https://unpkg.com/@vue/compiler-sfc@3.4.16/dist/compiler-sfc.esm-browser.js";
window.vueCompilerSFC = vueCompilerSFC;
</script>
<script src="https://unpkg.com/typescript@4.9.5/lib/typescript.js"></script>
<script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script>
<script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script>
<script type="text/javascript" src="config.js"></script>
<script type="text/javascript">
System.import("./index.ts");
</script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"> </div>
</div>
</body>
</html>
The following properties help you configure the feature:
- searchExpr
Specifies one or several data fields to search. - searchMode
Specifies whether found items should contain the typed-in string or start with it. - searchTimeout
Specifies the delay between the moment a user stops typing and the moment the search is executed. - minSearchLength
Specifies the minimum number of characters that a user should type in to trigger the search. - showDataBeforeSearch
Specifies whether the SelectBox should display the unfiltered item list until a user have typed in the minimum number of characters (minSearchLength).
Set the acceptCustomValue property to true to allow users to add values to the SelectBox. You should also implement the onCustomItemCreating handler to create new data source entries.