4

I am working on Sitecore 10.3 with headless Next.js. I want carousel component in next js with scroll this is my NextJs component code. Is there any way with the help I can use JS in this code for scrolling.

import { TextField, RichTextField, ImageField,RichText } from "@sitecore-jss/sitecore-jss-nextjs";

type FieldsCarouselDetailsFieldsFields = {
  Title?: TextField;
  Description?: RichTextField;
  Image?: ImageField;
};

type FieldsCarouselDetailsFields = {
  id?: string;
  url?: string;
  name?: string;
  displayName?: string;
  fields?: FieldsCarouselDetailsFieldsFields;
};

type Fields = {
  CarouselDetails?: FieldsCarouselDetailsFields[];
};
const baseurl = "https://www.dockerlearning.localhost";
type CarouselDetailsProps = {
  fields?: Fields;
};

const CarouselDetails = (props: CarouselDetailsProps): JSX.Element => (
  <div id="carouselExampleIndicators" className="carousel slide" data-ride="carousel">
  <ol className="carousel-indicators">
    <li data-target="#carouselExampleIndicators" data-slide-to="0" className="active"></li>
    <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
    <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
  </ol>
  <div className="carousel-inner">
  {
  props.fields?.CarouselDetails?.map(item =>  {
     return (
      <div>
    <div className="carousel-item active">
      <img className="d-block w-100" src= {baseurl+item.fields?.Image?.value?.src} alt="First slide" style={{  height: '777px' , width: '777px' }}/>
    </div>
    <div className="carousel-caption d-none d-md-block">
    <h5>{item.fields?.Title?.value}</h5>
    <RichText field={item.fields?.Description}></RichText>
  </div>

    </div>
  )
})
}
  </div>
  <a className="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
    <span className="carousel-control-prev-icon" aria-hidden="true"></span>
    <span className="sr-only">Previous</span>
  </a>
  <a className="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
    <span className="carousel-control-next-icon" aria-hidden="true"></span>
    <span className="sr-only">Next</span>
  </a>
</div>
);

export default CarouselDetails;
1
  • Can you please add more details here Commented Sep 17 at 4:29

3 Answers 3

1

I think so you need to import Bootstrap's CSS and JavaScript. For Next.js, import Bootstrap CSS directly in the component or in your _app.js file. The JavaScript for Bootstrap can be dynamically required in a useEffect hook to ensure it's loaded on the client side.

I'm not sure it will work but you can try.

here is modified code:

import { TextField, RichTextField, ImageField, RichText } from "@sitecore-jss/sitecore-jss-nextjs";
import 'bootstrap/dist/css/bootstrap.min.css'; // Import Bootstrap CSS
import { useEffect } from 'react';

type FieldsCarouselDetailsFieldsFields = {
  Title?: TextField;
  Description?: RichTextField;
  Image?: ImageField;
};

type FieldsCarouselDetailsFields = {
  id?: string;
  url?: string;
  name?: string;
  displayName?: string;
  fields?: FieldsCarouselDetailsFieldsFields;
};

type Fields = {
  CarouselDetails?: FieldsCarouselDetailsFields[];
};

const baseurl = "https://www.dockerlearning.localhost";
type CarouselDetailsProps = {
  fields?: Fields;
};

const CarouselDetails = (props: CarouselDetailsProps): JSX.Element => {
  // Ensure Bootstrap JavaScript is loaded for carousel functionality
  useEffect(() => {
    require('bootstrap/dist/js/bootstrap.bundle.min.js');
  }, []);

  // Set the index of the active carousel item
  const activeIndex = 0;

  return (
    <div id="carouselExampleIndicators" className="carousel slide" data-bs-ride="carousel">
      <ol className="carousel-indicators">
        {props.fields?.CarouselDetails?.map((_, index) => (
          <li
            key={index}
            data-bs-target="#carouselExampleIndicators"
            data-bs-slide-to={index}
            className={index === activeIndex ? 'active' : ''}
          ></li>
        ))}
      </ol>
      <div className="carousel-inner">
        {props.fields?.CarouselDetails?.map((item, index) => (
          <div
            key={index}
            className={`carousel-item ${index === activeIndex ? 'active' : ''}`}
          >
            <img
              className="d-block w-100"
              src={`${baseurl}${item.fields?.Image?.value?.src}`}
              alt={`Slide ${index + 1}`}
              style={{ height: '777px', width: '100%' }}
            />
            <div className="carousel-caption d-none d-md-block">
              <h5>{item.fields?.Title?.value}</h5>
              <RichText field={item.fields?.Description} />
            </div>
          </div>
        ))}
      </div>
      <a
        className="carousel-control-prev"
        href="#carouselExampleIndicators"
        role="button"
        data-bs-slide="prev"
      >
        <span className="carousel-control-prev-icon" aria-hidden="true"></span>
        <span className="visually-hidden">Previous</span>
      </a>
      <a
        className="carousel-control-next"
        href="#carouselExampleIndicators"
        role="button"
        data-bs-slide="next"
      >
        <span className="carousel-control-next-icon" aria-hidden="true"></span>
        <span className="visually-hidden">Next</span>
      </a>
    </div>
  );
};

export default CarouselDetails;

You can try this modified code, let me know also if you required any modification.

Hope this helps!

2
  • Is there any other way to pass "bootstrap.bundle.min.js" in useEffect
    – Rahul
    Commented Sep 17 at 11:46
  • Yes, You can include Bootstrap’s CSS and JavaScript in the _app.js file to ensure it is available throughout your application. Commented Sep 18 at 4:53
1

You can use popular library that help to implement carousel and gives other aditional features as well.

  1. slick-slider: https://www.npmjs.com/package/slick-slider
  2. Splide: https://www.npmjs.com/package/@splidejs/splide

if you want to tried without any library you can refer this, i have added inline styles but you can change it based on your requirements.

import { TextField, RichTextField, ImageField, RichText } from '@sitecore-jss/sitecore-jss-nextjs';
import { useState } from 'react';

type FieldsCarouselDetailsFieldsFields = {
  Title?: TextField;
  Description?: RichTextField;
  Image?: ImageField;
};

type FieldsCarouselDetailsFields = {
  id?: string;
  url?: string;
  name?: string;
  displayName?: string;
  fields?: FieldsCarouselDetailsFieldsFields;
};

type Fields = {
  CarouselDetails?: FieldsCarouselDetailsFields[];
};

const baseurl = 'https://www.dockerlearning.localhost';

type CarouselDetailsProps = {
  fields?: Fields;
  slidesToMove?: number; // Optional prop to define how many slides to move
};

const CarouselDetails = (props: CarouselDetailsProps): JSX.Element => {
  const [currentIndex, setCurrentIndex] = useState(0); // Track the current slide index
  const totalSlides = props.fields?.CarouselDetails?.length || 0;

  // Optional prop to define the number of slides to move
  const slidesToMove = props.slidesToMove || 1;

  const nextSlide = () => {
    setCurrentIndex((prevIndex) => (prevIndex + slidesToMove) % totalSlides);
  };

  const prevSlide = () => {
    setCurrentIndex((prevIndex) => (prevIndex - slidesToMove + totalSlides) % totalSlides);
  };

  return (
    <div
      className="carousel-container"
      style={{ position: 'relative', width: '100%', overflow: 'hidden' }}
    >
      <div
        className="carousel-inner"
        style={{ display: 'flex', transition: 'transform 0.5s ease' }}
      >
        {props.fields?.CarouselDetails?.map((item, index) => (
          <div
            key={index}
            className={`carousel-item ${currentIndex === index ? 'active' : ''}`}
            style={{ minWidth: '100%', transition: 'transform 0.5s ease' }}
          >
            <img
              className="d-block w-100"
              src={baseurl + item.fields?.Image?.value?.src}
              alt={`Slide ${index}`}
              style={{ height: '777px', width: '100%' }}
            />
            <div className="carousel-caption d-none d-md-block">
              <h5>{item.fields?.Title?.value}</h5>
              <RichText field={item.fields?.Description} />
            </div>
          </div>
        ))}
      </div>
      <a
        className="carousel-control-prev"
        role="button"
        onClick={prevSlide}
        style={{ position: 'absolute', top: '50%', left: '10px', transform: 'translateY(-50%)' }}
      >
        Previous
        <span className="carousel-control-prev-icon" aria-hidden="true"></span>
        <span className="sr-only">Previous</span>
      </a>
      <a
        className="carousel-control-next"
        role="button"
        onClick={nextSlide}
        style={{ position: 'absolute', top: '50%', right: '10px', transform: 'translateY(-50%)' }}
      >
        <span className="carousel-control-next-icon" aria-hidden="true"></span>
        Next
        <span className="sr-only">Next</span>
      </a>
      <style jsx>{`
        .carousel-inner {
          transform: translateX(-${(currentIndex / totalSlides) * 100}%);
        }
        .carousel-item {
          flex: 0 0 100%;
          max-width: 100%;
        }
      `}</style>
    </div>
  );
};

export default CarouselDetails;
  • currentIndex is a state that keeps track of the currently visible slide.
2
  • Not working, I have tried this solution not coming proper
    – Rahul
    Commented Sep 17 at 11:17
  • Yes, because I added generic css. Can you share how you want so based on that we need to calculate scrolling part
    – Krushna
    Commented Sep 17 at 12:49
0

In Sitecore Next.js, to implement a carousel with scroll functionality, you may check this, by using a combination of React and a library like Swiper.js or react-slick. We have used them in our of our projects to create carousel like this. These libraries are popular for building carousels and support scroll interactions.

Here is the sample code.

// import Swiper core and required modules
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from 'swiper';

import { Swiper, SwiperSlide } from 'swiper/react';

// Import Swiper styles
import 'swiper/swiper.scss';
import 'swiper/components/navigation/navigation.scss';
import 'swiper/components/pagination/pagination.scss';
import 'swiper/components/scrollbar/scrollbar.scss';

// install Swiper modules
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y]);

export default () => {
  return (
    <Swiper
      spaceBetween={50}
      slidesPerView={3}
      navigation
      pagination={{ clickable: true }}
      scrollbar={{ draggable: true }}
      onSwiper={(swiper) => console.log(swiper)}
      onSlideChange={() => console.log('slide change')}
    >
      <SwiperSlide>Slide 1</SwiperSlide>
      <SwiperSlide>Slide 2</SwiperSlide>
      <SwiperSlide>Slide 3</SwiperSlide>
      <SwiperSlide>Slide 4</SwiperSlide>
      ...
    </Swiper>
  );
};

You also need to add the CSS with this component. Refer to this link for more details on implementing the same.

https://swiper6.vercel.app/react

Hope this helps.

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.