Swiper slider with f7-card (for quick selection of e.g. scenes on the main ui)

hi

I’m trying to make a swiper slider for my main ui overview page where, depending on the screen size, it will show options for some quick choices.

it’s the first time I make a widget and I’ve used some different examples from the forum.
I’m stuck right now as I can’t get the slidesPerView to work, it only shows one and then you have to swipe to see the next one, I’d like it to show more.

it is meant to be used in a block and full column width on a layout page.

Is there anyone who can guide me in the right direction

thanks in advance

uid: QuicAction_Swiper
tags: []
props:
  parameters:
    - description: title
      label: title
      name: title
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jan 7, 2024, 3:30:57 PM
component: f7-card
config:
  title: =props.title
  class:
    - padding
  style:
    backdrop-filter: ='blur(' + props.backgroundBlur + 'px)'
    background-size: contain
    background-repeat: no-repeat
    background-position: 100% 100%
    background-color: "=(props.backgroundColor === undefined ? 'var(--f7-color-white)' : (props.backgroundColor.substring(0,2) === '--' ? 'var(' + props.backgroundColor + ')' : props.backgroundColor))"
    border-radius: 5px
    overflow: hidden
    -ms-user-select: none
    -moz-user-select: none
    -webkit-user-select: none
slots:
  default:
    - component: f7-swiper
      config:
        navigation: true
        class:
          - padding-top
        params:
          initalSlide: 0
          runCallbacksOnInit: true
          grabCursor: true
          observer: true
          observeSlideChildren: true
          updateOnWindowResize: true
          mousewheel: true
          keyboard: true
          watchOverflow: true
          slidesOffsetBefore: 30
          slidesOffsetAfter: 30
          breakpoints:
            "0":
              slidesPerView: 1
              spaceBetween: 0
            "240":
              slidesPerView: 2
              spaceBetween: 0
            "320":
              slidesPerView: 3
              spaceBetween: 0
            "480":
              slidesPerView: 4
              spaceBetween: 5
            "640":
              slidesPerView: auto
              spaceBetween: 5
        style:
          --swiper-navigation-size: 30px
          --swiper-navigation-color: var(--normal-txt-color)
      slots:
        default:
          - component: f7-swiper-slide
            slots:
              default:
                - component: f7-card
                  config:
                    title: test 1
                    expandable: true
                    action: analyzer
                    actionAnalyzerItems: =[props.item1]
                    class:
                      - justify-content-center
                      - align-items-center
                      - text-align-center
                    style:
                      max-width: 50%
          - component: f7-swiper-slide
            slots:
              default:
                - component: f7-card
                  config:
                    title: test 2
                    expandable: true
                    action: analyzer
                    actionAnalyzerItems: =[props.item1]
                    class:
                      - justify-content-center
                      - align-items-center
                      - text-align-center
                    style:
                      max-width: 50%
          - component: f7-swiper-slide
            slots:
              default:
                - component: f7-card
                  config:
                    title: test 3
                    expandable: true
                    action: analyzer
                    actionAnalyzerItems: =[props.item1]
                    class:
                      - justify-content-center
                      - align-items-center
                      - text-align-center
                    style:
                      max-width: 50%
          - component: f7-swiper-slide
            slots:
              default:
                - component: f7-card
                  config:
                    title: test 4
                    expandable: true
                    action: analyzer
                    actionAnalyzerItems: =[props.item1]
                    class:
                      - justify-content-center
                      - align-items-center
                      - text-align-center
                    style:
                      max-width: 50%

I have never tried to use the breakpoints option so I cannot say for sure. But, your structure looks basically correct (I might try it without the quotes around the breakpoint widths just to be on the safe side, but that shouldn’t be the issue).

Alas it is also possible that the version of swiper included in the v7 F7 libraries is too old to have this feature.

The good news is that you should be able to replicate it with widget expressions . If instead of using breakpoints you just set the main slidesPerView and spaceBetween values with an expression based on screen.viewAreaWidth then you can probably achieve the same effect.

I’m starting to have something that can be used, I got it to work with the breakpoints option, but I’m curious how you do it with an expression based on screen.viewAreaWidth, can you give an example of that?

as for my widget, i’m working on getting the f7 cards to work a bit like a label cell so i’ll probably be back for some help

Quic Action Wigdet in its current form:

uid: Swiper_Quic_Action
tags: []
props:
  parameters:
    - description: A text prop
      label: Prop 1
      name: prop1
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jan 7, 2024, 7:55:31 PM
component: f7-swiper
config:
  navigation: true
  params:
    initialSlide: 0
    runCallbacksOnInit: true
    grabCursor: true
    observeSlideChildren: true
    updateOnWindowResize: true
    spaceBetween: 1
    mousewheel: true
    keyboard: true
    watchOverflow: false
    breakpoints:
      "0":
        slidesPerView: 1
      "240":
        slidesPerView: 2
      "320":
        slidesPerView: 3
      "480":
        slidesPerView: 4
      "640":
        slidesPerView: 5
  style:
    --swiper-navigation-size: 30px
    --swiper-navigation-color: var(--normal-txt-color)
slots:
  default:
    - component: f7-swiper-slide
      slots:
        default:
          - component: f7-card
            config:
              expandable: true
              title: test 1
              style:
                max-width: 100%
                background-color: "=props.bgcolor ? props.bgcolor : ''"
                border-radius: var(--f7-card-expandable-border-radius)
                box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
                height: 120px
                margin-left: 5px
                margin-right: 5px
                noShadow: false
                padding: 0px
    - component: f7-swiper-slide
      slots:
        default:
          - component: f7-card
            config:
              expandable: true
              title: test 2
              style:
                max-width: 100%
                background-color: "=props.bgcolor ? props.bgcolor : ''"
                border-radius: var(--f7-card-expandable-border-radius)
                box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
                height: 120px
                margin-left: 5px
                margin-right: 5px
                noShadow: false
                padding: 0px
    - component: f7-swiper-slide
      slots:
        default:
          - component: f7-card
            config:
              expandable: true
              title: test 3
              style:
                max-width: 100%
                background-color: "=props.bgcolor ? props.bgcolor : ''"
                border-radius: var(--f7-card-expandable-border-radius)
                box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
                height: 120px
                margin-left: 5px
                margin-right: 5px
                noShadow: false
                padding: 0px
    - component: f7-swiper-slide
      slots:
        default:
          - component: f7-card
            config:
              expandable: true
              title: test 4
              style:
                max-width: 100%
                background-color: "=props.bgcolor ? props.bgcolor : ''"
                border-radius: var(--f7-card-expandable-border-radius)
                box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
                height: 120px
                margin-left: 5px
                margin-right: 5px
                noShadow: false
                padding: 0px
    - component: f7-swiper-slide
      slots:
        default:
          - component: f7-card
            config:
              expandable: true
              title: test 5
              style:
                max-width: 100%
                background-color: "=props.bgcolor ? props.bgcolor : ''"
                border-radius: var(--f7-card-expandable-border-radius)
                box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
                height: 120px
                margin-left: 5px
                margin-right: 5px
                noShadow: false
                padding: 0px

Instead of defining slidesPerView in each of the breakpoints, just use the main slidesPerView setting. Then typical expression might be a series of nested ternary statements and look something like this:

params:
  slidesPerView: =(screen.viewAreaWidth >= 640)?(5):((screen.viewAreaWidth >= 480)?(4):(...etc nesting as many tests as you need))

But I would probably use a slightly sneakier method to reduce that to something like this:

params:
  slidesPerView: =5 - ([640,480,360,240,0]).findIndex( s => screen.viewAreaWidth >= s )

The only downside to this is that the screen object is not reactive so the number of slides will not change if the screen is resized while the slider is visible, a refresh would be required.