The following code generates a website which gives the user the opportunity to input a ingredient with corresponding amount (the input fields).
After the user pressed the add button the inputs of ingredient and amount are displayed in a table. Furthermore the third cell of the added row should be a remove button.
The only part of the provided code which is not working at the moment is the creation of the remove button. I am super new to web development and also to the handlebar library.
My question is how I can correctly display the button while using the handlebar library? Currently, instead of the actual button [object HTMLButtonElement] gets displayed. I am sure this is possible but I couldn't find the right way.
Code:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<script id="result" type="text/template">
<tr>
<td> {{ ingredient }} </td>
<td> {{ amount }} </td>
<td> {{ change }} </td>
</tr>
</script>
<script>
const template = Handlebars.compile(document.querySelector('#result').innerHTML);
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#add').onclick = () => {
// create the remove button (HERE IT GOES WRONG)
const btn = document.createElement("BUTTON");
btn.innerHTML = "remove element";
btn.className = "remove";
// get the inputs
const ingredient = document.querySelector('#ingredient').value;
const amount = document.querySelector('#amount').value;
const content = template({'ingredient': ingredient, 'amount': amount, 'change': btn});
document.querySelector('#tab').innerHTML += content;
};
});
</script>
</head>
<body>
<input type="text" id="ingredient">
<input type="text" id="amount">
<button id="add">Add</button>
<table id="tab">
<tr>
<th>Ingredient:</th>
<th>Amount:</th>
<th>Change:</th>
</tr>
</table>
</body>
</html>
I am grateful for any help.
You are mixing two different ways of adding content to the DOM. The first is using Handlebars to compile a HTML template String into a function that will return an interpolated HTML string when passed a data context Object. The second is using document.createElement to create DOM nodes that will be directly inserted into the DOM with DOM methods like .appendChild().
The btn variable you are creating is getting assigned to it the result of document.createElement("BUTTON"), which is an HTML Button Element Object. When you pass this to your compiled template function, Handlebars only knows to try to stringify it in order to make it a part of the rendered output. When this Object is stringified, it produces "[object HTMLButtonElement]".
You could do some unpleasant work to get the rendered HTML string of your button element and pass that to your template function, but the better thing to do would be to leave the HTMLing to the template.
This would mean removing all of your const btn code and replacing that variable in your template with the desired HTML.
Therefore:
<td> {{ change }} </td>
Becomes:
<td><button class="remove">remove element</button></td>
Of course the next tricky part becomes how to bind a click handler to these dynamically added buttons; but this is outside the scope of this question.
Related
I am doing an inventory table with html and I am attempting to overwrite a paragraph. I saw that it was possible to do
document.getElementById(“Myid”).innerHTML= variable;
And this worked on the online coding environment they demonstrated it on.
However. I’m attempting to do this for a website.
In a table that looks like
function myfunction(){
console.log(“howdy”);
const form =document.getElementById(“form1”);
const formN = form.elements[0];
let formNval = Number(formN.value);
document.getElementById(“Myid”).innerHTML= formNval;
}
<table>
<tr>
<td>
<p id=“Myid”>69</p>
</td>
<td>
<form id=“form1” onsubmit=“myfunction()” method=“post” action=“#”>
<input type=“number” min=“1”>
<button type=“submit” value=“Submit”>
</form >
</td>
</tr>
</table>
I previously tried to give my table data element an ID in order to do this but I switched it to adding a p element inside the table data element because that’s what the example showed. I run this on VSCode debugger and a go live extension but it only appears for a second then goes back to the original content. How can I make the change stay? Is there a way to place a variable inside the p element specifically made to save changes while running on a server?
My full JavaScript is just a test function that contains a console log for testing and the document. GetElementById line.
I have a loop of button elements that are outputted with a while loop from data called from a MySQL database via PHP.
A user can add a button to this list and I want to add the new button and it's associated HTML using the prepend() method on the parent element, so it appears at the top of the list.
I know how to do this in various stages using createElement and adding class names and attribute names, but wondered if there is a simpler way of doing it using a template literal of the required HTML?
I've seen plenty of examples using parentElement.innerHTML(variableName), where variableName is the template literal, but these button elements illustrated below are inside a loop, and want I to prepend the newly created button to the parent .board-list element shown in the HTML.
When a new board name is submitted, a fetch() post request happens in the background to update the database, but I need to create a new element with JavaScript so this shows instantly to the user.
At the moment the template literal newButton is added to the HTML inside quote marks as a string of text, not as HTML DOM elements.
JavaScript
// added into the template literal below
const newBoardName = document.querySelector('.input-title').value;
const newButton = `
<button class="board-list-item full-width" name="board-name" type="submit">
<span>${newBoardName}</span>
<span class="add-icon flex">+</span>
</button>
`
document.querySelector(".board-list").prepend(newButton);
HTML
<div class="board-list">
// buttons outputted from the database appear here
</div>
<form>
<input class="input-title">
<button name="new-board-name">New Board Name</button>
<form>
I think a simple solution is to use .innerHTML, here is an example:
// added into the template literal below
const newBoardName = document.querySelector('.input-title').value;
const newButton = `
<button class="board-list-item full-width" name="board-name" type="submit">
<span>${newBoardName}</span>
<span class="add-icon flex">+</span>
</button>
`
let boardList = document.querySelector(".board-list");
boardList.innerHTML = newButton + boardList.innerHTML;
<div class="board-list">
// buttons outputted from the database appear here
</div>
<form>
<input class="input-title" value="user1">
<button name="new-board-name">New Board Name</button>
<form>
This is simply to answer your question, although it is not the best solution, so I do not see it recommended.
The solution to this was using the insertAdjacentHTML method. The question/answer given in one of the comments helped me on this, but I don't think it is a duplicate question, and the question linked to has an overly complicated answer IMHO.
// added into the template literal below
const newBoardName = document.querySelector('.input-title').value
const newButton = `
<button class="board-list-item full-width" name="board-name" type="submit">
<span>${newBoardName}</span>
<span class="add-icon flex">+</span>
</button>
`
// insert using 'afterbegin' to add as the first child element
document.querySelector(".board-list").insertAdjacentHTML('afterbegin', newButton)
I am getting data from the server and iterating over it to create a table and then I am using a form to store an id to local storage using javascript. Here is code snippet
<table>
<tr><th>Product ID</th></tr>
{{range .}}
<td ><form onsubmit="save_data()" action="/" method="get"><button class="btn btn-info pid" id="pid" name="{{.puid}}" value="{{.puid}}">Update</button></form></td>
{{end}}
<table>
<script>
function save_data() {
var input = document.getElementByID("pid");
localStorage.setItem("id", input.value);
}
</script>
However every time, no matter of which table row's "update" button I click, everytime only the ID of the first table row element is getting stored.
Is there a way I can generate unique IDs and reference it in Javascript when ranging over the data.
Thanks
In the loop You have
<button class="..." id="pid" name="{{.puid}}" value="{{.puid}}">Update</button>
which means that all buttons have id attribute whith the same value pid. This is an bug as id-s must be unique in the document. And when you call
document.getElementById("pid");
the first element matching the id="pid" is returned. That explains why "only the ID of the first table row element is getting stored".
To create unique id for each row you could use something like
{{range $index, $value := .}}
...<button class="..." id="pid{{$index}}" name="{{$value.puid}}" value="{{$value.puid}}">Update</button>...
{{end}}
but then you have a problem how to know which form was submitted when your save_data() event fires. To solve this you could send the current form or row id as a parameter, something like
{{range $index, $value := .}}
<td><form onsubmit="save_data(this, {{$index}})" action="/" method="get">...</form></td>
{{end}}
function save_data(form, rowno) {
var input = document.getElementById("pid"+rowno);
localStorage.setItem("id", input.value);
}
I need to have an "Add Features" button that will append the following text to the already existing text in a textarea:
<b>Features:</b>
<ul>
<li>Feature 1 here</li>
<li>Feature 2 here</li>
</ul>
It needs to appear in html form, so that the user can see the tags as well as their contents. Here is the HTML I'm using:
<tr class="addItemFormDark">
<td class="descriptionLabel">
<p>Description:</p>
</td>
<td>
<textarea name="description" id="addItemDescription" cols="77" rows="6"></textarea>
</td>
</tr>
<tr class="addItemFormDark">
<td colspan="2">
<input type="button" onclick="addFeatures('addItemDescription')" value="Add Features"/>
</td>
</tr>
...and here is the JavaScript I'm using:
function addFeatures(id) {
var contents = document.getElementById(id).innerHTML;
contents += "<b>Features:</b>\r<ul>\r\t<li>Feature 1 here</li>\r\t<li>Feature 2 here</li>\r</ul>";
document.getElementById(id).innerHTML = contents;
}
Now here is that part I'm having trouble with. If the textarea is empty, as it is to begin with, the desired text will be added to the textarea fine, and this can be repeated multiple times with each block of text being successfully added after the last.
However, if the user types anything in the box, whether into the empty text area, or after the successful addition of one of the desired blocks of code, this completely disables the button. It will then no longer add anything to the textarea until the page is refreshed.
I got exactly the same result if I used JQuery's .append method and gave the textarea and button an id.
Can anyone help?
innerHTML is not the correct property to use for setting a textarea's value. Use value instead.
function addFeatures(id) {
var textarea = document.getElementById(id);
textarea.value += "<b>Features:</b>\r<ul>\r\t<li>Feature 1 here</li>\r\t<li>Feature 2 here</li>\r</ul>";
}
With jquery I would use this:
var appendData = //the HTML text you want to add
var currentData = $("#textboxID").val();
var newData = currentData+appendData;
$("#textboxIS").val(newData);
I'm trying to get a variable in JS code to be displayed within a DIV within a table. I've cut the code down for simplicity just trying to get this working properly.
Firebug is reporting:
document.getElementById("valuelabel") is null
Here is the code:
<table>
<tbody>
<tr>
<td>
Value:
</td>
<td>
<div id="valuelabel"></div>
</td>
</tr>
</tbody>
</table>
<script language="javascript" type="text/javascript">
var mktValue = "12000";
document.getElementById("valuelabel").value = mktValue;
</script>
The mktValue will be a dynamically assigned numeric value; a textbox entry from another form. I just put "12000" in for testing purposes.
Within Firebug, it's shows the following for the dynamically assigned value.
var mktValue = '120700';
Thanks..
Divs don't have a "value", they do however have "innerHTML"
document.getElementById("valuelabel").innerHTML = mktValue;
div elements don't have a value (only form fields do). You can set the div's content via textContent (just text) or via innerHTML (HTML):
document.getElementById("target1").textContent = "This is normal text, <and> aren't special here.";
document.getElementById("target2").innerHTML = "This is HTML text, so <strong>tags</strong> are rendered as elements.";
<div id="target1"></div>
<div id="target2"></div>
you can use jquery to insert value into the specific id by using
$("#valuelabel").html(mktValue)