Issue
I am generating some html card and buttons from an array. I want to call a function with the data from the foreach. But I can't seem to figure it out.
I am getting the problem in the renderProducts() method.
/// <reference path="coin.ts" />
/// <reference path="product.ts" />
/// <reference path="productFactory.ts" />
enum VendingMachineSize {
small = 6,
medium = 9,
large = 1,
}
class Cell {
constructor(public product: CocoCola) {}
stock: 3;
sold: false;
}
class VendingMachine {
private totalMoney = 0;
private totalMoneyText = <HTMLSpanElement>document.getElementById("total-money");
private containerElement = <HTMLDivElement>document.querySelector(".machine");
allCoins: number[] = [0];
cells = [];
selectedCells = [new Cell(new CocoCola())];
set size(givenSize: VendingMachineSize) {
this.cells = [];
for (let index = 0; index < givenSize; index++) {
let product = ProductFactory.GetProduct();
this.cells.push(new Cell(product));
}
this.renderProducts();
}
constructor() {
console.log("I am vending machine!");
}
select(cell: Cell) {
cell.sold = false;
this.selectedCells.push(cell);
console.log(this.selectedCells);
}
acceptCoin(coin: Quarter): void {
this.totalMoney += coin.Value;
this.totalMoneyText.textContent = this.totalMoney.toString();
}
renderProducts() {
this.cells.forEach((product) => {
let html = `<div class="card " style="width: 18rem">
<img src=${product.product.category.getImageUrl()} class="" alt="..." />
<div class="card-body">
<h5 class="card-title">${product.product.name}</h5>
<p class="card-text">
${product.product.description}
</p>
<button type="button" class="btn btn-outline-dark w-100 select-btn" onclick="machine.select(${product})">💰 ${
product.product.price
}</button>
</div>
</div>`;
this.containerElement.insertAdjacentHTML("beforeend", html);
});
}
}
<button type="button" class="btn btn-outline-dark w-100 select-btn" onclick="machine.select(${product})">💰 ${product.product.price}</button>
I want this button to have an onclick listener with argument of product
When I do it like this it give me this error: Uncaught SyntaxError: Unexpected identifier (at (index):33:63)
This is where I created the instance of the class
/// <reference path="vendingMachine.ts" />
const machine = new VendingMachine();
machine.size = VendingMachineSize.medium;
Solution
You can not do it like that because you use string interpolation.
When you type
`some text ${product}`
and product
is Object in your scope, javascript will call toString
method on object and returns [Object object]
<- here is the error that you recieved: **Uncaught SyntaxError: Unexpected identifier**
When you're trying to interpolate onclick handler, you should produce valid JS code, for example:
<div onclick="machine.select(${number})"></div>,
<div onclick="machine.select('${string}')"></div>,
<div onclick="machine.select(JSON.parse('${JSON.encode(product)}'))"></div>
I recommend set listener after generating html; For example:
<button type="button" data-product="${product.product.name}" class="btn btn-outline-dark w-100 select-btn">💰 ${product.product.price}</button>
...
this.containerElement.insertAdjacentHTML("beforeend", html);
this.containerElement.querySelectorAll('button').forEach(item => {
item.addEventListener('click', () => {
this.select(item.dataset.product)
})
})
Answered By - Фарид Ахмедов
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.