0

I struggled with a way to properly describe the issue in the Title, so my apologies for any confusion up front. Basically, I am looping through a user's item, in this case, their "goals". On the page, when a user loads it, they should see each Goal, its description and then an Options button.

When a user has multiple Goals, the Options button is rendered for each goal, but clicking on any Option button on the page only displays the dropdown from the first item.

How can I make each button trigger its own individual dropdown? Below is the code for the loop and dropdown:

<% @goals.each do |goal| %>
      <% if goal.user_id == current_user.id %>
        <div class="goal"> 
          <p>Title: <%= goal.name %></p> 
          <p>Description: <%= goal.description %></p>
          <p>Due Date: <%= goal.due_date %></p>
          <p>Status: <%= goal.status %></p>
          <div class="dropdown">
              <button onclick="myFunction()" class="dropbtn">Options</button>
                <div id="myDropdown" class="dropdown-content">
                  <%= link_to 'Edit', edit_goal_path(goal) %>
                  <%= link_to 'Destroy', goal, method: :delete, data: { confirm: 'Are you sure?' } %>
                    <script>
              /* When the user clicks on the button, 
              toggle between hiding and showing the dropdown content */
                    function myFunction() {
                        document.getElementById("myDropdown").classList.toggle("show");
                    }

                    // Close the dropdown if the user clicks outside of it
                    window.onclick = function(event) {
                      if (!event.target.matches('.dropbtn')) {

                        var dropdowns = document.getElementsByClassName("dropdown-content");
                        var i;
                        for (i = 0; i < dropdowns.length; i++) {
                          var openDropdown = dropdowns[i];
                          if (openDropdown.classList.contains('show')) {
                            openDropdown.classList.remove('show');
                          }
                        }
                      }
                    }
                    </script>

                </div>
            </div>
        </div>
  • 2
    You shouldn't use `id` for `loop`, use `class` instead. `document.getElementById("myDropdown")` just work with first item – Tan Duong Apr 22 '18 at 02:00
  • Possible duplicate of [What is the scope of variables in JavaScript?](https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript) – Aluan Haddad Apr 22 '18 at 05:46

1 Answers1

-1

Inside myFunction, get the element and using that, find the appropriate dropdown to trigger. For this, you can use nextElementSibling to target the dropdown:

function myFunction(el) {
    var dropdown = el.nextElementSibling;
    dropdown.classList.toggle("show");
}

One small change is needed in your onclick binding: you need to pass the element using this:

<button onclick="myFunction(this)" class="dropbtn">Options</button>
Rohan
  • 79
  • 4