admin管理员组

文章数量:1394403

In semantic_ui-react library exists ponent Accordion. There are some examples, but I have to make nested accordion, which has structure:

-accordion:
    -sub_accordion1
    -sub_accordion2
    -sub_accordion3

I saw there is example of nested accordion with panels, but I don't want to put accordions into the panels. I tried so:

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>
    )
  }
}

It renders ponent, but I can collapse only main accordion and can't collapse it's children. How can I perform this feature?

In semantic_ui-react library exists ponent Accordion. There are some examples, but I have to make nested accordion, which has structure:

-accordion:
    -sub_accordion1
    -sub_accordion2
    -sub_accordion3

I saw there is example of nested accordion with panels, but I don't want to put accordions into the panels. I tried so:

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>
    )
  }
}

It renders ponent, but I can collapse only main accordion and can't collapse it's children. How can I perform this feature?

Share Improve this question edited Jan 10, 2018 at 20:54 Oleksandr Fediashov 4,3351 gold badge25 silver badges43 bronze badges asked Dec 21, 2017 at 14:17 Sam FisherSam Fisher 8582 gold badges16 silver badges37 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 2

Since you mentioned that you need a simple solution, it is better to use panels because they seem to automatically manipulate the activeIndex which is the main attribute that decides the expansion and collapse of the accordion. If you were to do it yourself like above you need to maintain all the hierarchy and manipulate yourself by adjusting state in the onClick handler. So, if your use case is not custom or plex you can try something like below.

Here is a working demo NESTED ACCORDION SEMANTIC UI

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 />
    )
  }
}

Also for the indentation, you need to override the default css

.indent {
  margin-left: 1em;
}

.no-padding {
  padding: 0px !important;
  margin: 0px !important;
}

The correct way to make a nested accordion:

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>
    Wele 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>
    Wele 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

Here is my version of this. Its a recursive Accordion inside Accordion inside Accordion (infinitely).

Its also on 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"));

本文标签: javascriptHow to make nested AccordionStack Overflow