Why can't i iterate correctly through handlebars elements?

折月煮酒 提交于 2019-12-11 06:17:25

问题


I am writing a front-end code for a website using jQuery and AJAX and Handlebars.js. I have HTML,CSS and script.js files. I am pretty new to Javascript and techniques. This is the first time i'm using Handlebars in my code.

I used JSON parsing to parse through the entire data provided in a URL. It's

something like

{"products": 
[{"id": 0, 
   "name": "Ocean Blue Shirt",
   "description": "<p>Ocean blue cotton shirt with a narrow collar and 
                      buttons down the front and long sleeves. Comfortable 
                      fit and tiled kalidoscope patterns. </p>", 
   "category": "men", 
   "image_url": "https://burst.shopifycdn.com/photos/young-man-in-bright- 
                 fashion_925x.jpg", 
   "unit_cost": 92.95, 
   "inventory": 0},  

 {"id": 1, 
  "name": "Classic Varsity Top",
  "description": "<p>Womens casual ......}
  ..
  ..
  ]}

I have created buttons and used {{name}} to create multiple buttons with iterated names. My objective is to make each button contain their respective {{description}} in a 'modal' view, when i click on them.

I have been able to achieve one the first button ( named by using {{name}} ) displaying its description starting from 'Ocean blue cott.....' when i click on it, however, i am not able to get anything if i click any other buttons( with other {{name}}s.

Kindly look at the code and help me figure out what's wrong, thanks!

script.js

    var myRequest = new XMLHttpRequest()
    myRequest.open('GET' , 'http://127.0.0.1:8010/products' )
    myRequest.onload = function() {

            var myData = JSON.parse(myRequest.responseText)

            createHTML(myData)

                // Get the modal
                var modal = document.getElementById("myModal")
                // Get the button that opens the modal
                var btn = document.getElementById("myBtn")

                // Get the <span> element that closes the modal
                var span = document.getElementsByClassName("close")[0]

                // When the user clicks on the button, open the modal

                btn.onclick = function() {
                 modal.style.display = "block"
                }

                // When the user clicks on <span> (x), close the modal
                span.onclick = function() {
                  modal.style.display = "none"
                }


    }
            myRequest.send()

            function createHTML(data) {

            var template = document.getElementById("prodTemp").innerHTML
            var compiledTemplate = Handlebars.compile(template)
            var genHTML = compiledTemplate(data)

            var prodContainer = document.getElementById("prod-container")
            prodContainer.innerHTML = genHTML

    }

index.html

   {{#each products}}

                                <tr>

                                    <td>

                                        <!-- Trigger/Open The Modal -->
                                        <button id="myBtn">{{name}}</button>


                                        <!-- The Modal -->
                                        <div class = "modal" id="myModal" >
                                          <!-- Modal content -->
                                          <div class="modal-content">
                                            <span class="close">&times;</span>
                                              <li  >Product Description: {{{description}}}</li>
                                          </div>
                                        </div>
                                    </td>
                                    <td>
                                        ${{unit_cost}}
                                    </td>
                                </tr>
                            {{/each}}

回答1:


ID of the modal is what triggers the modal. If all the modal elements have the same ID then the button won't know whom to trigger.

{{#each products}}
<tr>
    <td>

        <!-- Trigger/Open The Modal -->
        <button data-toggle="modal" data-target="#{{id}}">{{name}}</button>


        <!-- The Modal -->
        <div class="modal" id="{{id}}" role="dialog">
            <!-- Modal content -->
            <div class="modal-content">
                <span class="close">&times;</span>
                <li>Product Description: {{{description}}}</li>
            </div>
        </div>
    </td>
    <td>
        ${{unit_cost}}
    </td>
</tr>
{{/each}}



回答2:


The reason is you are using the same id for all buttons and modal elements, so when executing bind the action, document.getElementById() will only take effect on the first one.

I created this codepen base on your code for solving. Please check it. The idea is to create unique id for each of elements. And the relation between them when handling events bases on their corresponding index.

(function(window, document, $, undefined) {
  'use strict';
  
  var data,
      source,
      template;
  
  // Our data object
  data = {"products": 
[{
  "id": 0, 
   "name": "Ocean Blue Shirt",
   "description": "<p>Ocean blue cotton shirt with a narrow collar and buttons down the front and long sleeves. Comfortable fit and tiled kalidoscope patterns. </p>", 
   "category": "men", 
   "image_url": "https://burst.shopifycdn.com/photos/young-man-in-bright-fashion_925x.jpg", 
   "unit_cost": 92.95, 
   "inventory": 0
},  

 {"id": 1, 
  "name": "Classic Varsity Top",
  "description": "<p>Womens casual</p>",
  "category": "women", 
   "image_url": "https://burst.shopifycdn.com/photos/young-man-in-bright-fashion_925x.jpg", 
   "unit_cost": 80.00, 
   "inventory": 0}
 ]};
  
  // Get the template source
  source = $("#my-template").html();
	  
  // Compile the template into a Handlebars function
  template = Handlebars.compile(source);
	
  // Pass our data object to the compiled Handlebars function
  // Insert back into the page
	$('#welcome-message').html(template(data));
 //binding events for elements
  var $openEls = document.getElementsByClassName('open');
  for(var i =0 ; i< $openEls.length; i++){
    var $open = $openEls[i];
    $open.onclick = function(){
      var index = this.id.split('-')[1];
      // console.log('open index ', index)
      var modal = document.getElementById("myModal-"+index);
      modal.style.display = 'block';
    }
  } 
  
  var $closeEls = document.getElementsByClassName('close');
  for(var j =0 ; j< $closeEls.length; j++){
    var $close = $closeEls[j];
    $close.onclick = function(){
      var closeIndex = this.id.split('-')[1];
      // console.log('close index ', closeIndex)
      var modal = document.getElementById("myModal-"+closeIndex);
      modal.style.display = 'none'; 
    }
  }
})(window, document, jQuery);
<div id="welcome-message">
  <script id="my-template" type="text/x-handlebars-template">
    {{#each products}}

    <tr>

      <td>

        <!-- Trigger/Open The Modal -->
        <button id="myBtn-{{@index}}" class="open">{{name}}</button>

        <!-- The Modal -->
        <div class="modal" id="myModal-{{@index}}">
          <!-- Modal content -->
          <div class="modal-content">
            <span class="close" id="close-{{@index}}">&times;</span>
            <li>Product Description: {{{description}}}</li>
          </div>
        </div>
      </td>
      <td>
        ${{unit_cost}}
      </td>
    </tr>
    {{/each}}

  </script>
</div>

You could how it works as following image



来源:https://stackoverflow.com/questions/56413992/why-cant-i-iterate-correctly-through-handlebars-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!