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

  • 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. – Ganesh Sanap Dec 25 '19 at 12:13
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/Lee@xxx.onmicrosoft.com"
    };


  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.stack.imgur.com/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.stack.imgur.com/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>      
    );    
  }
}
|improve this answer|||||
  • 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 Dec 26 '19 at 5:46
  • Check the update. – Lee_MSFT Dec 26 '19 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 Dec 26 '19 at 9:27
  • Shared my test component. – Lee_MSFT Dec 26 '19 at 9:35
  • Thank you very much for the help. I really appreciated – Milind Dec 26 '19 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.

|improve this answer|||||
  • up vote for Button Styles :) – Milind Dec 25 '19 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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