Topic: multiple MDBSelect does not select from state
<MDBSelect multiple>
<MDBSelectInput id="authorities"
name="authorities"
selected={this.state.authorities}
onChange={this.changeHandler}/>
<MDBSelectOptions>
{roles.map(role => (
<MDBSelectOption value={role}>
{role}
</MDBSelectOption>
))}
</MDBSelectOptions>
</MDBSelect>
The option within the array this.state.authorities are not checked. I cannot find my mistake. Singel MDBSelect works and if I check some values the array gets set correctly.
Anna Morawska staff answered 6 years ago
Hi there,
I'm not sure what you want to achieve - please provide me with a complete working example, with state object and the changeHandler method, then I will try to help :)
Best,
Ania
hberndt answered 6 years ago
Ok, thank you
State object
state: IUserManagementUpdateState = {
isNew: !this.props.match.params || !this.props.match.params.login,
isShow: !this.props.match.url.endsWith('edit'),
activeItem: '1',
value: {}
};
value is an entity which get loaded via redux. It is set within render:
const { user : propsUser, loading, updating, roles } = this.props;
const { value : stateUser = {} } = this.state;
const current = defaults({}, stateUser, propsUser);
The entity has a member authorities as array (e.g. ROLE_ADMIN, ROLE_USER)
Now comes the snippet for the select box:
<MDBSelect multiple>
<MDBSelectInput id="authorities" name="authorities"
selected={current.authorities}
disabled={this.state.isShow}/>
<MDBSelectOptions
{roles.map(role => (
<MDBSelectOption value={role} checked>
{role}
</MDBSelectOption>
))}
</MDBSelectOptions>
</MDBSelect>
The options are not selected. For completion here is my changeHandler:
changeHandler = e => {
const newValues = getValueFromEvent(e);
console.log(this.state.value);
if (newValues) {
const change = {
...this.state.value,
...newValues
};
// Update our component-local state with these changes, so that the child components
// will re-render with the new values right away
this.setState({ value: change });
}
};
Anna Morawska staff answered 6 years ago
well, still not sure If I understand you ;p You use that component in a really unusual way - you don't have to manually update state to check and uncheck select options - it is done internally.
Does the changeHandler method fire?
Please, take a look at this example:
import React, { Component } from "react";
import { MDBSelect, MDBSelectInput, MDBSelectOptions, MDBSelectOption} from "mdbreact";
class SelectPage extends Component {
changeHandler = e => {
console.log(e)
};
render() {
return (
<div>
<MDBSelect multiple getValue={this.changeHandler}>
<MDBSelectInput selected="Choose your option" />
<MDBSelectOptions>
<MDBSelectOption disabled>Choose your option</MDBSelectOption>
<MDBSelectOption value="1" >Option 1</MDBSelectOption>
<MDBSelectOption value="2">Option 2</MDBSelectOption>
<MDBSelectOption value="3">Option 3</MDBSelectOption>
<MDBSelectOption value="4" selected>Option 4</MDBSelectOption>
<MDBSelectOption value="5">Option 5</MDBSelectOption>
</MDBSelectOptions>
</MDBSelect>
</div>
);
}
}
export default SelectPage;
In my opinion you should refactor your code, then you will get something similar to this:
import React, { Component } from "react";
import { MDBSelect, MDBSelectInput, MDBSelectOptions, MDBSelectOption} from "mdbreact";
class SelectPage extends Component {
changeHandler = e => {
console.log(e)
};
render() {
return (
<div>
<MDBSelect multiple getValue={this.changeHandler}>
<MDBSelectInput d="authorities" name="authorities" selected={current.authorities} disabled={this.state.isShow} />
<MDBSelectOptions>
<MDBSelectOption disabled>Choose your option</MDBSelectOption>
{ roles.map(role => (
<MDBSelectOption value={role}>{role}</MDBSelectOption>
))
}
</MDBSelectOptions>
</MDBSelect>
</div>
);
}
}
export default SelectPage;
hberndt answered 6 years ago
Hi Anna, here is my update. I implemented your solution. There seems to be a bug with multiple selection. Without the multiple option, the first option in the array is displayed. With multiple option, the array gets cleared.
changeHandlerRoles = value => {
let newValues;
newValues = {
authorities: value
};
const change = {
...this.state.value,
...newValues
};
console.log(change);
this.setState({ value: change });
}
<MDBSelect multiple getValue={this.changeHandlerRoles}>
<MDBSelectInput id="authorities" name="authorities" selected={current.authorities}/>
<MDBSelectOptions>
{roles.map(role => (
<MDBSelectOption key={role} value={role}>{role}</MDBSelectOption>
))}
</MDBSelectOptions>
</MDBSelect>
The console first logs an empty array while rendering when getValue is triggered. Would be great to get a solution. Regards, Holger
Anna Morawska staff answered 6 years ago
Hi there,
please check out this solution - it use the map method on the roles array and renders options. You can choose which option has to be checked at the beginning.
import React, { Component } from "react";
import { MDBSelect, MDBSelectInput, MDBSelectOptions, MDBSelectOption } from "mdbreact";
class SelectPage extends Component {
state = {
current: 'admin',
roles: [{name: "admin", selected: false}, {name: "moderator", selected: true}, {name: "developer", selected: false}, {name: "user", selected: false} ],
authorities: ""
}
changeHandlerRoles = value => {
this.setState({ authorities: value }, () => console.log(this.state));
}
render(){
const { roles } = this.state;
return(
<MDBSelect multiple getValue={this.changeHandlerRoles} >
<MDBSelectInput id="authorities" name="authorities" />
<MDBSelectOptions>
{roles.map(role => (
<MDBSelectOption key={role.name} value={role.name} selected={role.selected}>{role.name}</MDBSelectOption>
))}
</MDBSelectOptions>
</MDBSelect>
)
}
}
export default SelectPage;
Raiczyk answered 6 years ago
Hi! I'm having the same problem. The proposed solution works, but it's not the best option in my case. I define the state:
...
constructor(props) {
super(props);
this.state = {
currentFilters: {
provinces: [],
localities: [],
stores: [],
dates: {
from: null,
to: null
},
sites: []
}
};
this.handleSelectChange = this.handleSelectChange.bind(this)
}
and then bind it to the select like this:
<MDBSelect getValue={values => this.handleSelectChange('stores', values)} multiple>
<MDBSelectInput selected={this.state.currentFilters.stores} />
<MDBSelectOptions search>
{
this.props.availableStores.map(store =>
<MDBSelectOption value={store.id}>{store.name}</MDBSelectOption>)
}
</MDBSelectOptions>
</MDBSelect>
then every time render is called, the select should show currentFilters.stores as selected options because it's binded to the state.
Is that possible?
Thanks in advance.
Anna Morawska staff answered 6 years ago
Hi there,
somehow, you have to decide if the store is selected - so maybe write a separate function which, based on passed props, return true or false according to the curretFilters value. For example something like this:
checkIfSelected = store => () => {
const { provinces, localities } = this.state.currentFilters;
if (provinces.includes(store.province)) return true;
if (localities.includes(store.localisation)) return true;
return false;
}
<MDBSelect getValue={values => this.handleSelectChange('stores', values)} multiple>
<MDBSelectInput selected="Choose your option" />
<MDBSelectOptions search>
{
this.props.availableStores.map(store =>
<MDBSelectOption selected={this.checkIfSelected(store)} value={store.id}>{store.name}</MDBSelectOption>)
}
</MDBSelectOptions>
</MDBSelect>
)
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- User: Free
- Premium support: No
- Technology: MDB React
- MDB Version: 4.8.4
- Device: Notebook
- Browser: chrome
- OS: macOS
- Provided sample code: No
- Provided link: No