Can react-select underline searched text in filtered options? - react-select

I want to create react-select that when user type text, it will show filtered options whose part of match texts are underlined and change color from black to red as provided below image. Is it possible? Thanks.

After a while, I get the answer :)
import Select, { components } from 'react-select';
const options1 = [
{
value: 'chocolate',
label: 'chocolate',
},
{
value: 'strawberry',
label: 'strawberry',
},
{
value: 'vanilla',
label: 'vanilla'
}
]
class MyOption extends React.Component {
f_search = (input,option) => {
const num = option.indexOf(input)
const len = input.length
return (
<div>
<span>{option.substr(0, num)}</span>
<span style={{color:"red", textDecoration: "underline"}}>{input}</span>
<span>{option.substr(num +len)}</span>
</div>
)
}
render() {
const input = this.props.selectProps.inputValue
const option = this.props.data.label
return (
<components.Option {...this.props}>
{this.f_search(input,option)}
</components.Option>
)
}
}
const ReactSelect7 = () =>
<Select options={options1} components={{ Option: MyOption }} />

Related

REACT NATIVE / my child component don't re-render despite props change

I'm facing an issue on the code below (sandbox here https://codesandbox.io/s/silly-rubin-9ghc5?fontsize=14&hidenavigation=1&theme=dark ), the props change but doesn't refresh the component accordingly.
I would like to be able to keep track of different votes / options within a state in the parent node, hence i'm using an array where the index is the index of my option and the value the number of votes.
import { useEffect, useState } from "react";
import { Button, View } from "react-native";
import "./styles.css";
const myList = [
{
cid: 0,
cTx: "Paris"
},
{
cid: 1,
cTx: "Lyon"
},
{
cid: 2,
cTx: "Marseille"
},
{
cid: 3,
cTx: "Valence"
},
{
cid: 4,
cTx: "Bordeaux"
}
];
interface mTprop {
myItemId: number;
myItemTxt: string;
myItemSt: number[];
myItemClck: () => void;
}
const MyItem = (props: mTprop) => {
const onBtPress = () => {
props.myItemClck();
console.log(props.myItemSt);
};
return (
<View
style={{
flexDirection: "row"
}}
>
<h3>{props.myItemTxt}</h3>
<Button onPress={onBtPress} title="Learn More" />
<h3>{props.myItemSt[props.myItemId]}</h3>
</View>
);
};
export default function App() {
const [selectedOpt, setSelectedOpts] = useState(new Array(0));
useEffect(() => {
setSelectedOpts(new Array(myList.length).fill(0));
}, []);
const updateOptions = (ix: number) => {
++selectedOpt[ix];
setSelectedOpts(selectedOpt);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{myList.map((itm, ix) => {
return (
<MyItem
key={ix}
myItemId={ix}
myItemTxt={itm.cTx}
myItemSt={selectedOpt}
myItemClck={() => updateOptions(ix)}
/>
);
})}
</div>
);
}
Thanks a million in advance !
Please let me know if further info is needed
In order to change data in list. You need to do this
const updateOptions = (ix: number) => {
const newList = selectedOpt.map((m, i) => {
if (i === ix) {
return m + 1;
}
return m;
});
setSelectedOpts(newList);
};

How to load new data to react-bootstrap-table2

With this code the table is getting populated. I am trying to load new data to the table on clicking the button "Load New Data" which will call "handleClick" handler and I am loading new data "this.state.MyDataList = require('./data1.json');" but the actual table is showing the same old data. Why the new data is not getting reflected in the table.
import React, {Component} from 'react';
import 'react-bootstrap-table2-toolkit/dist/react-bootstrap-table2-toolkit.min.css';
import 'react-bootstrap-table2-filter/dist/react-bootstrap-table2-filter.css'
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter , selectFilter} from 'react-bootstrap-table2-filter';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import axios from 'axios';
const { SearchBar } = Search;
export default class Customers extends Component {
constructor(props) {
super(props)
this.state = {MyDataList: require('./data.json'),
"columns" : [{
dataField: 'id',
text: 'Title',
sort: true,
filter: textFilter()
},{
dataField: 'name',
text: name',
sort: true,
filter: textFilter()
},{
dataField: 'age',
text: 'Age'
}]};
}
//function which is called the first time the component loads
componentDidMount() {
}
handleOnExpand = (row, isExpand, rowIndex, e) => {
//My code here
}
**handleClick = () => {
this.state.MyDataList = require('./data1.json');
}**
handleDataChange = ({ dataSize }) => {
this.data = require('./data1.json');
console.log("Hi")
}
render() {
// if (!this.state.MyDataList)
// return (<p>Loading data</p>)
return (<div className="addmargin">
<ToolkitProvider
keyField="Id"
data={ this.state.MyDataList }
columns={ this.state.columns }
search
>
{
props => (
<div>
<h3>Input something at below input field:</h3>
<SearchBar keyField='Id' data={ this.state.MyDataList } columns={ this.state.columns }/>
<hr/>
**<button className="btn btn-warning" onClick={ this.handleClick }>Load New Data</button>**
<BootstrapTable onDataSizeChange={ this.handleDataChange } bootstrap4 keyField='Id' data={this.state.MyDataList } columns={ this.state.columns } striped hover condensed filter={ filterFactory() } />
</div>
)
}
</ToolkitProvider>
</div>
);
}
}
It worked after loading data with the state setter " this.setState".
handleClick = () => {
this.setState({MyDataList : require('./data1.json') })
}

Can we remove one of selected option in react-select programmatically?

In react-select https://github.com/jedwatson/react-select , can we remove one of selected option in react-select programmatically?
E.g in the below screenshot I would like to unselectred programmatically?
Many thanks!
You can save selected options in state and remove selected one by update new state, you can check here codeSandBox
import React, { useState } from "react";
import "./styles.css";
import Select from "react-select";
const options = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
];
export default function App() {
const [selectedOption, setSelect] = useState(null);
const handleChange = selectedOption => {
setSelect(selectedOption);
};
const removeOption = e => {
const newSelect = selectedOption.filter(
item => item.value !== e.target.name
);
setSelect(newSelect);
};
return (
<>
<Select
isMulti
value={selectedOption}
onChange={handleChange}
options={options}
/>
<button name="chocolate" onClick={removeOption}>
Remove Chocolate
</button>
<button name="vanilla" onClick={removeOption}>
Remove Vanilla
</button>
<button name="strawberry" onClick={removeOption}>
Remove Strawberry
</button>
</>
);
}

AsyncSelect: how to set an initial value?

I am using AsyncSelect and need to change the value of the component based on outside logic.
For instance, I have this simple component:
import { colourOptions } from '../data';
const filterColors = (inputValue: string) => {
return colourOptions.filter(i =>
i.label.toLowerCase().includes(inputValue.toLowerCase())
);
};
const promiseOptions = inputValue =>
new Promise(resolve => {
setTimeout(() => {
resolve(filterColors(inputValue));
}, 1000);
});
export default class WithPromises extends Component {
render() {
return (
<AsyncSelect cacheOptions defaultOptions loadOptions={promiseOptions} />
);
}
}
Is there a way to set the initial value of it? I thought of using props but I couldn't figure out how execute onChange event as this would load the options array and set label and value.
Try adding a value like this:
<AsyncSelect
cacheOptions
defaultOptions
value={{ label: 'yellow', value: 2 }}
loadOptions={promiseOptions} />
it worked for me.
When changing the value from the menu options and selected item not change or changed happened based on outside logic then just use the state in value={yourState} to set the initial & updated values of AsyncSelect. Selected contain object like value={value:'', label:''}
const formFields = {
name: '',
foo:'',
bar:''
}
const [inputs, setInputs] = useState(formFields);
inputs is my state which i used to set the fields values
value={inputs.name ? { label: inputs.name } : { label: 'Search customer...' }}
I used only label:'Search customer...' to make it look like place holder.
<AsyncSelect
defaultOptions
value={inputs.name ? { label: inputs.name } : { label: 'Search customer...' }}
cacheOptions
onChange={(e) => handleCustomerSelect(e)}
loadOptions={customerPromiseOptions}
/>
here is my onChange which is called when item is select from dropdown menu
function handleCustomerSelect(selectedOption) {
const { value } = selectedOption;
setInputs({ ...inputs, name:value });
}
You can set your initial value from options as well like this

How can I make an entire row clickable in a DetailsList component? (office-ui-fabric)

I've been using the DetailsList component but haven't found a way to make an entire row clickable - is there a sample code snippet or pointers on how this can be achieved?
https://developer.microsoft.com/en-us/fabric#/components/detailslist
Overriding onRenderRow worked for me.
const _columns: IColumn[] = [
{
key: 'name',
name: 'Name',
fieldName: 'name',
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: 'value',
name: 'Value',
fieldName: 'value',
minWidth: 100,
maxWidth: 200,
isResizable: true,
}
];
const _items = Array.apply(null, Array(10)).map((_: any, num: number) => ({
key: num.toString(),
name: `Item ${num.toString()}`,
value: num.toString()
}));
class Content extends React.Component {
private _renderRow(props: Fabric.IDetailsRowProps, defaultRender: any): JSX.Element {
return (
<Fabric.DetailsRow {...props} onClick={() => alert('click')}/>
);
}
public render() {
return (
<Fabric.Fabric>
<Fabric.DetailsList
items={ _items }
columns={ _columns.concat(..._columns, ..._columns, ..._columns) }
onRenderRow={this._renderRow}
/>
</Fabric.Fabric>
);
}
}
ReactDOM.render(
<Content />,
document.getElementById('content')
);
Here is th e single click solution,
Use onActiveItemChanged prop like:
const _onActiveItemChanged = (item): void => {
alert(`Item invoked: ${JSON.stringify(item)}`);
};
here is the DetailList
<DetailsList
items={assessmentList}
compact={false}
columns={columns}
onActiveItemChanged={_onActiveItemChanged }
/>
Please onItemInvoked Property and method. But it works on double click. I am also looking for single click solution
const onItemInvoked = (item): void => {
alert(`Item invoked: ${JSON.stringify(item)}`);
};
<DetailsList
items={assessmentList}
compact={false}
columns={columns}
selectionMode={SelectionMode.multiple}
getKey={_getKey}
setKey="multiple"
layoutMode={DetailsListLayoutMode.justified}
checkboxVisibility={CheckboxVisibility.hidden}
isHeaderVisible={true}
selectionPreservedOnEmptyClick={false}
enterModalSelectionOnTouch={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="Select Checkbox"
onRenderRow={onRenderRow}
onItemInvoked={onItemInvoked}
onRenderDetailsHeader={(headerProps, defaultRender) => {
return (
<Sticky
stickyPosition={StickyPositionType.Header}
isScrollSynced={true}
stickyBackgroundColor="transparent"
>
<div className="text-center">{defaultRender(headerProps)}</div>
</Sticky>
);
}}
/>
Use onRenderRow and cloneElement to attach an onClick listener:
import React, { useCallback, cloneElement } from 'react';
import { DetailsList } from '#fluentui/react';
const Component = () => {
const onItemInvoked = useCallback( ( item ) => {
console.log( item );
}, [] );
const onRenderRow = useCallback( ( row, defaultRender ) => {
return cloneElement( defaultRender( row ), { onClick: () => onItemInvoked( row.item ) } )
}, [ onItemInvoked ] );
return (
<DetailsList
onRenderRow={ onRenderRow }
/>
);
};