How to make an reactive slick-slider inside bootstrap-3-modal?

Hi, this is my first post here, so please be gentle. I am making my first Meteor web app (to be compiled to Android and iOS later), but struggle with this:

(TL;DR at the bottom)

What I want to achieve is the following:

To have a set of images presented in a slider inside a (fullscreen) modal, where the images are reactively fetched from a CollectionFS.

I have almost managed to do this in my app, however:

  1. The images are not shown when the modal opens, but will become visible if I resize the screen and/or magnify +/-.
  2. If an update to the collection happens when the modal is open, the the new image is not properly added to the slider, but instead shown beneath/on top of the slider.

In hope for anyone to help, I have carefully prepared a minimal example.
My test case is created as follows (currently on Meteor 1.4, but I had this problem since 1.2 or before):

$ meteor create slider-in-modal-test
$ cd slider-in-modal-test
$ meteor npm install

$ meteor --version
Meteor 1.4.2.3

# Get some demo pics:
$ cd /tmp/
$ wget placehold.it/400x300.png
$ wget placehold.it/401x301.png
$ wget placehold.it/402x302.png

# Add the packages for the test:
$ meteor add cfs:standard-packages
$ meteor add cfs:filesystem
$ meteor add udondan:slick

# Modal, both needed I think:
$ meteor add twbs:bootstrap
$ meteor add peppelg:bootstrap-3-modal

# Slick slider:
$ meteor add udondan:slick

Now, modify/create sources:
client/main.html

<head>
  <title>slider-in-modal-test</title>
</head>

<body>
  <h1>Welcome to Meteor!</h1>
  <!-- {{> carouselDynamic}} --> <!-- if the slider carousel is shown before the modal, it won't render correctly inside the modal -->
  <br/>
  {{> showModal}}
</body>

<Template name="showModal">
  <button type="button" id="example" class="btn btn-default" >Show modal</button>
</Template>

<template name="exampleModal">
  <div id="myModal" class="modal fade">
    <div class="modal-dialog">
      <div class="modal-content">

        <div class="modal-header">
          <h4 class="modal-title">Modal example</h4>
        </div>

        <div class="modal-body">
          <p>A modal example.</p>
	  {{> carouselDynamic}}
        </div>

        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        </div>

      </div>
    </div>
  </div>
</template>

<template name="carouselDynamic">
  <h>Slick carousel dynamic</h>
  <div id="carouselDyn">
    {{#each images}}
    {{> carouselItem}}
    {{/each}}
  </div>
</template>

<Template name="carouselItem">
  <div class="item">
    <div><img src="{{this.url}}" width="200px" /></div>
  </div>
</Template>

client/main.js

import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

import './main.html';

Meteor.subscribe('images');

Template.showModal.events({
    'click button#example'(event, instance){
	Modal.show('exampleModal')
	//$('#myModal').modal('show');
    },
});

Template.carouselDynamic.helpers({
  images: function () {
    return Images.find(); // Where Images is an FS.Collection instance
  }
});

// As per http://stackoverflow.com/questions/30140232/meteor-with-iron-router-cant-get-slick-carousel-working
Template.carouselItem.onRendered( function() {
    Meteor.subscribe('images');
    $('#carouselDyn').slick({
	dots: true,
	arrows: true
    })
});

client/main.css

/* CSS declarations go here */
#carouselDyn {
  border:   1px solid black;
  width:    200px;
  position: relative;
  top:      10px;
  left:     10px;
}

#carouselDyn div {
  width:    200px;
}

.slick-prev:before, .slick-next:before {
  color:    silver;
}

common.js (in the root folder, outside client/):

Images = new FS.Collection("images", {
  stores: [new FS.Store.FileSystem("images")]
});

server/main.js

import { Meteor } from 'meteor/meteor';

Meteor.startup(() => {
  // code to run on server at startup
    Images.allow({
	'insert': function () { return true;},
	'update': function () { return true;},
	'download': function () {return true;},
    });
});

Meteor.publish("images", function () {
  return Images.find()
});

Then put two of the example images into the MongoDB (note: full path to the images seems to be required):

$ meteor # run in separate terminal
$ meteor shell
> var f = new FS.File();
> f.attachData('/tmp/400x300.png')
> Images.insert(f)
> var f = new FS.File();
> f.attachData('/tmp/401x301.png')
> Images.insert(f)

Now, with meteor running, go to localhost:3000 and press the “show modal” button. It presents the modal as expected, with slick initiated also.

But, if you — with the modal still open — add one image:

$ meteor shell
> var f = new FS.File();
> f.attachData('/tmp/402x302.png')
> Images.insert(f)

it will not be reactively added, but rather go beneath the slider.

Since I want to replace the click button with the first image in the collection, and make it clickable to present the modal with the slider, I need to find out how to:

  1. Add images to the collection reactively, and make the slider rerender correctly.
  2. Be able to let the client subscribe to the collection, use the first image, but still correctly render slider in the modal when it is opened (see comment in main.html)
  3. Make the slider and the modal “fullscreen”, and still render correctly. The modal is okay with this css:
.modal-dialog {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.modal-content {
  height: auto;
  /* min-height: 100%; */
  border-radius: 0;
}

but how to I set the slider to full width without destroying it?

TL;DR: Want to use slider inside modal in Meteor with images from Collection, but it doesn’t work as expected.

Any help appreciated!

1 Like

Any updates on this?