Reputation: 1384
I would like to create a custom component in React using TypeScript that's essentially a combobox which has auto-complete/search functionality, connecting to its own remote store. What I would like to do is send an "onSelect" event so that I can receive the selected item where ever I'm using that component in my app.
Doing the auto-complete/search stuff with the remote store is easy, but the React component stuff has me stumped. I'm still learning both, so perhaps I'm trying to walk before I can crawl, but I don't want to start out creating a mess when I know that it should be possible to achieve this outcome which would be more elegant. I just need to find some sort of guide, but so far I haven't found one.
Here's what I want to achieve:
<MyCombobox onSelect={handleSelect} />
The handleSelect function would be used throughout my app where ever I need to use the MyCombobox component. The function needs to accept an argument, of course (which is what has me stumped at the moment, in TS).
Upvotes: 0
Views: 373
Reputation: 1384
From all the googling I've done this morning, I've managed to cobble together something that works (from a plethora of sources):
App.tsx:
import React from 'react';
import './App.css';
import MyCombobox from './MyCombobox';
class App extends React.Component {
receiveSomething(something: string) {
alert('Something: ' + something);
}
render() {
return (
<div>
<MyCombobox receiveSomething={this.receiveSomething} defaultValue="qwerty" />
</div>
);
}
}
export default App;
MyCombobox.tsx:
import React from 'react';
export interface IMyCombobox {
defaultValue: string,
receiveSomething:(name:string) => void
}
class MyCombobox extends React.PureComponent<IMyCombobox, any> {
state = {
something: this.props.defaultValue
}
sendSomething() {
this.props.receiveSomething(this.state.something);
}
handleChange = (event: any) : void => {
this.setState({
something: event.target.value
});
}
render() {
return (
<div>
<input
type='text'
maxLength={20}
value={this.state.something}
onChange={this.handleChange} />
<input
type='button'
value='Send Something'
onClick={this.sendSomething.bind(this)} />
</div>
)
}
}
export default MyCombobox;
Upvotes: 0
Reputation: 11848
One possible solution is as following
import * as React from "react";
import { render } from "react-dom";
interface MyComboProps {
// Here props from parent should be defined
}
interface MyComboState {
ValuesToShow: string[];
SearchValue: string;
}
class StringSearchMenu extends React.Component<MyComboProps, MyComboState> {
constructor(p: MyComboProps) {
super(p);
this.state = {
ValuesToShow: [],
SearchValue: ""
};
}
protected selectString(event: React.ChangeEvent<HTMLInputElement>): void {
let value = event.target.value;
if (value === "") this.setState({ ValuesToShow: [] });
else {
/* here you can put fetch logic. I use static array as example */
let possibleValues = ["Green", "Red", "Blue", "Yellow", "Black"];
this.setState({
ValuesToShow: possibleValues.filter(f => f.indexOf(value) > -1)
});
}
}
render() {
return (
<div>
Enter value to search {" "}
<input onChange={this.selectString.bind(this)} />
<div>
{this.state.ValuesToShow.map(v => (
<div>{v}</div>
))}
</div>
</div>
);
}
}
And working example is here
Upvotes: 1