问题
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">×</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">×</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}}">×</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