Adding list item using jQuery and Bootstrap - javascript

I had a simple to-do list app that worked fine, recently I overhauled the app using Bootstrap, before I wasnt using any css framework. Now the jQuery is not working properly... Why is this?
Here is the relevent HTML:
<div id="to-do">
<form class="form-inline">
<input class="form-control" type="text" id ="input" placeholder ="I need to...">
<button class="btn btn-primary" id ="add" type="submit">Add Item</button>
</form>
<ul id="list"></ul>
</div>
This is my Javascript code:
$(function() {
// configuration
// button
var add = $('#add');
// list container
var listContainer = $('#list');
// click event for button
add.on('click', function() {
// value of input
inputValue = $('#input').val();
// add new list item
listContainer.prepend('<li> ' + inputValue + '</li>');
// clear value input
$('#input').val('');
});
});

Mine works fine, does is what you needed to do ?
$(function() {
// configuration
// button
var add = $('#add');
// list container
var listContainer = $('#list');
// click event for button
add.on('click', function() {
event.preventDefault(); // stop default behaviour of submit button
// value of input
inputValue = $('#input').val();
// add new list item
listContainer.prepend('<li> ' + inputValue + '</li>');
// clear value input
$('#input').val('');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<div id="to-do">
<form class="form-inline">
<input class="form-control" type="text" id ="input" placeholder ="I need to...">
<button class="btn btn-primary" id ="add" type="submit">Add Item</button>
</form>
<ul id="list"></ul>
</div>

Related

JavaScript Removing Elements Dynamically! removeChild

Technology I am using is materialize and vanilla js. I've created a materialize button that opens a model. within the model is a form that takes user input, then places the input text onto the main page, when the Submit button is triggered. then I have a button that should remove/delete the input posted. So the issue I'm having is that the JavaScript linked to the button which should delete/removeChild isn't working. please help :)
// ----------------Models Materialize Framework----------------
document.addEventListener('DOMContentLoaded', () => {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
});
//Delete From The Dom
const delExerciseBtn = document.querySelector('.del-exercise-btn');
delExerciseBtn.addEventListener('click', (e) => {
if(e.target.className == 'delete'){
const h6 = e.target.parentElement;
delExerciseBtn.removeChild(h6);
}
});
// Add User's To the Dom.
const addExerciseDom = document.querySelector('.exercise-dom');
const exerciseForm = document.querySelector('.exercises-form');
const disabledExersiceBtn = document.querySelector('.disabled-exersicebtn');
exerciseForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get Input Value
const value = exerciseForm.querySelector('input[type="text"]').value;
// Create Elements
const h6 = document.createElement('h6');
// Add Content
h6.textContent = value;
// Append To Dom
addExerciseDom.appendChild(h6);
//Disable Btn
disabledExersiceBtn.setAttribute('disabled', 'disabled');
});
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<!-- Google icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!-- Sytle.css -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<!----- user's input ------->
<div class="row">
<div class="col s12 center valign-wrapper center-align">
<div class=" exercise-dom delete"> <!--Users text input h6----> </div>
</div>
</div>
<!-- Btn/Modals/form -->
<div class="row">
<!-- Dom Btn -->
<div class="col s12 center ">
<a href="#exercise" class="btn-floating btn-small darken-4 z-depth-2 black center modal-trigger disabled-exersicebtn">
<i class="material-icons white-text">add </i>
</a>
</div>
<!-- Modal/form -->
<div class="modal modal-position" id="exercise">
<div class="modal-content">
<div class="row exercises-padding">
<form class="col s12 exercises-form" autocomplete="off">
<div class="input-field col s10">
<i class="material-icons prefix">fitness_center</i>
<input type="text" id="autocomplete-input" class="autocomplete center">
<label for="autocomplete-input" ><h6>Exercises</h6></label>
</div>
<div class="modal-footer">
<input class="modal-close btn black" type="submit" value="Submit">
</div>
</form>
</div>
</div>
</div>
<!-- Remove Users Btn -->
<div class="col s12 center remove-padding">
<a href="#" class="btn-floating btn-small darken-4 z-depth-2 black center modal-trigger del-exercise-btn">
<i class="material-icons white-text ">remove </i>
</a>
</div>
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- app.JavaScript -->
<script src="app.js"></script>
</body>
</html>
Update:
you have a nesting error in your HTML, a </div> is missing, which is why the DOM doesn't contain the form
check the DOM with developer tools by inspecting elements, and you'll see that the structure is wrong
you can also use for example Codepen's "Analyze HTML" function in the HTML pane to check your HTML
the <form>'s class is Exercises-form, and the selector .exercises-form (from const exerciseForm = document.querySelector('.exercises-form');) therefore can't find the element, as CSS class names are case-sensitive. exerciseForm then becomes null, which causes the error Uncaught TypeError: Cannot read property 'addEventListener' of null
the delete button still doesn't work. I suggest to you try for yourself. Use the browser developer tools, especially the DOM element inspector and the console for interactive tests for your selector queries (and the element you select in the element inspector is accessible as $0 in the console.). There are many tutorials a Google search away.
Additional note: I oversaw that there's already an document.addEventListener('DOMContentLoaded', () => {... at the top of the file. You can put your code there, no need for another DOMContentLoaded event listener (although it doesn't hurt either).
Original answer:
You get
Uncaught TypeError: Cannot read property 'addEventListener' of null
that means that
const delExerciseBtn = document.querySelector('.del-exercise-btn');
couldn't find the node and returned null.
Probable reason: code runs too early, browser has not yet constructed the DOM.
Solution: wrap your code in a DOMContentLoaded event handler:
window.addEventListener('DOMContentLoaded', (event) => {
const delExerciseBtn = document.querySelector('.del-exercise-btn');
// ...
});
const h6 = e.target.parentElement;
delExerciseBtn.removeChild(h6);
You are trying to remove its parent from a button. And you need to remove the button from the parent.
const h6 = e.target.parentElement;
h6.removeChild(e.target);

Reference appened HTML code via id with jquery

I have a problem concerning the use of .append("..."). I am coding a simple To-Do List and want to delete a list element when I click on the appended "REMOVE" button by reference to the buttons class.
I think it is not working because .append() isn't changing the html code of the website. At least I can't spot a difference after clicking the "ADD ITEM" button.
Do you have any ideas?
Thanks in advance!
var inputText;
var itemList = [];
$("#addButton").click(function(){
inputText = $("#textInput").val();
itemList.push(inputText);
$("#textInput").val("");
showItems();
});
//not working
$(".deleteButton").click(function(e){
console.log("test");
var className = e.attr("id");
console.log("ID:" + className);
});
function showItems(){
$("#list").html('');
for(var i=0; i<=itemList.length-1; i++){
$("#list").append('<div class="listelement"><p type="text" class="listItem" id="listItem '+ i +'">'+ itemList[i] +'</p> <button type="button" class="deleteButton" id="'+ i +'">REMOVE</button><div>');
}
}
<body>
<div class="container">
<div class="headline">
<h1 id="headline">TO DO LIST</h1>
</div>
<div class="userInput">
<input type="text" id="textInput">
<button type="button" id="addButton">ADD ITEM</button>
</div>
<div class="list" id="list">
<div class="listelement" id="listelement">
</div>
</div>
</div>
<script src="jquery-3.4.1.min.js"></script>
<script src="script.js"></script>
</body>
</html>
You need to use event delegation.
$(document).on("click",".deleteButton",function(e) {
$(this).closest(".listelement").remove()
});
$(".deleteButton").click(function(e){ will only work on those elements that exist on the page, but not on newly added elements.
var inputText;
var itemList = [];
$("#addButton").click(function() {
inputText = $("#textInput").val();
itemList.push(inputText);
$("#textInput").val("");
showItems();
});
//not working
$(document).on("click",".deleteButton",function(e) {
$(this).closest(".listelement").remove()
});
function showItems() {
$("#list").html('');
for (var i = 0; i <= itemList.length - 1; i++) {
$("#list").append('<div class="listelement"><p type="text" class="listItem" id="listItem ' + i + '">' + itemList[i] + '</p> <button type="button" class="deleteButton" id="' + i + '">REMOVE</button><div>');
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="headline">
<h1 id="headline">TO DO LIST</h1>
</div>
<div class="userInput">
<input type="text" id="textInput">
<button type="button" id="addButton">ADD ITEM</button>
</div>
<div class="list" id="list">
<div class="listelement" id="listelement">
</div>
</div>
</div>
If you just want to remove that specific div where you are clicking you can use following code. You dont need to match id here.
$(document).on("click",".deleteButton",function(e){
let parent = $(this).closest(".listelement");
parent.remove();
});
But according to your code after delete if you add something, all the data of the array will show.Because you are not deleting data from array. I think you need to delete that data from the array too.
$(document).on("click",".deleteButton",function(e){
let parent = $(this).closest(".listelement");
let id = $(this).attr("id");
console.log(id);
itemList.splice(id, 1);
parent.remove();
});
The issue here is that the element appended doesn't have an event listener attached to it, when you're calling $(...).click it will attach an event listener only to the currently existing elements. Since you're calling it when the document loads and there are no elements with the class deleteButton at that time it won't do anything.
You can solve this by moving the deletion code to it's own function and attaching a click event listener for each new element you create.
In order to do so efficiently, you'll need to get the element you're creating, you can do this like so:
$(HTML Code).appendTo('#list').click(...);
This will create an element from the html you pass it, append it to the element with the id list and attach a click event listener to it, so in the end this will the result:
var inputText;
var itemList = [];
$("#addButton").click(function() {
inputText = $("#textInput").val();
itemList.push(inputText);
$("#textInput").val("");
showItems();
});
function deleteItem(e) {
console.log(e.target.id);
}
function showItems() {
$("#list").html('');
for (var i = 0; i <= itemList.length - 1; i++) {
var html = '<div class="listelement"><p type="text" class="listItem" id="listItem ' + i + '">' + itemList[i] + '</p> <button type="button" class="deleteButton" id="' + i + '">REMOVE</button><div>';
$(html).appendTo('#list').click(deleteItem);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="headline">
<h1 id="headline">TO DO LIST</h1>
</div>
<div class="userInput">
<input type="text" id="textInput">
<button type="button" id="addButton">ADD ITEM</button>
</div>
<div class="list" id="list">
<div class="listelement" id="listelement">
</div>
</div>
</div>
If you try to do something with the elements that are dynamically added to DOM using the jQuery click() method it will not work, because it bind the click event only to the elements that exist at the time of binding
you can use
$(document).on("click", "button.deleteButton" , function() {
$(this).parent().remove();
});
https://jsfiddle.net/82d0e5at/3/

I cannot seem to push items to my to-do list

The finished product is just supposed to have a checkbox next to each entry, and the option to edit or delete each item. I'm nowhere near that as I can't even get an item to post.
Here's are the files that I have: HTML, CSS, JS.
Also, I'm sorry for the formatting.I didn't paste the CSS as that's not an issue as far as I'm concerned.
HTML:
var list = document.getElementById('list'); //The unordered list.
var entry = document.createElement("li"); //Whatever this is. I'm assuming a command saved into a variable (?).
//var todolist = list.getElementsById('li');
// var btn = document.getElementById('ToDoButton');
//
// btn.addEventListener("click", function(){
// todolist.appendChild('li');
// });
/* Upon submission of the item in the text field, the string is stored in inputValue
and theText becomes a text node of inputValue, which is appended to the end of the variable
entry. This means that there should be a new item added to the unordered list with the information
found in the text field, but it doesn't show.
Also, as far as I know, this is only if the Add button is clicked, and not upon
pressing Enter while in the text box. */
function newElement() {
var inputValue = document.getElementById("textBox").value;
var theText = document.createTextNode(inputValue);
entry.appendChild(theText);
if (inputValue !== '') {
document.getElementById(list).appendChild(entry);
}
}
<!DOCTYPE html>
<html>
<head>
<title>To-Do List</title>
<link rel="stylesheet" href="todo.css">
</head>
<body>
<div class="toDoList">
<h4>To-Do List</h4>
<form target="_self">
<!-- This is so that the submitted information doesn't go anywhere but to the current page. -->
<input type="text" name="toDoList" placeholder="To-Do" id="textBox">
<input type="submit" value="Add" onclick="newElement()" id="ToDoButton">
<!-- newElement() is a JS function that will add the information in the search bar to the unordered list below. -->
</form>
</div>
<section id="main">
Tasks:
<ul id="list">
<!-- These are dummy values for the unordered list. The idea
is that the next item should be placed beneath them. -->
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</section>
<script type="text/javascript" src="todo.js">
</script>
</body>
</html>
This is a short example of how to dynamically add elements on the page. User types in a to do item, then clicks the button. When they click the button, we get the value from the input box, create a new list item element, and then append it to the dom.
function addItem() {
var el = document.createElement('li')
var val = document.getElementById('item-val').value;
el.innerHTML = val;
document.getElementById('list').append(el);
}
<input id="item-val" type="text" />
<button onclick="addItem()">Add an item</button>
<ul id="list"></ul>
A few problems:
1) When you click the button, it submits the form. This causes your page to refresh, so any and all changes made by the JavaScript are lost, because you re-load the page from the server. Changing it to <button type="button" means it doesn't cause a postback any more. To be honest you probably don't actually need <form> here at all if you aren't going to send the data to the server.
2) Better to put your list and entry variables inside the function - globals are best avoided if you can, to reduce accidental scope issues. Also you need to create a new entry each time, not keep appending the same one.
3) document.getElementById(list).appendChild(entry) doesn't work because list is already an object representing an element - it's not a string containing an ID. so list.appendChild() is correct here - i.e. you can just call the appendChild() function on the existing object directly.
4) Optionally, you don't really need the separate textNode object - just set the innerText property of the list item instead.
5) Optionally again, but considered best practice: I declared an unobtrusive event handler (using addEventListener) rather than putting it inline inside the HTML. This is generally considered to make the code more maintainable and traceable, as all the script is held in one place, separate from the HTML.
Here's a fixed version:
document.querySelector("#ToDoButton").addEventListener("click", newElement);
/* Upon submission of the item in the text field, the string is stored in inputValue
and theText becomes a text node of inputValue, which is appended to the end of the variable
entry.*/
function newElement() {
var list = document.getElementById('list'); //The unordered list.
var entry = document.createElement("li"); //a new list item
var inputValue = document.getElementById("textBox").value;
if (inputValue !== '') {
entry.innerText = inputValue;
list.appendChild(entry);
}
}
<!DOCTYPE html>
<html>
<head>
<title>To-Do List</title>
<link rel="stylesheet" href="todo.css">
</head>
<body>
<div class="toDoList">
<h4>To-Do List</h4>
<form target="_self">
<input type="text" name="toDoList" placeholder="To-Do" id="textBox">
<button type="button" id="ToDoButton">Add</button>
</form>
</div>
<section id="main">
Tasks:
<ul id="list">
<!-- These are dummy values for the unordered list. The idea
is that the next item should be placed beneath them. -->
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</section>
<script type="text/javascript" src="todo.js">
</script>
</body>
</html>
Your main issue is that you were using and <input type="submit"> when you were expecting the behavior of <input type="button"> with a click event listener:
document.querySelector('#ToDoButton').addEventListener('click', newElement);
function newElement() {
var inputValue = document.getElementById("textBox").value;
var theText = document.createTextNode(inputValue);
var liEl = document.createElement('li');
liEl.appendChild(theText);
if (inputValue !== '') {
document.getElementById('list').appendChild(liEl);
}
}
<head>
<title>To-Do List</title>
<link rel="stylesheet" href="todo.css">
</head>
<body>
<div class="toDoList">
<h4>To-Do List</h4>
<input type="text" name="toDoList" placeholder="To-Do" id="textBox">
<!--The input type needs to be "button, not "submit"-->
<input type="button" value="Add" id="ToDoButton">
</div>
<section id="main">
Tasks:
<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</section>
<script type="text/javascript" src="todo.js">
</script>
</body>

How can I insert a Print button that prints a table

i have an asp.net mvc project. there is an index page with extension cshtml. and when i generated it shows to me on browser a page contain title, buttons, table and footer.
i want to add a button to print just the table not all the page.
i add in the layout:
<link id="ctl00_Link1" rel="stylesheet" href="themes/css/print.css" type="text/css" media="print">
and in the end of index page:
<div class="line-btn ">
<input type="submit" name="ctl00$Index" value="print" onclick="window.print();return false;" id="ctl00_MainContent_Button1" class="btn fl btn-print">
</div>
but it still doesn't work and print all the index page!
You can achieve what you want using following code. Add following in your index.cshtml page:
<div class="line-btn">
<input type="submit" value="print" onclick="PrintOnlyTable()" class="btn fl btn-print">
</div>
<script>
function PrintOnlyTable() {
var HTML = $("html");
var cln = document.documentElement.innerHTML;
HTML.html($("table"));
window.print();
document.documentElement.innerHTML = cln;
return false;
}
</script>

referencing jQuery created element, to register a click (with fiddle)

I'm working on a project which would require the user to be able to add, and edit tags.
On the page, is: a div container, containing the tags, a textbox (newTag) and a button (add tag) that will add a tag to the container. Another textbox (editTag) and a button (update tag) that will update the tag information typed in by the user. There is also a select list that will, in realtime - keep track of all the changes made.
Wen a user clicks on a tag that was already rendered, to edit it - all works well. The tag name goes into the edit textbox, and the tag is selected in the list.
The problem arises when a user created tag gets clicked... nothing happens. I have a feeling it has to do with the fact the object is in the DOM, but isn't rendered HTML. But I have no clue as to how to resolve this issue - how to reference a click of a dom object.
Here's my code:
HTML:
<!-- tags container -->
<div class="container_12">
<div class="grid_2"><img src="images/spacer.png" /></div>
<div id="content" class="grid_8">
<button name="PHP" class="tag-button">PHP</button>
<button name="CSS" class="tag-button">CSS</button>
</div>
<div class="grid_2"><img src="images/spacer.png" /></div>
</div>
<!-- tags container end -->
<!-- action buttons container -->
<div class="container_12 action-bar">
<div class="grid_4"><img src="images/spacer.png" /></div>
<div id="action-add">
<input type="text" name="newTag" id="newTag" />
<input type="button" id="add" value="Add tag" />
</div>
<div class="grid_4"><img src="images/spacer.png" /></div>
<div id="action-edit">
<input type="text" name="editTag" id="editTag" />
<input type="button" id="update" value="Update tag" />
</div>
<!-- action buttons container end -->
</div>
<!-- Real Time list container -->
<div class="container_12">
<div class="grid_4"><img src="images/spacer.png" /></div>
<select id="insertString">
<option value="0">PHP</option>
<option value="1">CSS</option>
</select>
</div>
<!-- real time list container end -->
jQuery:
//button add click
$('#add').click(function() {
//creating a new tag for the tag bar
var tag = $('#newTag').val();
var tagHTML=$('<button name= "' + tag + '" class="tag-button">'+ tag + '</button>');
var qString = "";
// adding the tag to the bar
$("#content").append(tagHTML);
//get last value in the list
var lastValue = $('#insertString option:last-child').val();
if (! lastValue) {lastValue = 0;}
else {lastValue = ++ lastValue; }
//add new option for the new tag
$('<option value="' + lastValue + '">' + tag + '</option>').appendTo("#insertString")
})
//tag button click
$(".tag-button").click(function(){
var name = $(this).attr('name');
//add the tag name to the editTag textbox
$('#editTag').val(name);
$('#insertString option:contains("'+ name + '")').attr('selected', true);
});
Also, here's my fiddle:
http://jsfiddle.net/Lm3ab/
Help would be appreciate, and thank you for your time.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
Use
$("#content").on("click", ".tag-button", function() {
DEMO
just add another click, thus
$("#content").on("click", ".tag-button", function(){});
http://jsfiddle.net/Lm3ab/1/
Event delegation, since these tags weren't on the page at the time of the click events being binded, they have no listeners. Bind the click event to the container and target the elements:
$("#content").on("click", ".tag-button", function() {

Categories