Как сделать вложенный Аккордеон?

В библиотеке semantic_ui-react существует компонент Accordion. Есть несколько примеров, но я должен сделать вложенный аккордеон, который имеет структуру:

-accordion:
    -sub_accordion1
    -sub_accordion2
    -sub_accordion3

Я видел пример вложенной гармошки с панелями, но я не хочу вставлять гармошки в панели. Я пробовал так:

export default class AccordionExampleStandard extends Component {
  state = { activeIndex: 0 }

  handleClick = (e, titleProps) => {
    const { index } = titleProps
    const { activeIndex } = this.state
    const newIndex = activeIndex === index ? -1 : index

    this.setState({ activeIndex: newIndex })
  }

  render() {
    const { activeIndex } = this.state

    return (
      <Accordion>
        <Accordion.Title active={activeIndex === 0} index={0} onClick={this.handleClick}>
          <Icon name='dropdown' />
          What is a dog?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 0}>
          <Accordion.Title active={activeIndex === 1} index={1} onClick={this.handleClick}>
          <Icon name='dropdown' />
          What kinds of dogs are there?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 1}>
          Content1
        </Accordion.Content>

        <Accordion.Title active={activeIndex === 2} index={2} onClick={this.handleClick}>
          <Icon name='dropdown' />
          How do you acquire a dog?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 2}>
          Content2
        </Accordion.Content>
<Accordion.Title active={activeIndex === 3} index={3} onClick={this.handleClick}>
          <Icon name='dropdown' />
          What kinds of dogs are there?
        </Accordion.Title>
        <Accordion.Content active={activeIndex === 3}>
         Content3
        </Accordion.Content>
        </Accordion.Content>
      </Accordion>
    )
  }
}

Он отображает компонент, но я могу свернуть только основной аккордеон и не могу свернуть его дочерние элементы. Как я могу выполнить эту функцию?


person Sam Fisher    schedule 21.12.2017    source источник


Ответы (3)


Поскольку вы упомянули, что вам нужно простое решение, лучше использовать panels, потому что они, кажется, автоматически управляют activeIndex, который является основным атрибутом, который определяет расширение и сжатие аккордеона. Если вы должны были сделать это самостоятельно, как указано выше, вам нужно поддерживать всю иерархию и манипулировать собой, настраивая состояние в обработчике onClick. Итак, если ваш вариант использования не является индивидуальным или сложным, вы можете попробовать что-то вроде ниже.

Вот рабочая демонстрация Вложенный семантический интерфейс ACCORDION

import { Accordion } from 'semantic-ui-react';

const AccordionContent = (content) => (
  <div className="indent">
    {content}
  </div>
)

const SubAccordion1Panels = [
  {
    title: 'Sub Accordion 11',
    content: { content: AccordionContent('11 Content'), key: '11-content'} ,
    key: 'sub-accordion-11'
  }, {
    title: 'Sub Accordion 12',
    content: { content: AccordionContent('12 Contents'), key: '12-content' },
    key: 'sub-accordion-12'
  }, {
    title: 'Sub Accordion 13',
    content: { content: AccordionContent('13 Contents'), key: '13-content' },
    key: 'sub-accordion-13'
  },
]

const SubAccordion1Content = (
  <div className="indent">
    <Accordion.Accordion
      style={{marginLeft: "20px"}}
      className="no-padding"
      panels={SubAccordion1Panels}
    />
  </div>
)

const SubAccordionPanels = [
  {
    title: 'Sub Accordion 1',
    content: { content: SubAccordion1Content, key: 'sa1-content' },
    key: 'sub-accordion-1'
  }, {
    title: 'Sub Accordion 2',
    content: { content: AccordionContent('SA2 Content'), key: 'sa2-content' },
    key: 'sub-accordion-2'
  }, {
    title: 'Sub Accordion 3',
    content: { content: AccordionContent('SA3 Content'), key: 'sa3-content' },
    key: 'sub-accordion-3'
  }
]

const SubAccordions = (
  <div className="indent">
    <Accordion.Accordion
      className="no-padding"
      panels={SubAccordionPanels}
    />
  </div>
)

const AccordionPanels = [
  { title: 'Accordion', content: { content: SubAccordions, key: 'sub-accordions' } },
]

const AccordionExampleNested = () => (
  <Accordion
    defaultActiveIndex={0}
    panels={AccordionPanels}
  />
)

class App extends React.Component {
  render() {
    return (
      <AccordionExampleNested />
    )
  }
}

Также для отступа вам нужно переопределить css по умолчанию

.indent {
  margin-left: 1em;
}

.no-padding {
  padding: 0px !important;
  margin: 0px !important;
}
person Nandu Kalidindi    schedule 22.12.2017

Как правильно сделать вложенную гармошку:

import React from 'react'
import { Accordion } from 'semantic-ui-react'

const level1Panels = [
  { title: 'Level 1A', content: 'Level 1A Contents' },
  { title: 'Level 1B', content: 'Level 1B Contents' },
]

const Level1Content = (
  <div>
    Welcome to level 1
    <Accordion.Accordion panels={level1Panels} />
  </div>
)

const level2Panels = [
  { title: 'Level 2A', content: 'Level 2A Contents' },
  { title: 'Level 2B', content: 'Level 2B Contents' },
]

const Level2Content = (
  <div>
    Welcome to level 2
    <Accordion.Accordion panels={level2Panels} />
  </div>
)

const rootPanels = [
  { title: 'Level 1', content: { content: Level1Content, key: 'content-1' } },
  { title: 'Level 2', content: { content: Level2Content, key: 'content-2'         } },
]

const AccordionExampleNested = () => (
  <Accordion defaultActiveIndex={0} panels={rootPanels} styled />
)

export default AccordionExampleNested
person Mosè Raguzzini    schedule 21.12.2017
comment
Возможно, он пропустил документы, потому что предложенные фрагменты работают прямо из коробки. - person Mosè Raguzzini; 21.12.2017
comment
Я увидел этот фрагмент и написал в ответ, что делать панно-гармошку не нужно. Мне нужно сделать просто, без панелей. в этом фрагменте мы видим панели = {rootPanels} - person Sam Fisher; 21.12.2017

Вот моя версия этого. Это рекурсивный аккордеон внутри аккордеона внутри аккордеона (бесконечно).

Его также на CodePen https://codepen.io/codeman1293/pen/OJWppQM?editors=1111

console.clear();
const ButtonToolbar = ReactBootstrap.ButtonToolbar;
const Button = ReactBootstrap.Button;
const Jumbotron = ReactBootstrap.Jumbotron;
const Accordion = ReactBootstrap.Accordion;
const Panel = ReactBootstrap.Panel;

var baseItems = [
  { id: 1, title: "Land", body: "", parentId: 0 },
  { id: 2, title: "Sea", body: "Submarine", parentId: 0 },
  {
    id: 8,
    title: "Air",
    body: "Helicopter<br />Aeroplanes<br />Drones",
    parentId: 0
  },
  { id: 3, title: "Cars", body: "", parentId: 1 },
  { id: 4, title: "Vans", body: "Transit<br />Sprinter", parentId: 1 },
  {
    id: 5,
    title: "Boats",
    body: "Speedboat<br />Fishing Boat<br />Dinghy",
    parentId: 2
  },
  { id: 6, title: "Petrol", body: "", parentId: 3 },
  { id: 7, title: "Automatic", body: "", parentId: 6 },
  { id: 9, title: "2.0L", body: "BMW X3<br />Mercedes GLC<br />Audi Q5", parentId: 7 }
];

const App = React.createClass({
  render() {
    const RecursiveAccordion = ({ items, recurse = false }) => {
      return (
        <Accordion>
          {items.map((item, index) => {
            var children = baseItems.filter((i) => {
              return i.parentId === item.id;
            });

            var hasChildren = children.length > 0;

            if (item.parentId === 0) {
              return (
                <Panel header={item.title} eventKey={index}>
                  {hasChildren && (
                    <div>
                      <RecursiveAccordion items={children} recurse={true} />
                      <div dangerouslySetInnerHTML={{ __html: item.body }} />
                    </div>
                  )}
                  {!hasChildren && (
                    <div dangerouslySetInnerHTML={{ __html: item.body }} />
                  )}
                </Panel>
              );
            }

            if (recurse) {
              return (
                <Panel header={item.title} eventKey={index}>
                  {hasChildren && (
                    <div>
                      <RecursiveAccordion items={children} recurse={true} />
                      <div dangerouslySetInnerHTML={{ __html: item.body }} />
                    </div>
                  )}
                  {!hasChildren && (
                    <div dangerouslySetInnerHTML={{ __html: item.body }} />
                  )}
                </Panel>
              );
            }
          })}
        </Accordion>
      );
    };

    return <RecursiveAccordion items={baseItems} recurse={false} />;
  }
});

ReactDOM.render(<App />, document.getElementById("app"));
person Andrew    schedule 01.04.2021