reactjs 如何在单击按钮时打开TextField?

eyh26e7m  于 2023-04-11  发布在  React
关注(0)|答案(4)|浏览(169)

我在这里遇到了麻烦,我创建了一个选项,其中如果用户单击Other's按钮,TextField将打开,但问题是,当我再次单击Others按钮时,它不会关闭。
我想在这里是保持文本字段打开,只要按钮是highlighted and close it when the user unclickedit 在这个图像中,我点击了它,所以它将open`

但当我再次点击它。

它仍然开放。
因此,我在这里所做的是渲染QuestionChoices,并检查choices's essay === true,然后显示TextField

{
    "_id": "642d892955e310c62e46b9d3",
    "title": "Question Sample",
    "choices": [
        {
            "choices": "GAD Orientation",
            "essay": false,
        },
        {
            "choices": "Gender Sensitivity Training",
            "essay": false,
        },
        {
            "choices": "Gender Mainstreaming",
            "essay": false,
        },
        {
            "choices": "GAD Planning and Budgeting",
            "essay": false,
        },
        {
            "choices": "GAD Analysis Tools",
            "essay": false,
        },
        {
            "choices": "Harmonized Gender and Development Guidelines",
            "essay": false,
        },
        {
            "choices": "Gender Mainstreaming Evaluation Framework",
            "essay": false,
        },
        {
            "choices": "Others, enumerate",
            "essay": true,
        },
        {
            "choices": "None",
            "essay": false,
        }
    ],
    "type_of_question": true,
}

所以我在这里做的是,我检查了choice.essay === true,然后打开它。Part4.js

const [openChoiceId, setOpenChoiceId] = useState(null);
  const handleClick = (choice) => {
    if (choice.essay === true) {
      setOpenChoiceId(choice.choices);
    } else {
    }
  };

{currentChoices.map((choice, index) =>(
                  <Grid item xs={6} key={index}>
                   <label className="toggle-button" key={choice.id} onClick={() => handleClick(choice)}>
                   <input className="toggle-button__state" type="checkbox" name="choice" value={choice.choices} onChange={handleChange}/>
                   <span className="toggle-button__text">{choice.choices}</span>
                   
                   <Box sx={{position:'absolute', bottom: 50, left: 0, width: '100%', px: 2}}>
                   {openChoiceId === choice.choices && choice.essay === true && 
                   <TextField
                    id="filled-multiline-static"
                    label="Others"
                    fullWidth
                    multiline
                    rows={3}
                    name="essay" onChange={handleTextFieldChange} 
                    variant="outlined"
                  />}

                   </Box>

                 </label>
                  </Grid>
                  
              ))}

编辑:
当我尝试这个的时候。

const handleClick = (choice) => {
      setOpenChoiceId(choice.choices);
  };

附加信息

我在这里创建了一个codesandbox,希望它能帮上忙
https://codesandbox.io/s/pensive-star-wj57um?file=/src/sampleData.js
HandleChange来自我的父组件,所以它看起来是这样的

const [answer,setAnswer] = useState({
      email: email,
      category: type,
      affiliation: affiliation,
      part: `part${getSurveyPart}`,
      choice: "",
      essay: "",
     })

HandleChange.js

const handleChange = (e) => {
            const value = e.target.value;
            const inputType = e.target.type;
        
            let newChoice = answer.choice; // initialize newChoice with the current choice array
        
            if (inputType === 'radio') {
            newChoice = [value];
            } else if (inputType === 'checkbox') {
            const isChecked = e.target.checked;
            const choiceIndex = answer.choice.indexOf(value);
            if (isChecked) {
                newChoice = [...answer.choice, value];
            } else {
                newChoice = [
                ...answer.choice.slice(0, choiceIndex),
                ...answer.choice.slice(choiceIndex + 1),
                ];
            }
            }
        
            const newAnswer = { ...answer, choice: newChoice };

            setAnswer(newAnswer);
        };
4si2a6ki

4si2a6ki1#

我认为你只需要一个简单的布尔状态,并根据所选择的选项,你可以切换其值。
替换

const [openChoiceId, setOpenChoiceId] = useState(null);

const handleClick = (choice) => {
    if (choice.essay === true) {
      setOpenChoiceId(choice.choices);
    } else {
    }
  };

const [visibleTextField, setVisibleTextField] = useState(false);

const handleChange = (e, choice) => {
  if (choice.essay) {
    setVisibleTextField(e.target.checked);
  }
};

显示文本字段的条件应替换为

{
  visibleTextField && (
    <TextField
      id="filled-multiline-static"
      label="Others"
      fullWidth
      multiline
      rows={3}
      name="essay"
      onChange={handleTextFieldChange}
      variant="outlined"
    />
  );
}

监听更改事件,而不是像下面这样单击

<input
    className="toggle-button__state"
    type="checkbox"
    name="choice"
    value={choice.choices}
    onChange={(e) => handleChange(e, choice)}
  />

最终代码

const [visibleTextField, setVisibleTextField] = useState(false);

const handleChange = (e, choice) => {
  if (choice.essay) {
    setVisibleTextField(e.target.checked);
  }
};
{
  currentChoices.map((choice, index) => (
    <Grid item xs={6} key={index}>
      <label className="toggle-button" key={choice.id}>
        <input
          className="toggle-button__state"
          type="checkbox"
          name="choice"
          value={choice.choices}
          onChange={(e) => handleChange(e, choice)}
        />
        <span className="toggle-button__text">{choice.choices}</span>
      </label>

      <Box
        sx={{
          position: 'absolute',
          bottom: 50,
          left: 0,
          width: '100%',
          px: 2,
        }}
      >
        {visibleTextField && (
          <TextField
            id="filled-multiline-static"
            label="Others"
            fullWidth
            multiline
            rows={3}
            name="essay"
            variant="outlined"
          />
        )}
      </Box>
    </Grid>
  ));
}
vjhs03f7

vjhs03f72#

当你点击任何一个按钮时,确保一开始就将所有的“choices.essay”值设置为false。你可以通过以下方式做到这一点:

choices.forEach(item => item.essay = false);

然后,您可以打开或关闭essay textarea on按钮单击。如果essay为true,则设置为false。如果essay值为false,则设置为true。

const handleClick = (choice) => {
    if(choice.essay === true) {
        choice.essay = false
    } else {
        choice.essay = true
    }
}

而且,当你呈现组件时,确保只有当“choice.essay === true”时才呈现它。你可以删除“openChoiceId === choice.choice”语句。它是这样的

{choice.essay === true && 
    <TextField 
        id="filled-multiline-static"
        label="Others"
        fullWidth
        multiline
        rows={3}
        name="essay" onChange={handleTextFieldChange} 
        variant="outlined"
    />}
mlnl4t2r

mlnl4t2r3#

从编辑后的代码看,你似乎在选择多个选项,当你选择其他选项时,你需要显示输入。你可以做下面的事情来实现这一点。

const [openChoices, setOpenChoices] = useState([]);
  const handleChange = (e, choice) => {
    if (e.target.checked) {
      setOpenChoices(prev => [...prev, choice.choices]);
    } else {
      setOpenChoices(prev => prev.filter(p => p !== choice.choices));
    }
  };

在JSX中

{currentChoices.map((choice, index) =>(
                  <Grid item xs={6} key={index}>
                   <label className="toggle-button" key={choice.id}>
                   <input className="toggle-button__state" type="checkbox" name="choice" value={choice.choices} onChange={e => handleChange(e, choice)}/>
                   <span className="toggle-button__text">{choice.choices}</span>
                   
                   <Box sx={{position:'absolute', bottom: 50, left: 0, width: '100%', px: 2}}>
                   {openChoices.includes(choice.choices) && choice.essay === true && 
                   <TextField
                    id="filled-multiline-static"
                    label="Others"
                    fullWidth
                    multiline
                    rows={3}
                    name="essay" onChange={handleTextFieldChange} 
                    variant="outlined"
                  />}

                   </Box>

                 </label>
                  </Grid>
                  
              ))}
kuhbmx9i

kuhbmx9i4#

你有很多事情需要解决
首先,您没有检查复选框是否被选中,因此您可以将其删除或添加到状态

onClick={(e) => handleClick(choice,e)}

  const handleClick = (choice,e) => {
    setOpenChoiceId(e.currentTarget.checked ? choice : {});
  };

我删除了带有文本的span,并添加了一个带有htmlFor的标签,因此每当您单击文本时,它都会单击实际的复选框,现在onClick事件处理程序需要位于复选框而不是标签上

<label
      className="toggle-button"
      htmlFor={choice._id}
    >
      {choice.choices}
      </label>

      <input
        className="toggle-button__state"
        id={choice._id}
        type="checkbox"
        name="choice"
      onClick={(e) => handleClick(choice,e)}
        value={choice.choices}
      />

最后一件事是你做了一个错误的条件语句
要显示textField,您需要检查状态,而不是之前所做的,条件链接.?是因为openChoiceId将在没有复选框被选中时设置为空,并且将是一个对象,不会将essay作为属性

{openChoiceId?.essay === true && (jsx goes here) }

相关问题