Enable the input text field on clicking of a button

Viewed 53

I have two input fields which are basically password fields. The disabling of these two fields are controlled by two external flags. if already set flag is true, then make this disabled and show the text as "already set". Also , there is a button next to this input field that can make this input enable and then user should be able to enter the text as password. I am clearing "Already set" text whenever I click on this edit. In my case the content is cleared, but I am unable to edit.

Can some one help me here.

Sandbox:https://codesandbox.io/s/react-functional-component-forked-8nrbb1?file=/src/index.js:0-1419

import React, { useState } from "react";
import { render } from "react-dom";
import * as data from "./messages.json";

const App = () => {
  return <Test {...{ alreadySetVal1: true, alreadySetVal2: true }} />;
};

const Test = ({ alreadySetVal1, alreadySetVal2 }) => {
  const [input1, setInput1] = useState(alreadySetVal1 ? "Already Set" : "");
  const [input2, setInput2] = useState(alreadySetVal2 ? "Already Set" : "");
  const [config, setConfig] = useState({ config1: false, config2: false });
  return (
    <>
      <div>
        <input
          disabled={alreadySetVal1}
          value={input1}
          type={alreadySetVal1 ? "text" : "password"}
          onChange={(e) => setInput1(e.target.value)}
        />
        <span
          onClick={() => {
            setInput1("");
            setConfig({ ...config, config1: true });
          }}
        >
          Enable Input 1
        </span>
      </div>
      <div>
        <input
          disabled={alreadySetVal2}
          value={input2}
          type={alreadySetVal2 ? "text" : "password"}
          onChange={(e) => setInput2(e.target.value)}
        />
        <span
          onClick={() => {
            setInput2("");
            setConfig({ ...config, config2: true });
          }}
        >
          Enable Input 2
        </span>
      </div>
    </>
  );
};

render(<App messages={data.messages} />, document.getElementById("root"));


2 Answers

The issue is with the disabled property that you have added to your input tags, alreadySetVal1 and alreadySetVal2 . You are accessing these from props , so until and unless these values are changed from the parent element , you won't be able to edit the fields . So access the props via a local State and assign that local State variable as disabled property .

Working Link CodeSandbox

The input's disabled state should come from the config state which should use an initial state boolean state set from the passed props.

Example:

const Test = ({ alreadySetVal1, alreadySetVal2 }) => {
  const [input1, setInput1] = useState(alreadySetVal1 ? "Already Set" : "");
  const [input2, setInput2] = useState(alreadySetVal2 ? "Already Set" : "");

  // set initial config values if the passed input values are enabled or not
  const [config, setConfig] = useState({
    config1: !!input1, // disable input if value is truthy
    config2: !!input2
  });

  return (
    <>
      <div>
        <input
          disabled={config.config1} // <-- based on config value
          value={input1}
          type={config.config1 ? "text" : "password"}
          onChange={(e) => setInput1(e.target.value)}
        />
        <span
          onClick={() => {
            setInput1("");
            setConfig({ ...config, config1: false }); // <-- enable the input if clicked
          }}
        >
          Enable Input 1
        </span>
      </div>
      <div>
        <input
          disabled={config.config2}
          value={input2}
          type={config.config2 ? "text" : "password"}
          onChange={(e) => setInput2(e.target.value)}
        />
        <span
          onClick={() => {
            setInput2("");
            setConfig({ ...config, config2: false });
          }}
        >
          Enable Input 2
        </span>
      </div>
    </>
  );
};

Edit enable-the-input-text-field-on-clicking-of-a-button

enter image description here

Note that if Test needs to respond to and handle the alreadySetVal1 and alreadySetVal2 props values changing during its life that you might also need to implement a useEffect hook to synchronize the local state to keep everything running as expected.

It may look something like the following:

useEffect(() => {
  const input1 = alreadySetVal1 ? "Already Set" : "";
  const input2 = alreadySetVal2 ? "Already Set" : "";
  setInput1(input1);
  setInput2(input2);
  setConfig({
    config1: !!input1,
    config2: !!input2
  });
}, [alreadySetVal1, alreadySetVal2]);
Related