
Research
/Security News
11 Malicious Go Packages Distribute Obfuscated Remote Payloads
Socket uncovered 11 malicious Go packages using obfuscated loaders to fetch and execute second-stage payloads via C2 domains.
multi-selector-dropdown
Advanced tools
A React component for multi-select dropdown with API-driven options, search capability, and add new option functionality
A powerful React component for multi-select dropdown with API-driven options, search capability, and add new option functionality. Built with TypeScript and designed for modern React applications.
npm install multi-selector-dropdown
This package requires the following peer dependencies:
npm install react react-dom react-bootstrap-typeahead
You'll also need to import the required CSS in your application:
import 'react-bootstrap-typeahead/css/Typeahead.css';
A simple example showing the basic functionality of the component:
import { useState, useEffect } from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'react-bootstrap-typeahead/css/Typeahead.css';
import './App.css'; // Assuming you have some custom styles
interface UserOption {
id: string | number;
label: string;
}
function App() {
const [selectedOptions, setSelectedOptions] = useState<UserOption[]>([]);
const [options, setOptions] = useState<UserOption[]>([]);
useEffect(() => {
const dummyUsers: UserOption[] = [
{ id: '1', label: 'Alice Johnson' },
{ id: '2', label: 'Bob Smith' },
{ id: '3', label: 'Charlie Davis' },
{ id: '4', label: 'Diana Ross' },
{ id: '5', label: 'Ethan Brown' },
];
setOptions(dummyUsers);
}, []);
const handleAddNew = (value: string): UserOption => {
const newUser = { id: `new-${Date.now()}`, label: value };
setOptions((prev) => [...prev, newUser]);
return newUser;
};
return (
<div className="min-vh-100 d-flex align-items-center justify-content-center bg-light">
<div className="container p-4 rounded-4 shadow-lg" style={{ maxWidth: '900px', backgroundColor: '#ffffff' }}>
<h2 className="text-center text-primary fw-bold mb-4">Multi-Selector Dropdown</h2>
<p className="text-center text-muted mb-5">
This example uses hardcoded data instead of fetching from an API.
</p>
<div className="row justify-content-center">
<div className="col-md-10">
<label className="form-label text-dark fw-semibold">Select Users*</label>
<Typeahead
id="user-multi-select"
labelKey="label"
multiple
allowNew
newSelectionPrefix="Add new user: "
options={options}
placeholder="Search and select users..."
onChange={(selected: any[]) => {
const cleanOptions: UserOption[] = selected.map((item) =>
typeof item === 'string' ? handleAddNew(item) : item
);
setSelectedOptions(cleanOptions);
}}
selected={selectedOptions}
className="bg-white rounded-3 shadow-sm border border-secondary"
/>
</div>
</div>
{selectedOptions.length > 0 && (
<div className="mt-5">
<h4 className="text-dark text-center fw-semibold mb-4">Selected Users</h4>
<div className="table-responsive">
<table className="table table-striped table-hover table-bordered">
<thead className="table-primary">
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{selectedOptions.map((option) => (
<tr key={option.id} className="align-middle">
<td>{option.id}</td>
<td>{option.label}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
</div>
</div>
);
}
export default App;
A comprehensive example demonstrating advanced features like multiple dropdowns, different configurations, and complex state management:
import React, { useState } from 'react';
import MultiSelectorDropdown from 'multi-selector-dropdown';
import { Option } from 'multi-selector-dropdown';
import 'react-bootstrap-typeahead/css/Typeahead.css';
const AdvancedExample = () => {
const [selectedUsers, setSelectedUsers] = useState<Option[]>([]);
const [selectedProducts, setSelectedProducts] = useState<Option[]>([]);
const [selectedCategories, setSelectedCategories] = useState<Option[]>([]);
// Mock API function for adding new users
const handleAddNewUser = async (value: string): Promise<Option | null> => {
await new Promise(resolve => setTimeout(resolve, 300));
return {
id: `user-${Date.now()}`,
label: value,
type: 'user'
};
};
// Mock API function for adding new products
const handleAddNewProduct = async (value: string): Promise<Option | null> => {
await new Promise(resolve => setTimeout(resolve, 300));
return {
id: `product-${Date.now()}`,
label: value,
type: 'product'
};
};
// Mock API function for adding new categories
const handleAddNewCategory = async (value: string): Promise<Option | null> => {
await new Promise(resolve => setTimeout(resolve, 300));
return {
id: `category-${Date.now()}`,
label: value,
type: 'category'
};
};
const handleUserChange = (options: Option[]) => {
setSelectedUsers(options);
console.log('Selected users:', options);
};
const handleProductChange = (options: Option[]) => {
setSelectedProducts(options);
console.log('Selected products:', options);
};
const handleCategoryChange = (options: Option[]) => {
setSelectedCategories(options);
console.log('Selected categories:', options);
};
return (
<div className="container mt-5">
<h2>Multi-Selector Dropdown - Advanced Example</h2>
<p className="text-muted">
This example demonstrates advanced features including multiple dropdowns,
different configurations, and complex state management.
</p>
<div className="row">
<div className="col-md-4">
<h4>Users Dropdown</h4>
<MultiSelectorDropdown
apiUrl="https://jsonplaceholder.typicode.com/users"
placeholder="Search and select users..."
label="Select Users"
required={true}
allowAddNew={true}
addNewPrefix="Add new user: "
onAddNew={handleAddNewUser}
onChange={handleUserChange}
multiple={true}
maxSelections={3}
clearButton={true}
size="sm"
error=""
touched={false}
/>
</div>
<div className="col-md-4">
<h4>Products Dropdown</h4>
<MultiSelectorDropdown
apiUrl="https://jsonplaceholder.typicode.com/posts"
placeholder="Search and select products..."
label="Select Products"
required={false}
allowAddNew={true}
addNewPrefix="Add new product: "
onAddNew={handleAddNewProduct}
onChange={handleProductChange}
multiple={true}
maxSelections={5}
clearButton={true}
size="md"
error=""
touched={false}
/>
</div>
<div className="col-md-4">
<h4>Categories Dropdown</h4>
<MultiSelectorDropdown
apiUrl="https://jsonplaceholder.typicode.com/albums"
placeholder="Search and select categories..."
label="Select Categories"
required={false}
allowAddNew={true}
addNewPrefix="Add new category: "
onAddNew={handleAddNewCategory}
onChange={handleCategoryChange}
multiple={false}
clearButton={true}
size="lg"
error=""
touched={false}
/>
</div>
</div>
<div className="row mt-4">
<div className="col-md-4">
<h5>Selected Users ({selectedUsers.length})</h5>
<ul className="list-group">
{selectedUsers.map((user) => (
<li key={user.id} className="list-group-item">
<strong>ID:</strong> {user.id} | <strong>Name:</strong> {user.label}
</li>
))}
</ul>
</div>
<div className="col-md-4">
<h5>Selected Products ({selectedProducts.length})</h5>
<ul className="list-group">
{selectedProducts.map((product) => (
<li key={product.id} className="list-group-item">
<strong>ID:</strong> {product.id} | <strong>Name:</strong> {product.label}
</li>
))}
</ul>
</div>
<div className="col-md-4">
<h5>Selected Categories ({selectedCategories.length})</h5>
<ul className="list-group">
{selectedCategories.map((category) => (
<li key={category.id} className="list-group-item">
<strong>ID:</strong> {category.id} | <strong>Name:</strong> {category.label}
</li>
))}
</ul>
</div>
</div>
<div className="mt-4">
<h4>Summary</h4>
<div className="alert alert-info">
<strong>Total Selected Items:</strong> {selectedUsers.length + selectedProducts.length + selectedCategories.length}
<br />
<strong>Users:</strong> {selectedUsers.length} |
<strong>Products:</strong> {selectedProducts.length} |
<strong>Categories:</strong> {selectedCategories.length}
</div>
</div>
</div>
);
};
export default AdvancedExample;
Major Improvements:
Technical Fixes:
selected={[]}
prop to ensure dropdown shows optionsfilteredOptions
logic for proper option filteringProp | Type | Default | Description |
---|---|---|---|
apiUrl | string | - | Required. The URL to fetch options from |
apiMethod | 'GET' | 'POST' | 'GET' | HTTP method for API requests |
apiHeaders | Record<string, string> | {} | Additional headers for API requests |
apiParams | Record<string, any> | {} | Additional parameters for API requests |
placeholder | string | 'Select options...' | Placeholder text for the input |
label | string | - | Label for the dropdown |
required | boolean | false | Whether the field is required |
disabled | boolean | false | Whether the dropdown is disabled |
className | string | '' | Additional CSS classes |
searchEnabled | boolean | true | Enable search functionality |
searchPlaceholder | string | - | Placeholder for search input |
minSearchLength | number | 0 | Minimum characters before triggering search |
allowAddNew | boolean | true | Allow adding new options |
addNewPrefix | string | 'Add new: ' | Prefix for new option suggestions |
onAddNew | (value: string) => Promise<Option | null> | - | Callback for adding new options |
multiple | boolean | true | Enable multi-selection |
maxSelections | number | - | Maximum number of selections allowed |
onChange | (selectedOptions: Option[]) => void | - | Callback when selection changes |
onSearch | (searchTerm: string) => void | - | Callback when search term changes |
onBlur | () => void | - | Callback when input loses focus |
onFocus | () => void | - | Callback when input gains focus |
value | Option[] | [] | Controlled value |
defaultValue | Option[] | [] | Default value |
clearButton | boolean | true | Show clear button |
size | 'sm' | 'md' | 'lg' | 'md' | Size of the dropdown |
error | string | - | Error message to display |
touched | boolean | false | Whether the field has been touched |
interface Option {
id: string | number;
label: string;
[key: string]: any;
}
interface ApiResponse<T> {
data: T[];
total?: number;
page?: number;
limit?: number;
[key: string]: any;
}
The component expects the API to return data in one of these formats:
[
{ "id": 1, "label": "Option 1" },
{ "id": 2, "label": "Option 2" }
]
{
"data": [
{ "id": 1, "label": "Option 1" },
{ "id": 2, "label": "Option 2" }
],
"total": 2,
"page": 1,
"limit": 10
}
The component uses Bootstrap classes by default. You can customize the styling by:
className
prop.multi-selector-dropdown .rbt-input-main {
border-radius: 0.375rem;
}
.multi-selector-dropdown .btn-outline {
border-radius: 50px;
}
.multi-selector-dropdown .checkbox-pill {
background-color: #007bff;
border-color: #007bff;
}
The component includes built-in error handling for:
Errors are logged to the console and can be handled through the onAddNew
callback.
The component is built with accessibility in mind:
The component includes comprehensive tests:
npm test
All tests are passing and cover:
# Build the package
npm run build
# Run tests
npm test
# Link for local development
npm link
# Build and publish
npm run build
npm publish
MIT
Pull requests and issues are welcome! Please open an issue or PR on GitHub.
Akshay Bhalala
akshaybhalala@gmail.com
We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License - see the LICENSE file for details.
react
dropdown
multi-select
typeahead
search
api
typescript
bootstrap
form-control
autocomplete
select
input
ui-component
react-component
javascript
frontend
web-development
user-interface
interactive
responsive
FAQs
A React component for multi-select dropdown with API-driven options, search capability, and add new option functionality
The npm package multi-selector-dropdown receives a total of 34 weekly downloads. As such, multi-selector-dropdown popularity was classified as not popular.
We found that multi-selector-dropdown demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.ย It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Socket uncovered 11 malicious Go packages using obfuscated loaders to fetch and execute second-stage payloads via C2 domains.
Security News
TC39 advances 11 JavaScript proposals, with two moving to Stage 4, bringing better math, binary APIs, and more features one step closer to the ECMAScript spec.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).