Customize your AutoComplete with MUI styling

Upon taking over a project, I found myself working with material ui for the first time. Here is an excerpt from my code:

<FormControl fullWidth>
    <InputLabel
        className={className}
        htmlFor={id}
        error={error}
    >
        {label}
    </InputLabel>
    <Input
        className={className}
        id={id}
        value={value}
        onChange={(e) => {
            onChange(e.target.value)
        }}
    />
</FormControl>

This setup works well everywhere, with the label shrinking and styles being applied correctly. However, when inspecting the code, I noticed that the underline is styled using :before and :after pseudo classes.

Now, I need to apply similar styling to an Autocomplete component which uses Google Places to autocomplete locations. Specifically, I am working with the react-google-autocomplete library for this purpose.

I have attempted several methods, including:

const {ref} = usePlacesWidget({
    apiKey: process.env.REACT_APP_API_KEY,
    onPlaceSelected: (place) => {
        console.log(place);
    },
});


return (

    <FormControl fullWidth>

        <InputLabel
            className={className}
            htmlFor={id}
            error={error}
        >
            {label}
        </InputLabel>
        <Autocomplete
            ref={ref}
            id={id}
            className={className}
            placeholder=""
            renderInput={(params) => (
                <Input
                    {...params}
                    InputProps={{
                        ...params.InputProps,
                        className: {className}
                    }}
                />
            )}
        />
    </FormControl>
);

Despite the attempts, the label does not shrink as expected. I even tried adding:

InputLabelProps={{
  shrink: true,
  ...props.InputLabelProps,
 }}

without success.

The text field displays the correct size and font style but lacks any pseudo-class styling, featuring the default outline style instead.

I aim to replicate the appearance of the other text fields in the initial code snippet by applying the passed className. Any guidance would be greatly appreciated.

On a related note, when attempting the following:

const {ref} = usePlacesWidget({
    apiKey: process.env.REACT_APP_API_KEY,
    onPlaceSelected: (place) => {
        console.log(place);
    },
});


return (
<FormControl fullWidth>
    <InputLabel
        className={className}
        htmlFor={id}
        error={error}
    >
        {label}
    </InputLabel>

    <Input
        ref={ref}
        id={id}
        className={className}
    />
</FormControl>
);

The component receives styling, although the search functionality fails to work. This outcome was somewhat anticipated, but it would be beneficial to find a resolution for this issue as well.

Answer №1

It's difficult to pinpoint the exact issue without a provided code sandbox, but after reviewing the documentation, it seems that the problem may be related to not forwarding refs to the custom input component. You can refer to the following link for more information: https://mui.com/material-ui/react-autocomplete/#custom-input

The examples from MUI always utilize the TextField.

Additionally, based on my observations, the documentation for react-google-autocomplete does not include any examples resembling the way you are attempting to implement it. For reference, you can check out this link: https://github.com/ErrorPro/react-google-autocomplete/blob/HEAD/docs/examples.js

Answer №2

This solution may not be perfect, and I have not verified it with an actual API key as I do not possess one at the moment. Essentially, you can utilize the slots and slotsProps properties within the <Input> MUI component to integrate the <Autocomplete> component in place of the default <input> slot. Here is an example:

        <Input
          id={id}
          slots={{ input: Autocomplete }}
          slotProps={{ input: { apiKey: API_KEY, className: inputClasses } }}
        />

However, a drawback of this approach is that the default input styles are not automatically applied to the <Autocomplete>. To work around this issue, you can manually copy the className from the default <input> element provided by the MUI <Input> component like so:

  const hiddenInputRef = useRef(null);
  const [inputClasses, setInputClasses] = useState("");

  useEffect(() => {
    setInputClasses([...hiddenInputRef.current.classList].join(" "));
  });
...
      <Input style={{ display: "none" }} inputRef={hiddenInputRef} />

Here is a snippet of the minimum required code:

import { useState, useEffect, useRef } from "react";
import {
  FormControl,
  InputLabel,
  Input,
} from "@mui/material";
import Autocomplete from "react-google-autocomplete";

function App() {
  const API_KEY = "xxx";
  const [id, setId] = useState("inputId");
  const hiddenInputRef = useRef(null);
  const [inputClasses, setInputClasses] = useState("");

  useEffect(() => {
    setInputClasses([...hiddenInputRef.current.classList].join(" "));
  });
  return (
    <>
      <FormControl fullWidth>
        <InputLabel htmlFor={id}>label</InputLabel>
        <Input
          id={id}
          slots={{ input: Autocomplete }}
          slotProps={{ input: { apiKey: API_KEY, className: inputClasses } }}
        />
      </FormControl>
      <Input style={{ display: "none" }} inputRef={hiddenInputRef} />
    </>
  );
}

export default App;

Please note that I have not tested this setup with a working API key, so it is advisable to validate it using a legitimate API key before implementation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What might be the reason for the border not reaching the bottom of the popup in my chrome extension?

I am currently working on a Chrome extension and using Bootstrap 5 with Sass to style its popup. However, I have encountered an issue where the border of the popup does not extend to the bottom as expected. What could be causing this problem? popup.html & ...

Sliding panels with Jquery

I've created some basic panels that slide in and out horizontally. My goal is to hide all content except the first panel when the page loads. When a link to other panels is clicked, the current content will slide left to be hidden and new content will ...

Keep the Material UI ClickAwayListener open during touchmove events

My lack of experience with mobile touch events has led me to seek clarification on a specific issue. I have implemented a Material UI ClickAwayListener that wraps a Popper. The objective is for this Popper to remain open until the user clicks or taps outsi ...

Concentrating on a Div Element in React

I'm trying to set up an onKeyPress event that will be triggered when a key is pressed while a 'Level' element is displayed. I know that the div needs to be focused for events to register, but I'm not sure how to do this with functional ...

CSS trick that works on iOS16 as well

Previously, this CSS workaround was effective up to iOS version 15.6; however, it does not seem to be functioning in iOS 16. @media not all and (min-resolution:.001dpcm) { @supports (-webkit-appearance:none) {} } Are there any updated techniques avail ...

Organizing the website's files and extensions

Transitioning from programming desktop applications to websites can be overwhelming, especially when dealing with multiple languages and extensions like JavaScript, CSS, JSON, Bootstrap, Ajax, and PHP all at once. How do you effectively juggle these diff ...

Changing the background color of the canvas using Javascript

I want to create a rect on a canvas with a slightly transparent background, but I don't want the drawn rect to have any background. Here is an example of what I'm looking for: https://i.stack.imgur.com/axtcE.png The code I am using is as follo ...

Could not find the 'injectTapEventPlugin' export in the dependencies of Material-UI related to 'react-tap-event-plugin'

Currently, I am working on a project that involves using react, typescript, material-ui, and webpack. An issue has arisen with importing the injectTapEventPlugin function from the dependency of Material-UI, react-tap-event-plugin. The specific error messag ...

`Loading CSS files in Node.js with Express``

My CSS isn't loading properly when I run my HTML file. Even though the HTML is correctly linked to the CSS, it seems like express and node.js are not recognizing it. I find it confusing to understand the articles, tutorials, and stack overflow questio ...

children blocking clicks on their parents' divs

I previously asked a question about a parent div not responding to click events because its children were blocking it. Unfortunately, I couldn't recreate the issue without sharing a lot of code, which I didn't want to do. However, since I am stil ...

I am looking to implement a feature in my quiz application where a green tick mark appears next to the question number for the correct answer and a red cross mark for the wrong answer

My HTML code here retrieves questions from a database and displays them based on the question number. <h4>{{indexOfelement+1}}</h4>&nbsp;&nbsp; In my CSS, I need to style the questions as follows: How can I achieve this? Each question ...

Ways to modify the height of a button without impacting other buttons?

My goal is to create a calculator that looks like the image attached below: However, I'm having trouble aligning the equal button properly. How can I adjust it to match the equal button in the image? Here's the code snippet I'm currently w ...

When I try to upload an image onto my website, the layout of my text gets disrupted

There seems to be quite a gap between the welcoming message and the main body text. Significant spacing noticed between Title and body ...

Can the CSS be used to conceal the PNG image while still preserving the drop shadow effect?

I recently applied the "Filter: drop-shadow" effect to my png photo and it worked perfectly. However, I am now interested in hiding the actual png image while retaining the shadow effect. My initial attempt involved adjusting the translate and drop-shadow ...

Two CSS Issues - One specific to mobile devices, the other unique to Chrome browser

Having trouble with the top banner not stretching all the way on iPhone. Any solutions? Here's a screenshot for reference: Below is the CSS applied to the div: #banner { background-color: #F7F7F7; background-size: cover; box-shadow: 0 0 ...

Creating a static Top Bar that remains unaffected by page refreshing using Ajax or any other method can be achieved by implementing JavaScript and CSS

I've designed a sleek top bar for my upcoming website project. Below is the CSS code snippet for creating this clean div bar: .topbar { display:block; width:100%; height:40px; background-color:#f5f5f5; } I'm looking to incorporate a simple .SWF ...

What is the best way to display link icons - as images or using CSS background-image URLs?

When designing a web UI, I am considering using iconography to represent actions such as adding, editing, deleting, and searching for items. However, I want to ensure that the purpose of each action is clear without displaying text and cluttering the UI sp ...

Use HTML to showcase an image that dynamically changes based on the outcome of a query function

Hello there, I hope my inquiry is clear enough. I apologize for reaching out as I am unsure where to begin and what exactly I should be focusing on. Currently, I have an image displayed in an HTML page like this: <div id="tag_sunrise_sunset"><p ...

The class within the div element will fail to pick up the specified CSS styles

I've been troubleshooting an issue with a newly created div that's not picking up its corresponding styles from the stylesheet. It's frustrating and I could really use some help. Here is the HTML: <div class="2columnlayout"> < ...

Steps for eliminating the "choose file" tooltip from a Material UI textfield:

I would like to display only the image name in the text field when an image is selected, without having the choose file button inside the text field. <TextField variant='outlined' fullWidth type="file" ...