1

I have created react carousal from pnp controls, I was looking for help to style next and previous buttons and is there any way to add dots for the slides

enter image description here

My Carousal Code

public render(): React.ReactElement<IHomePageCarouselProps> {
    return (
      <div className={styles.carousel}>
              <Carousel
                buttonsLocation={CarouselButtonsLocation.bottom}
                buttonsDisplay={CarouselButtonsDisplay.buttonsOnly}
                isInfinite={true}
                element={this.state.carouselElements}
                    />
            </div>
    );
  }

React props and states

constructor(props: IHomePageCarouselProps) {
    super(props)

    this.state = {
      carouselElements: [
        <div key="1" >
          <div >
            <a href="#">
              <img src={banner_1} alt="banner" className={[styles['rounded-top'], styles['img-responsive']].join(' ')} />
            </a>
            <div className={[styles["ms-bgColor-white"], styles["rounded-bottom"], styles["p-10"]].join(' ')}>
              <span className={[styles["ms-fontColor-green"], styles["ms-fontWeight-bold"]].join(' ')}>
                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 key="2" >
          <div >
            <a href="#">
              <img src={banner_1} alt="banner" className={[styles['rounded-top'], styles['img-responsive']].join(' ')} />
            </a>
            <div className={[styles["ms-bgColor-white"], styles["rounded-bottom"], styles["p-10"]].join(' ')}>
              <span className={[styles["ms-fontColor-green"], styles["ms-fontWeight-bold"]].join(' ')}>
                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>
      ]
    }

My Carousal Output

enter image description here

Reason I am asking as my navigation buttons are not align and I want to add dots to know how many slides are there

1
  • I think adding dots is not possible as of now but you can add style to your next and previous button using prevButtonStyles and nextButtonStyles as given in documentation. Commented Dec 25, 2019 at 12:13

2 Answers 2

3

You could use react-slick slider.

Sample test demo in my SPFx:

enter image description here

You could customize the Previous Next as image instead of text.

Update:

The library supports custom HTML.

enter image description here

Update part2:

My test component(many test scenarios, ignore others)

import * as React from 'react';
import styles from './ReactSpFx.module.scss';
import { IReactSpFxProps } from './IReactSpFxProps';
import { escape } from '@microsoft/sp-lodash-subset';

import { SPHttpClient, SPHttpClientResponse,MSGraphClient } from '@microsoft/sp-http';

import Slider from "react-slick";
import "../../../../node_modules/slick-carousel/slick/slick.css"; 
import "../../../../node_modules/slick-carousel/slick/slick-theme.css";
import { any } from 'prop-types';

import { GraphFileBrowser } from '@microsoft/file-browser';
import { graph } from "@pnp/graph";
import { taxonomy, ITermStore, ITermSet, ITerms, ITermData, ITerm } from "@pnp/sp-taxonomy";

export interface IReactItem{ 
  ID:string,
  Title:string,
  Address:string
  Pic:{
    Description:string,
    Url:string
  }
}

export interface IReactGetItemsState{ 
  items:IReactItem[],
  selectValue:string
}

declare global {
  interface Window { _graphToken: any; }
}

const logo: any = require('../../assets/panda.jpg');
export default class ReactSpFx extends React.Component<IReactSpFxProps,IReactGetItemsState> {

  public constructor(props: IReactSpFxProps) {
    super(props);
    window._graphToken =props.userToken;
    this.state = {
      items:[],
      selectValue:"Radish"
    };
    this.next = this.next.bind(this);
    this.previous = this.previous.bind(this);    
    graph.setup({
      spfxContext: this.props.context
    });
  }

  public getAuthenticationToken():Promise<string> {    
    return new Promise(resolve => {
      resolve(
        window._graphToken
      );     
    });

  }

private getTermsetWithChildren(termStoreName: string, termsetId: string) {
  return new Promise((resolve, reject) => {
   //const taxonomy = new Session(siteCollectionURL);
   const store: any = taxonomy.termStores.getByName(termStoreName);
   store.getTermSetById(termsetId).terms.select('Name', 'Id', 'Parent').get()
   .then((data: any[]) => {
    let result = [];
    // build termset levels
    do {
     for (let index = 0; index < data.length; index++) {
      let currTerm = data[index];
      if (currTerm.Parent) {
       let parentGuid = currTerm.Parent.Id;
       insertChildInParent(result, parentGuid, currTerm, index);
       index = index - 1;
      } else {
       data.splice(index, 1);
       index = index - 1;
       result.push(currTerm);
      }
     }
    } while (data.length !== 0);
    // recursive insert term in parent and delete it from start data array with index
    function insertChildInParent(searchArray, parentGuid, currTerm, orgIndex) {
     searchArray.forEach(parentItem => {
      if (parentItem.Id == parentGuid) {
       if (parentItem.children) {
        parentItem.children.push(currTerm);
       } else {
        parentItem.children = [];
        parentItem.children.push(currTerm);
       }
       data.splice(orgIndex, 1);
      } else if (parentItem.children) {
       // recursive is recursive is recursive
       insertChildInParent(parentItem.children, parentGuid, currTerm, orgIndex);
      }
     });
    }
    resolve(result);
   }).catch(fail => {
    console.warn(fail);
    reject(fail);
   });
  });
 }

  public componentDidMount() {   

    this.getTermsetWithChildren(      
      'Taxonomy_hAIlyuIrZSNizRU+uUbanA==',
      '70719569-ae34-4f24-81b9-0629d68c05aa'
    ).then(data => {
      console.log(data);
    });

    var reactHandler = this;
    this.props.context.spHttpClient.get(`${this.props.context.pageContext.web.absoluteUrl}/_api/web/lists/getbytitle('TestList')/items?select=ID,Title,Address,Pic`,
    SPHttpClient.configurations.v1) .then((response: SPHttpClientResponse) => {  
      response.json().then((responseJSON: any) => {            
        reactHandler.setState({
          items: responseJSON.value.sort()
        });
      });  
    });  


     var userJSON={
      "@odata.id": "https://graph.microsoft.com/v1.0/users/[email protected]"
    };


  protected slider;
  next() {
    this.slider.slickNext();
  }
  previous() {
    this.slider.slickPrev();
  }

  handleChange = (event) => {
    this.setState({selectValue:event.target.value});
  };

  renderPic (item) {
    if (item.Pic === null) {
      return <img width={150} height={150}/> //use a default image better
    } else {
      return  <img width={150} height={150}  src={item.Pic.Url} />
    }
  }

  protected AddUserToGroup(){

  }
  public render(): React.ReactElement<IReactSpFxProps> {
    const settings = {
      dots: true,
      infinite: true,
      speed: 500,
      slidesToShow: 1,
      slidesToScroll: 1
    };

    this.props.context.msGraphClientFactory
      .getClient()
      .then((client: MSGraphClient): void => {
        // get information about the current user from the Microsoft Graph
        client
          .api('/me')
          .get((error, response: any, rawResponse?: any) => {
            let user=response.displayName;
        });
      });

    return (
      <div className={styles.reactSpFx}>

        <div className={styles.container}>         
        Image Load
        <img src={require('../../assets/panda.jpg')} alt="test" />        
        <div className={styles.img} title="Rencore logo">content</div>

        <button className="button" onClick={this.AddUserToGroup}>
            AddUserToGroup
          </button>

        {(this.state.items || []).map((item, index) => (
            <div key={item.ID} className={(index%2==0)?styles.rowA:styles.rowB}>{item.Title}      
            {index%2}      
            {this.renderPic(item)}           
            {/* <div dangerouslySetInnerHTML={{ __html: item.Address.replace(/[\n\r]/g,"<br/>")}}></div>  */}
          </div> 
          ))}                          
        </div>        

        <select 
        value={this.state.selectValue} 
        onChange={this.handleChange}>
          <option value="Orange">Orange</option>
            <option value="Radish">Radish</option>
            <option value="Cherry">Cherry</option>
          </select>
        <div>
          <h2> Single Item</h2>
          <Slider ref={c => (this.slider = c)} {...settings}>
            <div>
              <h3>1</h3>
              <img width="100%" height="300" src="https://i.sstatic.net/yG5lu.png"></img>
            </div>
            <div>
              <h3>2</h3>
              <img width="100%" height="300" src="https://media.wired.com/photos/5d09594a62bcb0c9752779d9/master/w_2560%2Cc_limit/Transpo_G70_TA-518126.jpg"></img>
              <div>
              The SharePoint Framework (SPFx) is a page and web part model that provides full support for client-side SharePoint development, easy integration with SharePoint data, and support for open source tooling. With the SharePoint Framework, you can use modern web technologies and tools in your preferred development environment to build productive experiences and apps that are responsive and mobile-ready from day one. The SharePoint Framework works for SharePoint Online and also for on-premises (SharePoint 2016 Feature Pack 2 and SharePoint 2019).
              </div>
            </div>
            <div>
              <h3>3</h3>
              <img width="100%" height="300" src="https://i.sstatic.net/yG5lu.png"></img>
            </div>
            <div>
              <h3>4</h3>
            </div>
            <div>
              <h3>5</h3>
            </div>
            <div>
              <h3>6</h3>
            </div>
          </Slider>
          <br/>
          <br/>
          <div style={{ textAlign: "center" }}>
          <button className="button" onClick={this.previous}>
            Previous
          </button>
          <button className="button" onClick={this.next}>
            Next
          </button>
        </div>
        </div>
      </div>      
    );    
  }
}
5
  • Thank you for the reply. But it uses jQuery and it can only accommodate images I am looking for something which can accommodate image and text beneath it
    – Milind
    Commented Dec 26, 2019 at 5:46
  • Check the update.
    – Lee
    Commented Dec 26, 2019 at 6:06
  • wow this is what I am looking, Kindly if you don't mind can you give me github repo for it
    – Milind
    Commented Dec 26, 2019 at 9:27
  • Shared my test component.
    – Lee
    Commented Dec 26, 2019 at 9:35
  • Thank you very much for the help. I really appreciated
    – Milind
    Commented Dec 26, 2019 at 9:41
2

As per my understanding adding dots is not possible as of now (correct me if I am wrong).

However, you can add style to your previous and next button using prevButtonStyles and nextButtonStyles as given in documentation.

Or as a work around you can use React Carousel control: Carousels.

1
  • up vote for Button Styles :)
    – Milind
    Commented Dec 25, 2019 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.