【问题标题】:Programmatically collapse all react-accessible accordion panels以编程方式折叠所有反应可访问的手风琴面板
【发布时间】:2021-09-10 00:22:31
【问题描述】:

我正在使用react-accessible-accordion 一次向用户呈现一个面板的表单。有一个“重置”按钮可以重置用户可能按下的任何按钮的影响。按钮位于面板内。您如何以编程方式折叠任何打开的面板? AccordionItem 有危险的SetExpanded 选项,但我没有看到任何实际使用的示例或该选项的完整文档(这就是option is described in the docs)。我是否必须在此处使用状态变量来使每个项目的展开折叠状态能够以编程方式对其进行操作?这是我现在拥有的代码的简化版本:

import React from 'react';
import ToggleButton from "react-bootstrap/ToggleButton";
import ButtonGroup from "react-bootstrap/ButtonGroup";
import 'bootstrap/dist/css/bootstrap.min.css';
import {Accordion, AccordionItem, AccordionItemHeading, AccordionItemButton, AccordionItemPanel} from 'react-accessible-accordion';


export const AccordionComponent = props => {
  stateHooks = [React.useState(-1), React.useState(-1)]
  const [ [varA, setVarA], [varB, setVarB] ] = stateHooks
  
  const handleResetAccordion = e => {
    e.preventDefault();
    stateHooks.forEach(hook => {  // pass -1 to each setter
      hook[1]('-1');  // index 1 contains the setter
    })
  }

  return (
    <div className="accordion_container">
      <Accordion allowZeroExpanded={true}>
        <AccordionItem>
          <AccordionItemHeading>
            <AccordionItemButton> Panel #1 Title </AccordionItemButton>
          </AccordionItemHeading>
          <AccordionItemPanel>
            <div className='radioQuestionCard'>
              <h3>Question #1 Prompt:</h3>
              <ButtonGroup className='radio' toggle id='q1'>
                <ToggleButton key='0' type="radio" name="q1" value='0' checked={varA === '0'}
                  onChange={e => setVarA(e.currentTarget.value)} > Q1: Option1
                </ToggleButton>
                <ToggleButton key='1' type="radio" name="q1" value='1' checked={varA === '1'}
                  onChange={e => setVarA(e.currentTarget.value)} > Q1: Option2
                </ToggleButton>
              </ButtonGroup>
            </div>
          </AccordionItemPanel>
        </AccordionItem>
        <AccordionItem>
          <AccordionItemHeading>
            <AccordionItemButton> Panel #2 Title </AccordionItemButton>
          </AccordionItemHeading>
          <AccordionItemPanel>
            <div className='radioQuestionCard'>
              <h3>Question #2 Prompt:</h3>
              <ButtonGroup className='radio' toggle id='q2'>
                <ToggleButton key='0' type="radio" name="q2" value='0' checked={varB === '0'}
                  onChange={e => setVarB(e.currentTarget.value)} > Q2: Option1
                </ToggleButton>
                <ToggleButton key='1' type="radio" name="q2" value='1' checked={varB === '1'}
                  onChange={e => setVarB(e.currentTarget.value)} > Q2: Option2
                </ToggleButton>
              </ButtonGroup>
            </div>
          </AccordionItemPanel>
        </AccordionItem>
      </Accordion>
      <button className='btn btn-danger btn-sm'
        onClick={handleResetAccordion} id='resetAccordion'> Reset
      </button>
    </div>
  )
}

【问题讨论】:

  • 看起来你已经在使用重置功能了。 “以编程方式折叠任何打开的面板”是什么意思?你想什么时候把它们全部折叠起来?
  • 用例是有人正在使用面板中的按钮进行选择,然后意识到他们想要重置所有答案。这些都是通过 handleResetAccordion 方法完成的,但我也希望打开的面板也可以关闭。这目前使打开的面板保持打开状态。
  • 您是否尝试在AccordianItems 上添加dangerouslySetExpanded 属性?其他几件事 - 文档说dangerouslySetExpanding,但这是错误的。在上面,您正在检查项目 b 中的 varA,可能只是一个伪代码拼写错误。看看这里的代码 - github.com/springload/react-accessible-accordion/tree/master/… - 你可以看到道具是如何使用的。
  • @MarkSwardstrom 我在原始问题中链接到该示例,但它是手动分配,而不是编程。换句话说,您可以从一开始就强制打开某些面板,但这不是动态的,并且手风琴不能再被用户操作。 dangerouslySetExpanded 标志的用例非常狭窄。

标签: reactjs accordion


【解决方案1】:

react-accessible-accordion 故意省略了以编程方式控制手风琴面板的展开状态的能力,因此我发现的解决方法是将整个手风琴放在一个 div 中,并为该 div 提供一个关键参数。当按键发生变化时,手风琴将被强制重新初始化。

let accordion_key = 12345;

const handleReinitialize = () => accordion_key++;

return(
  <div className="accordion_container" key={accordion_key}>
    <Accordion>
      <AccordionItem>
        <AccordionItemHeading>
        ... etc.
    <button onClick={handleReinitialize} id='reinitialize'>Reinitialize Accordion</button>
  </div>
)

【讨论】:

  • 当我重新初始化时,当我将它用于 FORM 技术时,我会丢失我当前的状态。换句话说,在使用此方法时要小心您的用例,否则 AccordionItem 中包含的 {children} 将重新初始化...
  • 此方法有效,但无需将手风琴包装在 div 中。可以直接为手风琴设置键。
  • 在这种情况下,div 是必要的,因为 React 要求您返回单个元素,因此您不能将 Accordion 和按钮作为两个松散的元素。但你说得对,钥匙可以直接放在手风琴上。
【解决方案2】:

我认为您可以将其设为布尔变量并以编程方式对其进行更改。如果它的值未定义,它将使用按钮状态值。

<AccordionItem dangerouslySetExpanded={isExpanded}> 
...
</AccordionItem>

isExpanded 由某处的 setState 变量设置

const [ isExpanded, setIsExpanded ] = setState()
const closeAll = () => {
  setIsExpanded(false)
}

【讨论】:

  • 这确实关闭了所有 AccordionItems,但用户无法再与它们进行交互,因此如果为 false,用户将无法再次打开它们。如果设置为 false,然后未定义,则按钮状态将重新打开关闭的任何内容。
猜你喜欢
  • 2021-03-17
  • 2014-02-18
  • 2017-02-27
  • 2021-07-07
  • 2011-06-19
  • 1970-01-01
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多