searchable dropdown in react - javascript

I have below list in react.
<select
id="sponsor"
name="sponsor"
className="form-control"
placeholder="Sponsor"
}
>
<option value="" selected>Please select the sponsor</option>
{
active && result.map((sponsor:Sponsor,index:number)=>
<option value={sponsor.id} >{sponsor.name}</option>
)
}
</select>
it is working perfectly fine. now I need to change it to searchable list. I did below.
import VirtualizedSelect from 'react-virtualized-select'
import "react-virtualized-select/styles.css";
import 'react-virtualized/styles.css'
<VirtualizedSelect
id="sponsor"
name="sponsor"
className="form-control"
placeholder="Sponsor"
options={ active && result.map((sponsor:Sponsor,index:number)=>
{sponsor.name}
)}
>
</VirtualizedSelect>
now nothing is coming in list. basically my requirement is to make list searchable and insert data of API into that list.
Could you please help me with same? Any other option will also be very helpful
Edit1:-
I need list like below. first line "Please choose sponsor"

according to VirtualizedSelect docs here https://www.npmjs.com/package/react-virtualized-select, the component accept array of objects like :
const options = [
{ label: "One", value: 1 },
{ label: "Two", value: 2 },
{ label: "Three", value: 3, disabled: true }
// And so on...
]
not array of strings and I think this is way its not working, I'd suggest to change your code to :
<VirtualizedSelect
id="sponsor"
name="sponsor"
className="form-control"
placeholder="Sponsor"
options={ active && result.map((sponsor:Sponsor,index:number)=>
({label: sponsor.name, value: sponsor.name})
)}
>
</VirtualizedSelect>

Related

Creating default value for Select/dropdown list and can be selected default value back again manually - ReactJs

I have gone through many sites before posting a question here and to understand on how to create a defaultValue in select however, all sites talks about setting the value but no where it talks about selecting the default value back again.
What I need
I have some 6 dropdown controls that has different values and each dropdown list is filled by API.
now I have used defaultValue as "--Select One--" for my work, it works as expected, however I need the default value to be selected again when needed manually, like if user want to undo the list back to default value**(--Select One--)**.
Why I need this
As said before I have 6 dropdown values and imagine I have selected values for 5 dropdown and I want to undo one of the option from any dropdown then the only option I have to clear all dropdown lists and do the selection again.
CODE
<Select className="AdvancedFilterText"
ref={selectRef}
options={categoryOptions}
styles={{
option: base => ({
...base,
borderBottom: '1px solid hsl(0, 0%, 80%,.5)',
height: '100%',
}),
}}
defaultValue={{value: "0", label:"--Select One--"}}
isSearchable
placeholder={"CHOOSE CATEGORY"}
onChange={event => onCategorySelect(event)}>
</Select>
Post adding MenuItem
Set displayEmpty and have one option with value=''
const data = [
{ value: 'accounting', label: 'Accounting' },
{ value: 'authority', label: 'Authority' },
{ value: 'coverage', label: 'Coverage' },
{ value: 'investigation', label: 'Investigation' }
]; // data from server
<Select displayEmpty>
<MenuItem value=''>Select...</MenuItem>
{data.map(item =>
<MenuItem key={item.value} value={item.value}>
{item.label}
</MenuItem>)
}
</Select>

How to clear v-model used with a select when options change

I have a cascading select (two part select) where the options in the second dropdown are determined by the value of the first dropdown. I do this by having a computed property which is based off of the first select. This then feeds the options into the second select. This mostly works fine.
The problem I'm having is if I have selected an option in the second select (which through v-model sets the value of the bound variable in Vue), and then I change the value of the first select. The options for the second select then update, and in that second select I appear to be selected to the empty option. However, the bound variable still has the previously selected value. I'm assuming this is because updating the option values for the second select doesn't actually trigger an input or change event so v-model doesn't respond to anything. I suppose I could fix this with a watcher, but I was hoping for a more elegant solution.
Coded example is here: https://codepen.io/Slotheroo/pen/ajwNKO/
JS/Vue:
new Vue({
el: '#app',
data: {
selectedFruit: null,
selectedVariety: null,
fruits: {
"apples": [
{
name: "honeycrisp",
madeBy: "applebees",
},
{
name: "macintosh",
madeBy: "the steves",
},
{
name: "gala",
madeBy: "ac/dc",
},
{
name: "pink lady",
madeBy: "Alecia Beth Moore",
},
],
"pears": [
{
name: "d'anjou",
madeBy: "Maya D'Anjoulou",
},
{
name: "bartlett",
madeBy: "Anton Yelchin",
}
],
},
},
computed: {
fruitVarieties: function() {
return this.fruits[this.selectedFruit]
}
},
});
HTML:
<div id="app">
<div>
<select v-model="selectedFruit">
<option value=""></option>
<option v-for="fruitName in Object.keys(fruits)" :value ="fruitName">{{fruitName}}</option>
</select>
</div>
<select v-model="selectedVariety">
<option value=""></option>
<option v-for="fruitVariety in fruitVarieties" :value="fruitVariety">{{ fruitVariety.name }}</option>
</select>
<div>
</div>
<p>Selected variety: {{ selectedVariety }}</p>
</div>
Steps to reproduce:
Select 'apples' in the first select
Select 'honeycrisp' in the second select
Select 'pears' or 'blank' in the first select
Hoped for result
selectedVariety returns to null
Actual result
selectedVariety still equals honeycrisp
I'd add an on-change handler to the first <select> to empty the selectedVariety when the selection changes...
<select v-model="selectedFruit" #change="selectedVariety = null">
https://codepen.io/anon/pen/JByEwy
Another option would be to add a watch on selectedFruit but Vue generally recommends using event handlers.
if you're using version 3.0.0, there is some feature with :reset-on-options-change='true'
e.g
<v-select required :options="filterKaryawan.unit.options" :reset-on-options-change='true' v-model="filterKaryawan.unit.selected" placeholder="placeholder" >
<template #search="{attributes, events}">
<input
class="vs__search"
v-bind="attributes"
v-on="events"
:required="filterKaryawan.unit.selected"
/>
</template>
</v-select>
The computed propertive is actually a watcher. So just put the reset value code in it.
computed: {
fruitVarieties: function() {
this.selectedVariety = null;
return this.fruits[this.selectedFruit]
}
}

How to make react-select always display the option list

How to make react-select always display the option list
By default it toggles when you click on the array button or when you start typing something
var Select = require('react-select');
var options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
];
function logChange(val) {
console.log('Selected: ', val);
}
<Select
name="form-field-name"
value="one"
options={options}
onChange={logChange}
/>
Use props
defaultMenuIsOpen
This will make dropdown open by default
<Select
defaultMenuIsOpen
name="form-field-name"
value="one"
options={options}
onChange={logChange}
/>
you can do one thing if you want to show all option without click on select list.
open select on Focus and give default Focus to select on it's mount as bellow.
var Select = require('react-select');
var options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
];
function logChange(val) {
console.log('Selected: ', val);
}
<Select
name="form-field-name"
value="one"
options={options}
onChange={logChange}
openOnFocus={true}
autofocus={true}
/>
After selection of option from list,Selected value will be displayed and others value automatically dropped.
UPD 2023
Just use menuIsOpen, defaultMenuIsOpen, menuIsOpen attributes:
<Select
defaultMenuIsOpen
autoFocus
menuIsOpen
...
/>

Broken Aurelia binding when object is null

Example based on Aurelia doc.
Page code:
export class MyPage {
products = [
{ id: 0, name: 'Motherboard' },
{ id: 1, name: 'CPU' },
{ id: 2, name: 'Memory' },
];
selectedProduct = null;
}
Page HTML:
<label>
Select product:<br/>
<select value.bind="selectedProduct">
<option model.bind="null">Choose...</option>
<option repeat.for="product of products"
model.bind="product">
${product.id} - ${product.name}
</option>
</select>
</label>
<div if.bind="selectedProduct">
Selected product 1: ${selectedProduct.id} - ${selectedProduct.name}
<div if.bind="selectedProduct.id > 0">
Selected product 2: ${selectedProduct.id} - ${selectedProduct.name}
</div>
</div>
When selecting CPU, then selecting null value, then selecting Memory, Selected product 1 is updated correctly with a value from a select element, but Selected product 2 is stuck with a CPU value.
How to bind selected value correctly inside the inner div?
In my application, I want to be able to display a content of selected item. Depending on an item type, I have a several <div if.bind="item.type === N">...</div> elements in order to display different HTML for each type of an item.
Note: binding doesn't work with newest packages, but works fine when I assign specific versions to the following packages in my package.json:
"aurelia-templating": "1.4.2"
"aurelia-templating-binding": "1.3.0"
"aurelia-templating-resources": "1.4.0"
"aurelia-templating-router": "1.1.0"

How do I create a dynamic drop down list with react-bootstrap

The example code in the react-bootstrap site shows the following. I need to drive the options using an array, but I'm having trouble finding examples that will compile.
<Input type="select" label="Multiple Select" multiple>
<option value="select">select (multiple)</option>
<option value="other">...</option>
</Input>
You can start with these two functions. The first will create your select options dynamically based on the props passed to the page. If they are mapped to the state then the select will recreate itself.
createSelectItems() {
let items = [];
for (let i = 0; i <= this.props.maxValue; i++) {
items.push(<option key={i} value={i}>{i}</option>);
//here I will be creating my options dynamically based on
//what props are currently passed to the parent component
}
return items;
}
onDropdownSelected(e) {
console.log("THE VAL", e.target.value);
//here you will see the current selected value of the select input
}
Then you will have this block of code inside render. You will pass a function reference to the onChange prop and everytime onChange is called the selected object will bind with that function automatically. And instead of manually writing your options you will just call the createSelectItems() function which will build and return your options based on some constraints (which can change).
<Input type="select" onChange={this.onDropdownSelected} label="Multiple Select" multiple>
{this.createSelectItems()}
</Input>
My working example
this.countryData = [
{ value: 'USA', name: 'USA' },
{ value: 'CANADA', name: 'CANADA' }
];
<select name="country" value={this.state.data.country}>
{this.countryData.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>;
})}
</select>
bind dynamic drop using arrow function.
class BindDropDown extends React.Component {
constructor(props) {
super(props);
this.state = {
values: [
{ name: 'One', id: 1 },
{ name: 'Two', id: 2 },
{ name: 'Three', id: 3 },
{ name: 'four', id: 4 }
]
};
}
render() {
let optionTemplate = this.state.values.map(v => (
<option value={v.id}>{v.name}</option>
));
return (
<label>
Pick your favorite Number:
<select value={this.state.value} onChange={this.handleChange}>
{optionTemplate}
</select>
</label>
);
}
}
ReactDOM.render(
<BindDropDown />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
// on component load, load this list of values
// or we can get this details from api call also
const animalsList = [
{
id: 1,
value: 'Tiger'
}, {
id: 2,
value: 'Lion'
}, {
id: 3,
value: 'Dog'
}, {
id: 4,
value: 'Cat'
}
];
// generage select dropdown option list dynamically
function Options({ options }) {
return (
options.map(option =>
<option key={option.id} value={option.value}>
{option.value}
</option>)
);
}
<select
name="animal"
className="form-control">
<Options options={animalsList} />
</select>
Basically all you need to do, is to map array. This will return a list of <option> elements, which you can place inside form to render.
array.map((element, index) => <option key={index}>{element}</option>)
Complete function component, that renders <option>s from array saved in component's state. Multiple property let's you CTRL-click many elements to select. Remove it, if you want dropdown menu.
import React, { useState } from "react";
const ExampleComponent = () => {
const [options, setOptions] = useState(["option 1", "option 2", "option 3"]);
return (
<form>
<select multiple>
{ options.map((element, index) => <option key={index}>{element}</option>) }
</select>
<button>Add</button>
</form>
);
}
component with multiple select
Working example: https://codesandbox.io/s/blue-moon-rt6k6?file=/src/App.js
A 1 liner would be:
import * as YourTypes from 'Constants/YourTypes';
....
<Input ...>
{Object.keys(YourTypes).map((t,i) => <option key={i} value={t}>{t}</option>)}
</Input>
Assuming you store the list constants in a separate file (and you should, unless they're downloaded from a web service):
# YourTypes.js
export const MY_TYPE_1="My Type 1"
....
You need to add key for mapping otherwise it throws warning because each props should have a unique key. Code revised below:
let optionTemplate = this.state.values.map(
(v, index) => (<option key={index} value={v.id}>{v.name}</option>)
);
You can create dynamic select options by map()
Example code
return (
<select className="form-control"
value={this.state.value}
onChange={event => this.setState({selectedMsgTemplate: event.target.value})}>
{
templates.map(msgTemplate => {
return (
<option key={msgTemplate.id} value={msgTemplate.text}>
Select one...
</option>
)
})
}
</select>
)
</label>
);
I was able to do this using Typeahead. It looks bit lengthy for a simple scenario but I'm posting this as it will be helpful for someone.
First I have created a component so that it is reusable.
interface DynamicSelectProps {
readonly id: string
readonly options: any[]
readonly defaultValue: string | null
readonly disabled: boolean
onSelectItem(item: any): any
children?:React.ReactNode
}
export default function DynamicSelect({id, options, defaultValue, onSelectItem, disabled}: DynamicSelectProps) {
const [selection, setSelection] = useState<any[]>([]);
return <>
<Typeahead
labelKey={option => `${option.key}`}
id={id}
onChange={selected => {
setSelection(selected)
onSelectItem(selected)
}}
options={options}
defaultInputValue={defaultValue || ""}
placeholder="Search"
selected={selection}
disabled={disabled}
/>
</>
}
Callback function
function onSelection(selection: any) {
console.log(selection)
//handle selection
}
Usage
<div className="form-group">
<DynamicSelect
options={array.map(item => <option key={item} value={item}>{item}</option>)}
id="search-typeahead"
defaultValue={<default-value>}
disabled={false}
onSelectItem={onSelection}>
</DynamicSelect>
</div>

Categories