Add search to Select React Bootstrap React JS - reactjs

i'm working with react-bootstrap to create a select list, by default there is a search in list but by just the first caracter. there is a way to add search in my select like the select from react-select. any help please ?
facture.js
import Select from '../retour/bloc/select';
export default function Facture() {
return (
<Select
label="Bordereaux"
name="Bordereaux"
changed={selectPick}
options={listBordereaux ? listBordereaux : []}
onClick={toggleOpen}
search
/>)}
Select.js
import React, { Component } from 'react';
import { Form, Row, Col } from 'react-bootstrap';
import PropTypes from 'prop-types';
import '../retour.css'
export default class Select extends Component {
render() {
let { label, name, value, changed, options } = this.props;
return (
<Form.Group as={Row}>
<Form.Label column lg={4} sm={10} className=""> {label} : </Form.Label>
<Col lg={6} sm={10}>
<Form.Control
name={name}
// size="sm"
as="select"
className="retour-select"
value={value}
onChange={(event) => changed(event, name)}
>
<option value="" hidden> {label} </option>
{label === "Bordereaux" ?
options.map(el =>
<option key={el.id} value={el.ref}>
}
</Form.Control>
</Col>
</Form.Group>
);
}
}
Select.propTypes = {
label: PropTypes.string,
};

Related

How to handle reusable components in React?

I'm trying to make a reusable input component. When data enters I want to handle those input data in the same place where I use that reusable input component. Not passing that as props.
I'm getting an error
Uncaught TypeError: Cannot read property 'value' of undefined
Can anyone give me any idea about how to handle data in such an instance?
InputFieldWithImage.js
import React, {useState} from "react";
import { Form, FormGroup, Input } from 'reactstrap';
function InputFieldWithImage(props) {
const [inputType] = useState(props.type)
const [inputValue, setInputValue] = useState('')
function handleChange(event){
console.log("Input.js");
console.log(inputValue);
setInputValue(event.target.value);
if(props.onChange) props.onChange(inputValue)
}
return (
<>
<Input type={inputType} value={inputValue} name="input-form" onChange={handleChange} class="inputclass"/>
</>
);
}
export default InputFieldWithImage;
AddTicket.js
import { Row, Col } from 'reactstrap';
import { Form, FormGroup, Input } from 'reactstrap';
import ActionButton from './../../components/ButtonComponent';
import InputFieldWithImage from './../../components/InputField/InputFieldWithImage'
import { render } from 'react-dom';
import ReactQuill from 'react-quill';
const AddTicket = (props) => {
const [assignee, setAssignee] = useState('');
const handleSubmit = (evt) => {
evt.preventDefault();
console.log('Assignee:' + assignee);
props.handleClose();
};
const test = () => {
console.log("text");
console.log('Assignee:' + assignee);
};
return (
<div className="popup-box">
<div className="box">
{/* <span className="close-icon" onClick={props.handleClose}>
x
</span> */}
<Form onSubmit={handleSubmit} style={{paddingLeft:30,paddingTop:50}}>
<Row style={{ paddingBottom: 50 }}>
<Col sm={11} xs={11} md={11}>
<h1>Add new ticket </h1>
</Col>
<Col onClick={props.handleClose} m={1} xs={1} md={1}>
<h1 className="close-icon">X </h1>
</Col>
</Row>
<FormGroup>
<Row style={{ marginBottom: '25px' }}>
<Col sm={2}>
<h4>Assignee</h4>
</Col>
<Col sm={2}>
<InputFieldWithImage value={assignee} onChange={(e) => setAssignee(e.target.value)} />
</Col>
</Row>
</FormGroup>
<Row>
<Col sm={2}></Col>
<Col>
<ActionButton text="Send" />
</Col>
</Row>
</Form>
</div>
</div>
);
};
export default AddTicket;
You need to pass event instead of inputValue . As there is input.target.value . That's why its giving error
function handleChange(event) {
console.log("Input.js");
console.log(inputValue);
setInputValue(event.target.value);
if (props.onChange) props.onChange(event);
}
Here is demo: https://codesandbox.io/s/hidden-tree-vr834?file=/src/App.js

React change variable onChange-method

I am experimenting with React and I have the following problem. Different employees are listed in the "medewerker:" dropdown. When 1 is selected, the data is replaced by the value of the selection using the 'handelChangeEmployee' function in the 'employeeOrder' variable. In the console.log everything changes as expected. Only if I read variable: 'employeeOrder' will it continue to show the previously set value. and this is not being replaced, is this possible? and if so how?
So what I want to achieve is that when a selection is made, the value in the existing variable is replaced with the value of the selection.
The code that I am currently using is:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import styles from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
import { Container } from "react-bootstrap";
import { Row } from "react-bootstrap";
import { Col } from "react-bootstrap";
import Close from '#material-ui/icons/Close';
import { render } from "react-dom";
const useStyles = makeStyles(styles);
export default function ChaskDesk() {
const employee = ["Robin","Raoul","Joppe "];
const service = ["Knippen","Scheren","Wassen"];
const counting = [1,2,3,4,5,6];
const gender = ["man", "vrouw", "kind"];
const client = ["Passant"];
let employeeOrder = 'Raoul';
const serviceOrder = [];
const countingOrder = [];
const genderOrder = [];
const clientOrder = "";
const payment = 0;
const classes = useStyles();
const handelChangeGender = function(event){
genderOrder.push(event.target.value);
console.log(genderOrder);
};
const handelChangeService = function(event){
serviceOrder.push(event.target.value);
console.log(serviceOrder);
};
let handelChangeEmployee = function(event){
console.log(employeeOrder);
employeeOrder = event.target.value;
console.log(employeeOrder);
};
return (
<div>
<Container className={classes.containerPixelActive}>
<h3>Afrekenen</h3>
<Row className={classes.tablePixelRow}>
<Col md={8} className={classes.rowChashdesk}>
<form>
<Row>
<Col md={6}>
<label>
Klant:
</label>
<br/>
<select >
{
client.map(function(item, i){
return <option key={i} value={item}>{item}</option>
})
}
</select>
</Col>
</Row>
<Row>
<Col md={6}>
<div className={classes.rowOfForm}>
<label>
Gender:
</label>
<br/>
<select onChange={handelChangeGender}>
{
gender.map(function(item, i){
return <option key={i} value={item}>{item}</option>
})
}
</select>
</div>
</Col>
</Row>
<Row>
<Col md={6}>
<div className={classes.rowOfForm}>
<label>
Behandeling:
</label>
<br/>
<select onChange={handelChangeService}>
{
service.map(function(item, i){
return <option key={i} value={item}>{item}</option>
})
}
</select>
</div>
</Col>
<Col md={6}>
<div className={classes.rowOfForm}>
<label>
Medewerker:
</label>
<br/>
<select onChange={handelChangeEmployee}>
{
employee.map(function(item, i){
return <option key={i} value={item}>{item}</option>
})
}
</select>
</div>
</Col>
</Row>
<Row>
<Col md={6}>
<div className={classes.rowOfForm}>
<label>
Verkregen behandeling:
</label>
<br/>
<input type="text" name="name" />
</div>
</Col>
<Col md={2}>
<div className={classes.rowOfForm}>
<label>
Aantal:
</label>
<br/>
<select>
{
counting.map(function(item, i){
return <option key={i} value={item}>{item}</option>
})
}
</select>
</div>
</Col>
<Col md={2}>
<div className={classes.rowOfForm}>
<label>
Prijs:
</label>
<br/>
<input type="text" name="name"/>
</div>
</Col>
<Col md={2}>
<div className={classes.rowIcon}>
<Close size={20} ></Close>
</div>
</Col>
</Row>
</form>
</Col>
<Col md={3} className={classes.rowChashdesk}>
<h5>Totaal overzicht</h5>
<h6>Medewerker</h6>
<p>{employeeOrder}</p>
<h6>Behandeling</h6>
<p>{serviceOrder}</p>
<h6>Aantal</h6>
<p>{countingOrder}</p>
<h6>Klant</h6>
<p>{clientOrder}</p>
<h6>Te betalen</h6>
<p>{payment}</p>
</Col>
</Row>
</Container>
</div>
);
}
The only way a react component knows to rerender is by your component (or some component above it) settings state. You're not using state, so it doesn't rerender.
Change this:
let employeeOrder = 'Raoul';
To this:
import { useState } from 'react';
// ... code omitted
const [employeeOrder, setEmployeeOrder] = useState('Raoul')
And change your handler to:
const handelChangeEmployee = function(event) {
setEmployeeOrder(event.target.value)
}
You will need to do similar things for genderOrder and ServiceOrder. You can't just push into an array and expect the page to update, you need to set state to a new array to cause the component to rerender. Don't mutate the old array, create a new one, as in:
setGenderOrder([...genderOrder, event.target.value])
For more info on useState and other hooks, see this page

How to use Multi-Select Dropdown in react-bootstrap

I am using react-bootstrap library. This library having a module called DropdownButton. So i am able to display data in dropdown. This is single selection data.
<DropdownButton
bsStyle="success"
title={this.state.addLeadStageSelectTitle}
key={"addleadstageDropDown"}
id={"addleadstageIDAdd"}
onSelect={this.handleSelectLeadStageAdd}
>
{this.state.vtx_sales_lead_status.map(objs => {
return (
<MenuItem eventKey={objs.id}>{objs.name}</MenuItem>
)
}
)}
</DropdownButton>
But I am trying to create it multiselect with same library.
Here is a multi-select example using hooks and react-bootstrap.
import React, { useState } from "react";
import { Col, Form } from "react-bootstrap";
export default function App() {
const [field, setField] = useState([]);
return (
<Form.Group as={Col} controlId="my_multiselect_field">
<Form.Label>My multiselect</Form.Label>
<Form.Control as="select" multiple value={field} onChange={e => setField([].slice.call(e.target.selectedOptions).map(item => item.value))}>
<option value="field1">Field 1</option>
<option value="field2">Field 2</option>
<option value="field3">Field 3</option>
</Form.Control>
</Form.Group>
);
}
I've checked the react-bootstrap documentation and it looks like there isn't a multiselect functionality.
So you can use a third party library, like: react-bootstrap-multiselect.
It's a Multiselect component for React (with Bootstrap). This is a React wrapper around an existing jQuery / Bootstrap library: bootstrap-multiselect
Basic usage:
import Multiselect from 'react-bootstrap-multiselect'
const data = [{ value:'One', selected:true }, { value: 'Two' }, { value:'Three' }]
const App = props => {
return <Multiselect onChange={props.handleChange} data={data} multiple />
}
Demo.
It is supported now:
import { Form } from 'react-bootstrap';
// [...]
<Form>
<Form.Control as="select" multiple value={options} onChange={onSelectedOptionsChange}>
{options.map(options => (
<option key={option.name} value={option.value}>
{option.name}
</option>
))}
</Form.Control>
</Form>

Redux-Form: Change in FieldArray submits parent form

I'm stuck on an issue with redux-form. I have a form which is being populated with initialValues. Inside the top level form I have a FieldArray which renders a list of input fields. Each input field has buttons to remove it (via fields.remove(index)) or insert another input right after it (via fields.insert(index+1)). My problem is: when I call fields.insert() the new field gets inserted and registered correctly, but the parent form gets submitted, which it shouldn't. Same happens on fields.push() when the data array has at least one item. But it does not on e.g. fields.remove() or fields.removeAll(). I cannot figure out why/where the submittal occurs. I've spend hours digging through the source and playing around with the official FieldArray example which does work. I couldn't find the issue online so I guess I have a bug somewhere, since this is independent of the redux-form version in use (tried >=6).
Thanks for your help, here's the code.
Parent Form
import React from 'react';
import { Field, FieldArray, reduxForm } from 'redux-form';
import Row from 'muicss/lib/react/row';
import Col from 'muicss/lib/react/col';
import Button from 'muicss/lib/react/button';
import MaterialInput from '../material/material-input';
import MaterialSelect from '../material/material-select';
import MaterialFieldArray from '../material/material-fieldarray';
import Cover from './cover';
import CheckboxGroup from './checkbox-group';
const MovieDetailsEditForm = props => {
const { handleSubmit, initialValues: { cover: { large: cover }, directors = [], actors = [] } } = props;
const getFSKOptions = () => {
return [
{value: 0, label: 0},
{value: 6, label: 6},
{value: 12, label: 12},
{value: 16, label: 16},
{value: 18, label: 18}
];
};
const getFormats = () => {
return [{value: 'DVD', label: 'DVD'}, {value: 'Blu-ray', label: 'Blu-Ray'}];
}
const getImages = () => props.initialValues.images.map( (image) => ({ value: image.large, checked: false }) );
return (
<Row>
<form className="mui-form" onSubmit={handleSubmit(props.handleFormSubmit)}>
<Col xs="12">
<Button type="submit" color="primary">Speichern</Button>
</Col>
<Col xs="12">
<Row>
<Col xs="12" md="6">
<Row>
<Col xs="12">
<Field name="title" id="title" component={MaterialInput} label="Filmtitel" type="text" />
</Col>
<Col xs="6">
<Field name="duration" id="duration" component={MaterialInput} label={props.initialValues.unit} type="text" />
</Col>
<Col xs="6">
<Field
name="format"
id="format"
options={getFormats()}
component={MaterialSelect}
label="Format"
parse={(value, name) => value ? value : null}
/>
</Col>
<Col xs="12">
<Field
name="fsk"
id="fsk"
options={getFSKOptions()}
component={MaterialSelect}
label="FSK Einstufung"
labelText="Freigegeben ab <<PLACEHOLDER>> Jahren"
parse={(value, name) => value ? value : null}
/>
</Col>
{ directors &&
<Col xs="12">
<h3>Regisseur{directors.length > 1 ? 'e' : ''}</h3>
<FieldArray component={MaterialFieldArray} name="directors" />
</Col>
}
{ actors &&
<Col xs="12">
<h3>Cast</h3>
<FieldArray component={MaterialFieldArray} name="actors" />
</Col>
}
</Row>
</Col>
<Col xs="12" md="6" className="cover">
<Field {...props} name="cover" id="cover" component={Cover} />
</Col>
</Row>
</Col>
<Col xs="12">
<Field {...props} name="images" component={CheckboxGroup} valueProperty="large" />
</Col>
</form>
</Row>
);
}
export default reduxForm({
form: 'MovieDetails',
enableReinitialize: true
})(MovieDetailsEditForm);
material-fieldarray.js
import React from 'react';
import { Field } from 'redux-form';
import Row from 'muicss/lib/react/row';
import Col from 'muicss/lib/react/col';
import Button from 'muicss/lib/react/button';
import MaterialInput from '../material/material-input';
export default props => {
const { fields } = props;
const addEntry = index => fields.insert(index + 1, '');
const removeEntry = index => fields.remove(index);
const renderEntries = () => {
return fields.map((field, index) => {
return (<li key={index}>
<Col xs="7" sm="8" md="7" lg="8">
<Field component={MaterialInput} name={`${field}`} id={`${field}`} />
</Col>
<Col xs="5" sm="4" md="5" lg="4" className="buttons">
<Button variant="fab" size="small" color="primary" onClick={() => addEntry(index)}>+</Button>
<Button variant="fab" size="small" color="danger" onClick={() => removeEntry(index)}>-</Button>
</Col>
</li>);
})
}
return (
fields.length &&
<ul className="inputfield-list">
{ renderEntries() }
</ul>
|| <Button onClick={() => fields.push('')}>Add</Button>
)
}
OK, the problem was a very subtle one and has nothing to do with React or Redux-Form. I forgot to put type="button" on the buttons that add/remove items to the FieldArray.
<Button variant="fab" size="small" color="primary" onClick={() => addEntry(index)}>+</Button>
That's how HTML forms work.

How to handle submitted values in my form using redux-form and serverside validation?

I'm using redux-form with a login form component in ReactJS.
But when I pass values to my form and I click on the submit button the values returned by the console.log are empty, and I don't know how to debug that.
Here's my form component
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link, withRouter } from 'react-router-dom';
import {reduxForm, Field} from 'redux-form';
import classnames from 'classnames'
// Actions
import {signin} from '../../actions/auth';
// Bootstrap
import { Grid, Row, Col, Image } from 'react-bootstrap';
// Includes
import '../../assets/css/users/signin.min.css';
import logo from '../../assets/images/datazonia_icone.png';
const renderField = ({input, label, type, forgotPassword=false, meta: {touched, error}}) =>(
<div className="form-group">
<label>{label}</label>
<input {...input} type={type}/>
{forgotPassword &&
<span className="forgot-pw">
<Link to="/users/password/reset">mot de passe oubliƩ ?</Link>
</span>}
{touched &&
error &&
<span className="help-block">
{error}
</span>}
</div>);
let SigninForm = (props) => {
const {handleSubmit, submitting, error } = props;
return (
<form onSubmit={handleSubmit}>
<Field
name="login"
component={renderField}
type='text'
input={{
className: "form-control"
}}
label="Email ou nom d'utilisateur"
/>
<Field
name="password"
component={renderField}
type="password"
input={{
className: "form-control"
}}
label='Mot de passe'
forgotPassword
/>
{error &&
<strong>
{error}
</strong>}
<button disabled={submitting} type="submit" className="btn btn-block btn-datazonia">Connexion</button>
</form>
);
};
SigninForm = reduxForm({
form: 'signin'
})(SigninForm);
class UserSignin extends Component {
onSubmit = (values) => {
console.log(values);
return this.props.signin(values, this.props.history, 'users');
};
render() {
return (
<div className="UserSignin">
<Grid>
<Row className="show-grid bloc-sign">
<Col sm={4} smOffset={4} xs={12} className="text-center title">
<Link to="/">
<Image src={logo} responsive className="center-block"/>
</Link>
<h3>Se connecter</h3>
</Col>
<Col sm={4} smOffset={4} xs={12}>
<div className="signin-form">
<SigninForm onSubmit={this.onSubmit}/>
</div>
</Col>
</Row>
</Grid>
</div>
);
}
}
UserSignin = connect(null, {signin})(withRouter(UserSignin));
export default UserSignin;
My values are empty when i click on the submit button, how can i get it to work ?
(And sorry for my English, I'm French)
OK, I've resolved this issue.
the problem was
input={{
className: "form-control"
}}
overrides the default behavior of redux-form

Resources