A simple guide on how to surround every incorrect input index in mapped inputs with red borders

I am incorporating a modal that corresponds each element of the object newCompanies to a specific row:

        {newCompanies.map((company, index) => {
          return (
            <div>
              <div
                className="side-by-side"
              >
                  <ModalInput
                    type="text"
                    id="name"
                    value={company.name}
                    onChange={(e) =>
                      this.editCompanyArr(index, "name", e, "validName")
                    }
                  ></ModalInput>
                  <ModalInput
                    type="text"
                    id="website"
                    value={company.website}
                    onChange={(e) =>
                      this.editCompanyArr(
                        index,
                        "website",
                        e,
                        "validWebsite"
                      )
                    }
                  ></ModalInput>
                      <ModalInput
                        type="text"
                        id="sector"
                        value={company.class}
                        onChange={(e) =>
                          this.editCompanyArr(
                            index,
                            "sector",
                            e,
                            "validSector"
                          )
                        }
                      ></ModalInput>

ModalInput is specifically defined in styles.js:

export const ModalInput = styled.input`
  padding: 10px;
  margin: 10px 0;
  border: 1px solid #f5f6f9;
  border-radius: 20px;
  background-color: #f5f6f9;
  height: 100%;
  width: ${props => props.width || 'auto'};
`;

This function is responsible for verifying if a user has inputted a correct value. For example, if numbers are detected within the name field, the value of validName will be set to false:

  editCompanyArr(i, obj, e, stateObject) {
      const { newCompanies, validName } = this.state;
      if (e.target.value.match("^[a-zA-Z ]*$") != null) {
        this.setState({ [stateObject]: true });
      } else {
        this.setState({ [stateObject]: false });
      }
      //edited out more body to update value in newCompanies
}

My concern arises in ensuring that if a user provides an incorrect input for any specific row, only that particular input and not all others receive a red border. How can I achieve this?

Answer №1

In order to achieve the desired outline effect, I recommend adding a CSS class that will style the inputs accordingly. By keeping track of the input's validity with a flag in the state, you can update the error status on submit and clear it when the user interacts with the input field.

Here is an example implementation using JSX:

const Form = () => {
  const [inputError, setInputError] = useState(false);
  const exampleInputRef = useRef(null);

  return (
    <form onSubmit={(e) => {
      const exampleInput = exampleInputRef.current;
      const exampleInputVal = exampleInput.value;

      if (exampleInputVal) {
        // Valid value - proceed with submission
      } else {
        // Invalid input - set error state
        setInputError(true);
      }
    }}>
      <input 
        className={inputError ? 'error' : ''} 
        ref={exampleInputRef}
        onChange={() => setInputError(false)}
        onFocus={() => setInputError(false)}
      />
    </form>
  );
}

Additionally, here is the corresponding CSS code snippet for the error styling:

input.error,
input:focus.error {
  outline: none;
  box-shadow: 0 0 0 1px red;
}

Answer №2

If you're looking to explore a different approach, consider the following:

Start by defining the necessary state variables. I opted for state variables named name and age for input values. Additionally, I included state variables for classes to trigger component re-renders and update border colors upon changes.

To initiate the process, I pre-set some initial className values so that the initial render displays a red border (utilizing border-danger from Bootstrap).

// initial classes
const initialClassNames = {
  name: "border-danger",
  age: "border-danger",
};

// required states
const [classNames, setClassNames] = useState(initialClassNames);
const [values, setValues] = useState({ name: "", age: 0 });

Subsequently, I associated distinct fields with their individual specifications which can be mapped later on. Notice how the state values are linked to the input field specifications.

// specs for all input fields
const inputFields = [
  {
    inputLabel: "Name",
    inputName: "name",
    inputValue: values.name,
    inputClassName: classNames.name
  },
  {
    inputLabel: "Age",
    inputName: "age",
    inputValue: values.age,
    inputClassName: classNames.age
  }
];

Within the return() function, each field is mapped over to provide the desired JSX elements.

return (
  <div className="container mt-3">
    {inputFields.map((f, i) => {
      return (
        <div className="mb-5" key={i}>
          <label htmlFor={`${f.inputName}${i}`}>{f.inputLabel}</label>
          <input
            id={`${f.inputName}${i}`}
            name={f.inputName}
            value={f.inputValue}
            onChange={handleChange}
            className={`form-control ${f.inputClassName}`}
          ></input>
        </div>
      );
    })}
  </div>
);

For handling change events in your inputs, utilize the following approach:

// handleChange for inputs
const handleChange = (e) => {
  e.preventDefault();
  setValues({
    ...values,
    [e.target.name]: e.target.value
  });
};

Additionally, validation can be implemented as shown below:

useEffect(() => {
  // validate name
  if (values.name) {
    setClassNames((prevState) => {
      return { ...prevState, name: (prevState.name = "border-success") };
    });
  } else {
    setClassNames((prevState) => {
      return { ...prevState, name: (prevState.name = "border-danger") };
    });
  }

  // validate age
  if (parseInt(values.age, 10)) {
    setClassNames((prevState) => {
      return { ...prevState, age: (prevState.age = "border-success") };
    });
  } else {
    setClassNames((prevState) => {
      return { ...prevState, age: (prevState.age = "border-danger") };
    });
  }
}, [values.name, values.age]);

Inside the useEffect() function, I verify whether the input fields are appropriately filled every time their values change (leading to component re-renders). Consequently, based on the validation result, I adjust the class names accordingly. In this illustration, Bootstrap classes like border-danger and border-success were used, but feel free to customize this according to your styling preferences.

Should you prefer validation only upon a specific event such as a button onClick(), that too can be accommodated.

View codesandbox example

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

Retrieve data from AJAX once the cycle is complete

Currently, I am attempting to calculate the sum of results from an external API by making a single request for each keyword I possess. The code is functioning properly; however, the function returns the value before all the ajax requests are completed. Eve ...

How do I use jQuery to animate a height increase where the added height is applied to the top of the element?

I am facing a simple issue that I need help resolving. The problem involves hidden content that, once expanded, needs to have a height of 99px. When collapsed, the container holding this content section#newsletter is set to be 65px in height. If you want ...

Eliminate the unnecessary gap below the image

I have noticed that there is too much space beneath an image on my website. I have tried checking for extra tags, but I suspect that it might be controlled in a css file. Could someone please help me identify which part of the css is causing this extra ...

What is the solution for the error "At-rule or selector required" ?

Can someone help me with my CSS code issues? I'm having trouble on the first and last lines. Total newbie here :) Error Messages: at-rule or selector expected (ln 1, Col 1) at-rule or selector expected (ln 51, Col 1) &bso ...

Guide on subscribing to an object from a service in Angular 2/5

I am facing an issue where I need to update my property component with data received from the server. In the Service, I have implemented something like this: private events: Event[] = []; eventChanged = new Subject<any>(); // Edit: added an observa ...

Steps for iterating through an array within an object

I currently have a JavaScript object with an array included: { id: 1, title: "Looping through arrays", tags: ["array", "forEach", "map"] } When trying to loop through the object, I am using the following ...

Turn off HTML5 Audio

There are 4 <audio> elements on a webpage. The client has asked for them to be available sequentially. Meaning, the first audio should play, then the rest should remain disabled until the first one finishes, and so on. In addition, they want the au ...

Is there a way to adjust the placement of the h1 tag using the before pseudo-element?

I'm looking to place an image on the left side of each h1 tag. I've been attempting to utilize the before pseudo element for this task. The issue arises when there is no content, causing the before pseudo element to overlap with the h1 tag. How ...

Error: webpack is failing to load the style and CSS loaders

I'm currently experimenting with the FullCalendar plugin from fullcalendar.io. They recommended using Webpack as a build system, which is new to me. I managed to set up the calendar functionality after some research, but I'm facing issues with th ...

Creating Spinning Text Effects in Internet Explorer with CSS

Inside a list item (<li>), I have some text that I want to rotate 270 degrees. Direct methods in FireFox, Safari, Chrome, and Opera work fine for this, but when it comes to IE, there is no direct support. I've tried using filters like matrix and ...

Retrieving data from Node.js within an Angular application

I am currently working on retrieving data from MongoDB and displaying it on my website. However, I am facing an issue in sending the entire fetched object to a specific port (the response) so that I can retrieve it from Angular. I also need to know how to ...

Strategies for capturing POST data sent to a JavaScript webpage

The request is sent from an external source beyond my control xyz.php <form action='https_:_//xyz.com/javascriptFile' method='POST'> <input type='text' name='data' /> </form> to: (My custom f ...

I am struggling to figure out how to incorporate a minimum 5-character validation requirement into the login form of this ant design. Unfortunately, I

After reviewing all the examples of ant.design form, I am unable to locate the validation for minimum length in the textboxes. Can someone assist me with this? https://ant.design/components/form/?locale=en-US#header https://codesandbox.io/s/pww70x7y6q i ...

Exploring Tailwind CSS for customizing the Material-UI "DateCalendar" component aesthetics

Currently, I am in the process of implementing a mini-calendar that bears a striking resemblance to Google's calendar display on the top-left corner (with a few design modifications). Utilizing Tailwind for styling react-components, I decided to opt f ...

Fade out the notification div when the user clicks anywhere outside of it

I am currently working on a website with a notification feature. When the user clicks on the notification button, a notification box will appear at the bottom of the button. I would like the behavior of this notification to be similar to Facebook's - ...

New Feature in Material UI V5: Ability to Specify Multiple Variants in the Primary Palette when Creating Theme

I am working with two different themes, one is the darkcustomtheme: export const darkcustomTheme = createTheme({ palette: { mode: 'dark', primary: { main: darkprimaryColor, dark: grey[100], light: grey[200], } ...

An error with rendering in Internet Explorer 8

When I hide a td in a table by setting its display to none, the table does not resize correctly when using IE8. If I have a table and want to remove an entire column, I might try something like this: $("th:first, th:last, tr td:first-child, tr td:last-ch ...

Can the :after pseudo-element be modified when hovering, except when hovering over the after element itself?

Currently, my CSS code looks like this: class-name:hover:after {} Although it works well, the hover effect triggers even when hovering over the after portion of the element. Is there a way to modify the code so that the :hover only applies when hovering ...

Trouble displaying JSON data when using a search box filter in React

My webpage is using JSON dummy data that can be filtered by keywords entered into a search box. Previously, all the data displayed correctly before creating filteredJson, but now nothing is showing up. What could be causing this issue? I want to send the ...

Issue with Vuetifyjs theme variable failing to function properly in version 1.0.0

Check out the step-by-step instructions provided in https://vuetifyjs.com/en/style/theme. I successfully changed the theme using the code below with vuetifyjs version 0.13.0. However, after updating to vuetifyjs 1.0.5, the font still displays correctly bu ...