admin管理员组

文章数量:1200985

I'm using Material UI (5) autocomplete to provide search functionality with the following user scenarios:

  • user enters text then presses enter -> go to search page with that text
  • user enters text and selects from drop down list -> go to search page with selected item

First first scenario doesn't work. The second does. Does autocomplete have its own ability to handle the enter key press or do I need to wrap it to get that key press event and send text input to search?

Because the first scenario has to be solved, I added a submit button. If I wrap the autocomplete in a div and put the action on that, the state doesn't have the correct query value.

I would like the autocomplete to send the correct text (either input or selected from suggestions) when the enter button is pressed.

I've tried freesolo and not freesolo and it doesn't seem to change the outcome. Does it only work in combination with another configuration?

import React, { useState, useEffect } from 'react';
import { TextField, Autocomplete, Button, Box } from '@mui/material';
import axios from '../../axios.js';

export default function SearchBar2({ postSearchHandler, query }) {
  const [q, setQ] = useState(() => query || '');
  const [suggestions, setSuggestions] = useState([]);

  const search = (value) => {
    console.log(`search: ${value}`);
    postSearchHandler(value);
  };

  useEffect(() => {
    console.log(`useEffect getSuggestions: ${q}`);
    if (q) {
      axios.post('/api/suggest', { q, top: 5, suggester: 'sg' })
      .then(response => {
          setSuggestions(response.data.suggestions.map(s => s.text));
      }).catch (error =>{
          console.log(error);
          setSuggestions([]);
        });
}}, [q]);


  const onInputChangeHandler = (event, value) => {
    console.log(`onInputChangeHandler: ${value}`);
    setQ(value);
  };


  const onChangeHandler = (event, value) => {
    console.log(`onChangeHandler: ${value}`);
    setQ(value);
    search(value);
  };

  const onEnterButton = (event) => {
    console.log(`onEnterButton: ${q}`);
    // if enter key is pressed
    if (event.key === 'Enter') {
      search(q);
    }
  };

  return (
    <div
      className="input-group"
      style={{ width: '95%', display: 'flex', justifyContent: 'center', alignItems: 'center', margin: '0 auto' }}
    >
      <Box sx={{ display: 'flex', alignItems: 'center', width: '75%', minWidth: '390px' }}>
      <Autocomplete
        freeSolo
        value={q}
        options={suggestions}
        onInputChange={onInputChangeHandler}
        onChange={onChangeHandler}
        disableClearable
        sx={{
          width: '75%',
          '& .MuiAutocomplete-endAdornment': {
            display: 'none'
          }
        }}
        renderInput={(params) => (
          <TextField
            {...params}
            id="search-box"
            className="form-control rounded-0"
            placeholder="What are you looking for?"
            onBlur={() => setSuggestions([])}
            onClick={() => setSuggestions([])}
          />
        )}
      />
      <div className="input-group-btn" style={{ marginLeft: '10px' }}>
        <Button variant="contained" color="primary" onClick={() => {
          console.log(`search button: ${q}`);
          search(q)}
          }>
          Search
        </Button>
      </div>
      </Box>
    </div>
  );
}

I'm using Material UI (5) autocomplete to provide search functionality with the following user scenarios:

  • user enters text then presses enter -> go to search page with that text
  • user enters text and selects from drop down list -> go to search page with selected item

First first scenario doesn't work. The second does. Does autocomplete have its own ability to handle the enter key press or do I need to wrap it to get that key press event and send text input to search?

Because the first scenario has to be solved, I added a submit button. If I wrap the autocomplete in a div and put the action on that, the state doesn't have the correct query value.

I would like the autocomplete to send the correct text (either input or selected from suggestions) when the enter button is pressed.

I've tried freesolo and not freesolo and it doesn't seem to change the outcome. Does it only work in combination with another configuration?

import React, { useState, useEffect } from 'react';
import { TextField, Autocomplete, Button, Box } from '@mui/material';
import axios from '../../axios.js';

export default function SearchBar2({ postSearchHandler, query }) {
  const [q, setQ] = useState(() => query || '');
  const [suggestions, setSuggestions] = useState([]);

  const search = (value) => {
    console.log(`search: ${value}`);
    postSearchHandler(value);
  };

  useEffect(() => {
    console.log(`useEffect getSuggestions: ${q}`);
    if (q) {
      axios.post('/api/suggest', { q, top: 5, suggester: 'sg' })
      .then(response => {
          setSuggestions(response.data.suggestions.map(s => s.text));
      }).catch (error =>{
          console.log(error);
          setSuggestions([]);
        });
}}, [q]);


  const onInputChangeHandler = (event, value) => {
    console.log(`onInputChangeHandler: ${value}`);
    setQ(value);
  };


  const onChangeHandler = (event, value) => {
    console.log(`onChangeHandler: ${value}`);
    setQ(value);
    search(value);
  };

  const onEnterButton = (event) => {
    console.log(`onEnterButton: ${q}`);
    // if enter key is pressed
    if (event.key === 'Enter') {
      search(q);
    }
  };

  return (
    <div
      className="input-group"
      style={{ width: '95%', display: 'flex', justifyContent: 'center', alignItems: 'center', margin: '0 auto' }}
    >
      <Box sx={{ display: 'flex', alignItems: 'center', width: '75%', minWidth: '390px' }}>
      <Autocomplete
        freeSolo
        value={q}
        options={suggestions}
        onInputChange={onInputChangeHandler}
        onChange={onChangeHandler}
        disableClearable
        sx={{
          width: '75%',
          '& .MuiAutocomplete-endAdornment': {
            display: 'none'
          }
        }}
        renderInput={(params) => (
          <TextField
            {...params}
            id="search-box"
            className="form-control rounded-0"
            placeholder="What are you looking for?"
            onBlur={() => setSuggestions([])}
            onClick={() => setSuggestions([])}
          />
        )}
      />
      <div className="input-group-btn" style={{ marginLeft: '10px' }}>
        <Button variant="contained" color="primary" onClick={() => {
          console.log(`search button: ${q}`);
          search(q)}
          }>
          Search
        </Button>
      </div>
      </Box>
    </div>
  );
}
Share Improve this question asked Jan 21 at 15:36 DFBerryDFBerry 2,0081 gold badge22 silver badges41 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

So you want to handle this situation:

User enters a text and presses Enter without selecting an option from dropdown list

To do this you need to implement the onKeyDown event.

onKeyDown={(event) => {
  if (event.key === 'Enter') {
    console.log(`onEnterButton: ${q}`);
    search(q);
  }
}}

Full code:

<Autocomplete
  freeSolo
  value={q}
  options={suggestions}
  onInputChange={onInputChangeHandler}
  onChange={onChangeHandler}
  disableClearable
  sx={{
    width: '75%',
    '& .MuiAutocomplete-endAdornment': {
      display: 'none',
    },
  }}
  onKeyDown={(event) => {
    if (event.key === 'Enter') {
      console.log(`onEnterButton: ${q}`);
      search(q);
    }
  }}
  renderInput={(params) => (
    <TextField
      {...params}
      id="search-box"
      className="form-control rounded-0"
      placeholder="What are you looking for?"
      onBlur={() => setSuggestions([])}
      onClick={() => setSuggestions([])}
    />
  )}
/>

Docs Reference.

本文标签: