How to pass yml data from Ruby loop to plain JavaScript modal (not Bootstrap)

I want a grid of projects represented by cards. Clicking each card you get a modal with details for the project (title, banner image, description etc). I am using Middleman static site generator.

I created a projects.yml file in a data folder:

"Project 1":
 project_id: 1
 card:
     selector: HTML5-CSS3-JavaScript
     image: project1-card.jpg
     text: Middleman · HTML5 & CSS3 · Ruby
 modal:
     title: A personal website.
     img_banner: project1-modal.jpg
     description:
         title_left: What is it?
         text_left:  A portfolio built with Middleman
         title_right: Categories
         text_right: HTML CSS Ruby Javascript
         title_middle: whatever
     body:
         title_1: My personal website with Middleman
         text_1: Lorem ipsum dolor sit amet....
     etc.....

"Project 2":
 project_id: 2
 card:
    selector: RubyOnRails
    image: project2-card.jpg
    text: Rails · HTML5 & CSS3 · Ruby
 modal: 
    title: A yelp clone
    img_banner: project2-modal.jpg
    description:
        title_left: What is it?
        text_left:  A yelp clone
        title_right: Categories
        text_right: HTML CSS Ruby Rails
        title_middle: whatever
    body:
        title_1: A yelp clone built with Rails
        text_1: Lorem ipsum dolor sit amet....
    etc.....
etc....

In projects.html.erb my Ruby iteration is like this:

<div class="shuffle-grid">
<% data.projects.each do |project, details| %>
<div class="item trigger" data-category="<%= details.card.selector %>" data-modal-title="<%= details.modal.title %>" data-modal-img-banner="<%= details.modal.img_banner %>" data-modal-description-title-left="<%= details.modal.description.title_left %>" data-modal-description-text-left="<%= details.modal.description.text_left %>" data-modal-description-title-right="<%= details.modal.description.title_right %>" data-modal-description-text-right="<%= details.modal.description.text_right %>" >
  <div class="padded-card">
    <div class="img-container"><%= image_tag <%= details.card.image %> %></div>
      <div class="text-padd">
        <div><h3><%= project %></h3></div>
        <div><h4><%= details.card.text %></h4></div>
      </div>
   </div>
 </div >
<% end %>
</div>

And right after comes the modal:

<div class="modal-overlay closed" id="modal-overlay"></div>
<div class="modal closed" id="modal">
    <button class="close-button" id="close-button">Close</button>
    <div class="modal-inner">
        <div id='title-id'></div>
        <div id='image-id'></div>
        <div id='description-title_left-id'></div>
        <div id='description-text_left-id'></div>
        <div id='description-title_right-id'></div>
        <div id='description-text_right-id'></div>
    etc...
 </div>
</div>

Obviously I know the solution I found is clunky passing all the parameters one by one in data-attributes and retrieving them in my javascript:

 window.onload = function () {
    'use strict';
     var modal = document.querySelector("#modal");
     var modalOverlay = document.querySelector("#modal-overlay");
     var closeButton = document.querySelector("#close-button");

    $('.trigger').on('click', function() {
        $('#title-id').html($(this).data('modal-title'));
        var modal_img_banner = $(this).attr('data-modal-img-banner');
        var img_to_insert = "<img src=/images/" + modal_img_banner + ">";
        $('#image-id').html(img_to_insert);
        $('#description-title_left-id').html($(this).data('modal-description-title-left'));
        etc...
        modal.classList.toggle("closed");
        modalOverlay.classList.toggle("closed");
   });

    closeButton.addEventListener("click", function() {
        modal.classList.toggle("closed");
        modalOverlay.classList.toggle("closed");
    });
};

What is the best solution in this situation? Is there a way to pass only the id of each project to the modal and then have this id populate each data directly into the view?

If I had used Bootstrap modal instead this is what I could have done using data-target:

<div class="shuffle-grid">
<% data.projects.each do |project, details| %>
  <div class="item project_id-<%= project_id %>" data-category="<%= details.card.selector %>" data-toggle="modal" data-target="#modal-project-<%= project_id %>">
    <div class="padded-card">
      <div class="img-container"><%= image_tag <%= details.card.image %> %></div>
        <div class="text-padd">
          <div><h3><%= project %></h3></div>
          <div><h4><%= details.card.text %></h4></div>
        </div>
      </div>
    </div >
  <% end %>
</div>

And in the modal:

<div class="modal fade" id="modal-project-<%= project_id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times </span></button>
<div class="modal-dialog" role="document">
    <div class="modal-content">
        <div class="modal-container">
            <div class="modal-banner">
                <h2 class="modal-title" id="myModalLabel"><%= details.modal.title %></h2>
                <%= image_tag details.modal.img_banner %>
            </div>
            <div class="modal-description">
                <div class="left-col flex1">
                    <div><h4><%= details.modal.description.title_left_1%></h4>
            etc....
            </div>
        </div>
    </div>
</div>
Basically I'd like to do the same as with Bootstrap but with a vanilla JavaScript modal.

Thank you all !

From what I understand, you can’t pass anything from the data files into JS.

What I ended up doing is something like this to achieve a similar result:

<% data.plans.each do |p| %>`
  <div class="col-6 col-sm-4 plan-card" data-plan=<%= p.code%> data-price=<%= p.price%> data-name=<%= p.name%> data-type=<%= p.type %> >
    <div class="plan-heading">
      <h2 class="plan-name"><%= p.name %></h2>
      <span class="plan-price">$<%=p.price %><span class="plan-frequency"> / <%=p.frequency %></span></span>
      <span class="plan-benefit"><%=p.caption %></span>
      <span class="plan-caption font-italic"><%=p.benefit %></span>
    </div>
    <div class="plan-body">
      <button class="btn btn-bar btn-primary">SELECT</button>
    </div>
  </div>
  <% end %>

Then you can reference the data attributes in JS or jQuery to populate your modals with what you need. A little hacky, but works!

$('selector').data('attribute');

Thanks Phil. This solution looks better. Just to make sure I understand correctly:

  1. does that mean that I would still need to code my modal the same way with id + empty content ? such as
    < div class=“modal-inner”>
    < div id=‘price’>
    < div id=‘name’>
    < div id=‘type’>
    etc…
    < /div>
    and in JS something like using thisdata = $(’#price’).data(‘price’). How do you actually populate the modal which is not available inside the loop but ouside the iteration. It may be why I can’t pass from the data into the modal.

  2. can’t an id for each plan be used and passed in the attributes somehow to retrieve the “instance” and populate the modal (same way as with Bootstrap)?

So what I would do is populate each card object with the data attributes I mentioned above. Then you should end up with some objects like.

<div data-name="name1" data-price="20">
</div>
<div data-name="name2" data-price="40">
</div>
<div data-name="name3" data-price="60">
</div>

Bootstrap actually handles dynamic modal content like this - you can read more about it here: