Home > Software engineering >  React How to avoid the need for ctrl-click in a multi-select box using?
React How to avoid the need for ctrl-click in a multi-select box using?

Time:09-14

I am using React and I would like use only click to select/unselect items in multi-select instead "ctrl click", it's possible in java script and jquery as the below code

$('option').mousedown(function(e) {
    e.preventDefault();
    $(this).prop('selected', !$(this).prop('selected'));
    return false;
});

is there are a way to be implemented with React ?

My Code Like this

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.Select multiple aria-label="Default select example" 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.Select>
    </Form.Group>
  );
}

CodePudding user response:

I was able to achieve this by doing this. I have two states one is the option and the other one is all the option I have selected. Now In the handleChange function I'm checking if the value is new add it into the array else remove it.


NOTE: now you can add multiple item without using ctrl


import React, { useState } from "react";

export function App(props) {
  const [options, setOptions] = useState(["field1", "field2", "field3"]);
  const [selected, setSelected] = useState([]);

  const handleChange = (e) => {
    e.preventDefault();
    let newArr = [];

    // checking if its exists remove it
    if (selected.includes(e.target.value)) {
      newArr = selected.filter((item) => item != e.target.value);
    } else {
      // eles adding into selected array
      newArr = [...selected, e.target.value];
    }

    // update state
    setSelected(setSelected);
  };
  return (
    <div className="App">
      <select multiple value={selected} onChange={handleChange}>
        {options.map((singleOption, index) => (
          <option key={index} value={singleOption}>
            {singleOption}
          </option>
        ))}
      </select>
    </div>
  );
}

CodePudding user response:

You can intercept the mousedown event, and just toggle the specific option.

const toggleOption = event => {
  event.preventDefault();
  const option = event.target;
  option.selected = !option.selected;
  const selectElement = option.closest('select');
  setField([...selectElement.selectedOptions].map(item => item.value))
}

and skip the onChange event.

<Form.Select
  multiple
  aria-label="Default select example"
  multiple
  value={field}
  onm ouseDown={toggleOption}
>
  <option value="field1">Field 1</option>
  <option value="field2">Field 2</option>
  <option value="field3">Field 3</option>
</Form.Select>
  • Related