Got tired Firefox's ugly select and not being able to style it. I thought I'd do one in React for learning purposes.
It seems to be easy to implement but I cannot figure out how to do onChange with custom component and how to get the value back with the event. If it is possible at all ...
The Select component looks like this:
type SelectProps = {
select: {
value: any
options: {
[k: string]: any
}
}
}
type SelectState = {
show: boolean
}
class Select extends Component<SelectProps, SelectState> {
constructor(props: SelectProps) {
super(props)
this.state = {
show: false
}
}
label = (v: any): string | undefined => {
for (var k in this.props.select.options) {
if (this.props.select.options[k] === v) return k
}
}
change = (i: number) => {
this.setState({ show: false })
this.props.select.value = this.props.select.options[this.keys[i]]
}
display = () => {
this.setState({ show: !this.state.show })
}
keys = Object.keys(this.props.select.options)
render() {
let { show } = this.state
let { options, value } = this.props.select
return (
<div className='select'>
<button onClick={this.display}>{this.label(value)}</button>
{!show ? null :
<ul>
{this.keys.map((e: string, i: number) => (
<li key={i} onClick={() => this.change(i)}>{e}</li>)
)}
</ul>
}
</div>
)
}
}
It works as expected. I can style it (hooray!).
I get the selected value from value parameter. I wondering though if I can get it with onChange event? So it behaves more like native select.
P.S.
This is styling of it (in stylus), in case it is needed
.select
display: inline-block
position: relative
background: white
button
border: .1rem solid black
min-width: 4rem
min-height: 1.3rem
ul
position: absolute
top: 100%
border: .1rem solid black
border-top: 0
z-index: 100
width: 100%
background: inherit
li
text-align: center
&:hover
cursor: pointer
background: grey
Thanks