0
votes

I am developing spfx web part for SharePoint Online using React and pnp controls

I am using pnp control Carousel

URL for the actual control: https://github.com/SharePoint/sp-dev-fx-controls-react/blob/master/docs/documentation/docs/controls/Carousel.md

<Carousel
  buttonsLocation={CarouselButtonsLocation.top}
  buttonsDisplay={CarouselButtonsDisplay.block}

  contentContainerStyles={styles.carouselContent}
  containerButtonsStyles={styles.carouselButtonsContainer}

  isInfinite={true}

  element={this.carouselElements}
  onMoveNextClicked={(index: number) => { console.log(`Next button clicked: ${index}`); }}
  onMovePrevClicked={(index: number) => { console.log(`Prev button clicked: ${index}`); }}
/>

In above control element={this.carouselElements}

property needs array of element distinguished based on the 'key' property

Now I have created another component which renders as below:

public render(): React.ReactElement<IHomePageCarouselProps> {
    return (
      <div className={styles.homePageCarousel}>
        {/* <div className="owl-carousel owl-theme owl-banner "> */}
        <div key="1">
          <a href="#">
            <img src="images/banner_1.jpg " alt="banner" className="rounded-top" />
          </a>
          <div className="bg-white rounded-bottom p-10">
            <span className="font-color-green font-weight-bold ">
              News title will show here. News title will show here. News title will show
              here. News title will show here. News title will show here. News title will
              show here. News title will show here. News title will show here. ...
                </span>
          </div>
        </div>
        <div key="2">
          <a href="#">
            <img src="images/banner_1.jpg " alt="banner" className="rounded-top" />
          </a>
          <div className="bg-white rounded-bottom p-10">
            <span className="font-color-green font-weight-bold ">
              News title will show here. News title will show here. News title will show
              here. News title will show here. News title will show here. News title will
              show here. News title will show here. News title will show here. ...
              </span>
          </div>
        </div>
        {/* </div> */}
      </div>
    )
  }

using above component in Carousel element property as below:

element={<HomePageCarousel />}

but HomePageCarousel cannot render without main div which is the requirement of React. Can somebody help me how can I output or extract array of elements?

2

2 Answers

1
votes

For rendering a list of elements in React you can use React.Fragment

      return(
       <React.Fragment>

        <div key="1">
          <a href="#">
            <img src="images/banner_1.jpg " alt="banner" className="rounded-top" />
          </a>
          <div className="bg-white rounded-bottom p-10">
            <span className="font-color-green font-weight-bold ">
              News title will show here. News title will show here. News title will show
              here. News title will show here. News title will show here. News title will
              show here. News title will show here. News title will show here. ...
                </span>
          </div>
        </div>
        <div key="2">
          <a href="#">
            <img src="images/banner_1.jpg " alt="banner" className="rounded-top" />
          </a>
          <div className="bg-white rounded-bottom p-10">
            <span className="font-color-green font-weight-bold ">
              News title will show here. News title will show here. News title will show
              here. News title will show here. News title will show here. News title will
              show here. News title will show here. News title will show here. ...
              </span>
          </div>
        </div>


      </React.Fragment>
)
1
votes

I was reading through the documentation for element property which states:

Fixed array of elemenets to be displayed in carousel - if triggerPageEvent is not used. In case triggerPageEvent is in use, JSX.Element has to be provided. Elements are distinguished based on the 'key' property.

And because the element is required then type what you must pass there can be JSX.Element | JSX.Element[].

So based on that, we need to create an array of JSX elements for <Carousel element={this.state.currentCarouselElement} />.

So what we need is for the element property of Carousel component is basically one array with a list of JSX elements. So I think based on that you can do just like the following:

class App extends Component {
  constructor() {
    super();

    // here we create an array with two JSX elements in an array
    this.state = {
      currentCarouselElement: [
        <div key="1">
          <a href="#">
            <img src="images/banner_1.jpg" alt="banner" className="rounded-top" />
          </a>
          <div className="bg-white rounded-bottom p-10">
            <span className="font-color-green font-weight-bold ">News article 1 text</span>
          </div>
        </div>,
        <div key="2">
          <a href="#">
            <img src="images/banner_2.jpg" alt="banner" className="rounded-top" />
          </a>
          <div className="bg-white rounded-bottom p-10">
            <span className="font-color-green font-weight-bold ">News article 2 text</span>
          </div>
        </div>
      ]
    }
  }

  // removed other properties just for the example you can add them back
  render() {
    return <Carousel element={this.state.currentCarouselElement}
    />
  } 
}

Or the other solution can be using still HomeCarouselComponent just like this:

public render(): React.ReactElement<IHomePageCarouselProps> {
    return [
      <div key="1">
        <a href="#">
          <img src="images/banner_1.jpg " alt="banner" className="rounded-top" />
        </a>
        <div className="bg-white rounded-bottom p-10">
          <span className="font-color-green font-weight-bold ">News article 1 text</span>
        </div>
      </div>,
      <div key="2">
        <a href="#">
          <img src="images/banner_2.jpg " alt="banner" className="rounded-top" />
        </a>
        <div className="bg-white rounded-bottom p-10">
          <span className="font-color-green font-weight-bold ">News article 2 text</span>
        </div>
      </div>
    ]
}

Please realize that the render function returns an array of JSX elements, semicolon separated:

[
   <div key="1"></div>,
   <div key="2"></div>
]

Additional info is that for each JSX elements you need to pass a key property just like I did for <div key="1">. I think inside of the Carousel component the render method uses map which requires key attribute for each rendered elements.

I hope this helps!