can't call function on element after creating it with javascript [duplicate] - javascript

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 5 years ago.
I 'm using coreUi static template.
So I'm manipulating a form.
I'm stuck at this form row that should contain websites, originally it contains 1row: input text, input URl, and a closeIcon.
There's also a add web button, so when I click it, another row in created. I successfullty implemented this feature with JS.
Now, when I press the closeIcon, I want the corresponding row to be deleted.
The problem is when I click the original's row close Button, the method is called, but when I press the other rows' close Buttons, that have been created with js, the function is not being called.
$(document).ready(function(){
$("#add_web_links").click(function(){
add_web_links();
});
$('.close').click(function(){
close_row();
});
});
function add_web_links()
{
var text="<div class='form-group row web'><label class='col-1 col-form-label'>Text</label><div class='col-2'><input class='form-control' type='text'></div> <label class='col-1 col-form-label'>URL</label> <div class='col-4'><input class='form-control' type='url'> </div> <div class='col-1'> <button type='button' class='close' aria-label='Close'> <span aria-hidden='true'>×</span></button></div></div>";
$('.web').last().after(text);
}
function close_row()
{
alert("closed");
}
<h6><B>Web Links</B></h6>
<div class="form-group row">
<label class="col-1 col-form-label">Text</label>
<div class="col-2">
<input class="form-control" type="text">
</div>
<label class="col-1 col-form-label">URL</label>
<div class="col-4">
<input class="form-control" type="url">
</div>
<div class="col-1">
<button type="button" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="col-6">
<button id="add_web_links" type="button" class="btn btn-link px-0">add web links</button>
</div>
</div>
Then I inspect the created close icons, they all have the class="close".

The event handler you've got doesn't trigger because the elements you're adding using script didn't exist when the handler was set up.
Use $(document).on("click", ".close", function() { //... . This will add the listener to the whole page instead, but then delegate handling of the event down to elements matching ".close", which do not have to exist when the handler is declared. For more information go to https://api.jquery.com/on/ - read the section "Direct and delegated events".

when you have element created after DOM rendered, I mean created dynamically you have to take approach of jquery event delegation concept.
$(document).on('click','<selector>',function(){
//Your code will go here.
......
});

The $('.close').click(...) adds handler to existing close button. But the handler doesn't listen another elements that will be created in future. Use event bubbling instead. Add this handler to parent container using on() method with selector to specify elements that trigger the event:
$('#myform').on('click', '. close', function() {
close_row();
});

you should deligate action when dynamically create new div and hide parent.prev elements + clicked button:
<script>
$(document).ready(function(){
$("#add_web_links").click(function(){
add_web_links();
});
$('.col-1').delegate("button","click",function(){
$( this ).parent().prevUntil().hide();
$(this).hide();
});
});
function add_web_links()
{
var text="<div class='form-group row web'><label class='col-1 col-form-label'>Text</label><div class='col-2'><input class='form-control' type='text'></div> <label class='col-1 col-form-label'>URL</label> <div class='col-4'><input class='form-control' type='url'> </div> <div class='col-1'> <button type='button' class='close' aria-label='Close'> <span aria-hidden='true'>×</span></button></div></div>";
$('.web').last().after(text);
$('.col-1').delegate("button","click",function(){
$( this ).parent().prevUntil().hide();
$(this).hide();
});
}
</script>
<div class="form-group row">
<label class="col-1 col-form-label">Text</label>
<div class="col-2">
<input class="form-control" type="text">
</div>
<label class="col-1 col-form-label">URL</label>
<div class="col-4">
<input class="form-control" type="url">
</div>
<div class="col-1">
<button type="button" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="col-6">
<button id="add_web_links" type="button" class="btn btn-link px-0">add web links</button>
</div>
</div>
<div class="web"></div>

Related

How to use HTML template tag with jQuery?

Something strange bug is going on in my code. I want to use HTML template tag with jQuery, because all the rest of my code is jQuery, but I only found JavaScript examples with it. I tried to "translate" from JavaScript to jQuery, this is what I came up with.
$.getJSON( "../Controller/ControllerBookstore.php?show_books=true", function( data ) {
$.each( data, function( index, value ) {
// let clone = document.getElementById('table-template').content.cloneNode(true);
// clone.querySelector('#id').innerText = value.id;
// clone.querySelector('#author').innerText = value.author;
// clone.querySelector('#title').innerText = value.title;
// clone.querySelector('#isbn').innerText = value.isbn;
let clone = $("#table-template").clone(true);
$("#id",clone).text(value.id);
$("#author",clone).text(value.author);
$("#title",clone).text(value.title);
$("#isbn",clone).text(value.isbn);
//$(".container").append(clone);
$("#header").append(clone);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div id="myAlert" class="alert alert-success collapse">
<span id="alert-text"></span>
<a id="alert-close" class="close" href="#" aria-label="Close">×</a>
</div>
<div class="row" id="header">
<div class="col"><h5>ID</h5></div>
<div class="col"><h5>Author</h5></div>
<div class="col"><h5>Title</h5></div>
<div class="col"><h5>ISBN</h5></div>
<div class="col"><h5>Action</h5></div>
</div>
<template id="table-template">
<div class="row">
<div class="col" id="id"></div>
<div class="col" id="author"></div>
<div class="col" id="title"></div>
<div class="col" id="isbn"></div>
<div class="col buttons">
<button class='btn btn-info edit'>Edit</button>
<button class='btn btn-danger delete'>Delete</button>
</div>
</div>
</template>
<div class="row justify-content-center" >
<form action="" class="col-4">
<input id = "id-box" type="hidden" name="id">
<div class="form-group row">
<label class="col-4">Author</label>
<input id = "author-box" type="text" class="form-control col-8" name="author" placeholder="Enter the author of the book">
</div>
<div class="form-group row">
<label class="col-4">Title</label>
<input id = "title-box" type="text" class="form-control col-8" name="title" placeholder="Enter the title of the book">
</div>
<div class="form-group row">
<label class="col-4">ISBN</label>
<input id = "isbn-box" type="text" class="form-control col-8" name="isbn" placeholder="Enter the ISBN of the book">
</div>
<div class="form-group row">
<button id = "submit" type="submit" name="save" class="btn btn-primary col-12">Save</button>
</div>
</form>
</div>
</div>
For some reason the JavaScript code I commented out works, but it only appends "clone" to my ".container" correctly, on the next line below the form. However I want to attach it to my ".header", but it attaches next to the header, not below it. The jQuery code doesn't do anything, it doesn't attach my "clone" anywhere.
I hope I was clear. Could you please help me to find the reason of the bugs?
A few changes are needed:
The id value of the template has a hyphen which must be escaped in the selector. Two backslashes are needed in the string literal; the first is needed to actually get a backslash in the string. The remaining one will be interpreted by the selector.
Clone the row element within the template, not the template itself. However, jQuery will not know of a DOM within the template tag, so you could just take the HTML content instead of cloning, and then turn that into a jQuery object again (which produces the DOM for it).
Insert the clone just before the template
Code:
let clone = $($("#table\\-template").html()); // <--------
$("#id",clone).text(value.id);
$("#author",clone).text(value.author);
$("#title",clone).text(value.title);
$("#isbn",clone).text(value.isbn);
$("#table-template").before(clone); // <------
As others have commented, id attributes should have unique values, so your template content cannot have id properties (since it gets cloned). Use class attributes instead.
jQuery bug
Hello my friend. You are cloning the incorrect element, because your create a clone of template with the id #table-template. Please, make this change to your code:
...
let clone = $("#table-template").html();
...
The other thing, the cloned code appears next to #header and not below it because you are using a .row class. I propose to create a div below the #header, with the id="body" and append the new content inside:
...
// $("#header").append(clone);
-> $("#body").append(clone);
...
Thanks for the example.
But I don't change the id of the "collapse" div.
The rest of the objects are cloned normally.
<template id="facilities_template">
<div class="collapse">
<div class="form-check icon-check">
<input class="form-check-input" type="checkbox">
<label class="form-check-label font-14" id="facilities_name" ></label>
<i class="icon-check-1 far fa-square color-gray-dark font-20"></i>
<i class="icon-check-2 fa fa-check-square font-20 color-green-dark"></i>
</div>
<div class="mb-3"></div>
</div>
</template>
JavaScript:
let cloneFacility = $($('#facilities_template').html());
$('#facilities_name', cloneFacility).text(value.name);
$('#facilities_name', cloneFacility).attr('data-facility-id', value.id);
$('#collapse', cloneFacility).attr('id','collapse'+ value.id)
$('#facilities_template').before(cloneFacility);
$('#faсility_filter').append(cloneFacility);

Show error message on Submit button if Radio Button is not clicked

I need to show an error message if No Radio Button is selected in the Model Form. I am getting Values into the radio form and now want to show a message that "Please select a Resume first" if no Resume is selected.
Following is the code for Model form in which I am showing the Radio Button:
<div class="modal fade" tabindex="-1" id="ResumeModal" role="dialog" ng-controller="topCtrl">
<div class="modal-dialog modal-sm">
<div class="modal-content ">
#using (Html.BeginForm("ApplyJob", "PostedJob", FormMethod.Post))
{
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
x
</button>
<h4 class="modal-title">Choose Your Resume</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<input type="hidden" name="PostedJobId" id="PostedJobById" value="#Model.PostedJobId" />
<input type="hidden" name="CreatedBy" id="CreatedBy" value="#Model.CreatedBy" />
#foreach (var item in NurseOneStop.WebSite.Models.ApplicationSession.CurrentUser.NurseResumeList)
{
<div class="col-md-12 lstCard">
<input type="hidden" name="CheckedResumeId" id="CheckedResumeId" />
<input type="radio" name="RBCheckedResume" style="height: 15px; width: 18px;" onchange="CheckedResume(#item.ResumeId)" /> <span>#item.ResumeName</span>
</div>
}
</div>
<span style="color:Red">{{msg}}</span>
#*<label id="lblMessage" style="color:red"></label>*#
</div>
</div>
<div class="modal-footer">
<span style="color:Red">{{msg}}</span>
<button id="btnSubmitResume" type="submit" class="btn btn-primary pull-right" ng-click="userAlertResumeSubmit()">
Submit
</button>
</div>
}
</div>
</div>
</div>
Below is the code for JavaScript:
<script type="text/javascript">
$(document).ready(function () {
$("#btnShowModal").click(function (){
$("#ResumeModal").modal('show');
});
});
function CheckedResume(id) {
$('#CheckedResumeId').val(id);
console.log($('#CheckedResumeId').val());
};
</script>
This is how I did it on a website recently. Please note, you should swap out the 'UIKit.notification' for something else if you are not using UIKit already on the website.
$('.btnSubmitResume').submit(function(e){
if ($("input[name=RBCheckedResume]:checked").length === 0) {
e.preventDefault();
UIkit.notification({
message: 'Please check at least one box to continue',
status: 'primary',
pos: 'top-right',
timeout: 5000
});
}
});
Also please note, you should not be using an ID within a for loop like id="CheckedResumeId". This will create multiple ID's of the same type and cause issues for you. I'd advise changing this to a class
ID attribute for an HTML element should be unique. In the code snippet which you've shared, duplicate hidden form elements with ID 'CheckedResumeId' will be created which will pollute the HTML DOM. You can take the element outside of foreach and check the code. Like Below
<input type="hidden" name="CheckedResumeId" id="CheckedResumeId" />
#foreach (var item in NurseOneStop.WebSite.Models.ApplicationSession.CurrentUser.NurseResumeList)
{
<div class="col-md-12 lstCard">
<input type="radio" name="RBCheckedResume" style="height: 15px; width: 18px;" onchange="CheckedResume(#item.ResumeId)" />
<span>#item.ResumeName</span>
</div>
}
Here goes the JS to check if radio button is clicked when executing the onsubmit function.
if($('#CheckedResumeId').val().trim() == "") {
//Give an error message to user saying that the radio button is not clicked.
}

jquery link not working after removeClass('disabled')

I have a script that disables links with a class "disabled"
//disabled links
$(document).ready(function() {
$(".disabled a").click(function() {
return false;
});
});
Additionally, I have a script that when the ".edit" button is clicked toggles the disabled state of the inputs in it's own form. It also does a removeClass('disabled') on any matching links in the form.
//toggle form edit
$("#edit").click(function(e) {
e.preventDefault();
$(this).closest("form").find("input").prop('disabled',false);
$(this).closest("form").find(".input-group-addon").removeClass('disabled');
$("#save").prop('disabled',false);
$("#edit").prop('disabled',true);
$(".alert").hide(400, "swing");
});
Then there is a script for adding and deleting input fields
//add input fields
$(".form-group").on('click', 'a.addInput', function() {
var original = $(this).closest(".input-group");
original.clone().insertAfter(original);
});
//remove input fields
$(".form-group").on('click', 'a.deleteInput', function() {
var original = $(this).closest(".input-group");
if($(this).closest(".form-group").children(".input-group").length > 1) {
original.remove();
}
});
HTML:
<form class="edit">
<div class="panel">
<div class="panel-heading">
<span><i class="fa fa-user" aria-hidden="true"></i> Basic Information</span>
<span class="pull-right"><input id="save" class="btn btn-success" type="submit" value="Save" disabled></span>
<span class="pull-right"><button id="edit" class="btn btn-default">Edit</button></span>
</div>
<div class="panel-body">
<div class="form-group">
<label for="email">Email</label>
<div class="input-group">
<input type="email" class="form-control" placeholder="Email" name="email" value="engelo#dingosoft.us" disabled required>
<div class="input-group-addon disabled"><span class="fa fa-plus"></span></div>
<div class="input-group-addon disabled"><span class="fa fa-minus"></span></div>
</div>
</div>
<div class="form-group">
<label for="phone">Phone</label>
<div class="input-group">
<input type="tel" class="form-control" pattern="\d{3}[\-]\d{3}[\-]\d{4}" placeholder="Format: 555-555-5555" name="phone" value="419-555-1212" disabled required>
<div class="input-group-addon disabled"><span class="fa fa-plus"></span></div>
<div class="input-group-addon disabled"><span class="fa fa-minus"></span></div>
</div>
</div>
</div>
</div>
</form>
The problem I am having is that when the class "disabled" is removed from the links, the links ('a.addInput') & ('a.deleteInput') do not function. What am I missing here?
Click handlers are attached to elements, not to selectors. So when you do this:
$(".disabled a").click(function() {
return false;
});
You are assigning that behavior to all elements which match at that moment (in this case, when the document loads). No matter what changes you make to the DOM after the fact, any elements which were matched when you invoked the above code will still have the above click handler.
One approach here could be to assign the click handler to a common unchanging parent, instead of to the elements themselves. By using .on() in this way, you can evaluate the selector dynamically when the click event happens instead of just once when the page loads. Something like this:
$(document).on("click", ".disabled a", function() {
return false;
});
Then the second selector (".disabled a") will be evaluated with each click. So if the DOM has changed such that an element no longer matches that selector, this click handler won't be used.
You need to add prevent the event.
$(".form-group").on('click', 'a.addInput', function(e) {
e.preventDefault();
var original = $(this).closest(".input-group");
original.clone().insertAfter(original);
});
//remove input fields
$(".form-group").on('click', 'a.deleteInput', function(e) {
e.preventDefault();
var original = $(this).closest(".input-group");
if($(this).closest(".form-group").children(".input-group").length > 1) {
original.remove();
}
});
or you can add a href="javascript:void(0);" to addInput and deleteInput.
I hope it will be help to achieve your goal...

JS Dynamically added fields - delete button not working [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 6 years ago.
The problem is that then I add some input fields dynamically, the on click action which should delete the added row is not working. I know that click action has to use .on but it didn't helped. Any ideas?
Here is the .js file:
$(document).ready(function() {
$('.eventsRowsWrapper').each(function() {
var $wrapper = $('.eventsRows', this);
$(".addEventButton", $(this)).on('click', function() {
//console.log(jsFrontend.data.get('Planning.test'));
//$('.multi-event:first-child').clone(true).appendTo($wrapper).find('input').val('').attr('id', '');
$($wrapper).append('<div class="form-group multi-event controls form-inline"> <input name="date[]" maxlength="255" type="text" placeholder="Data" class="datepickerClass form-control sortable ui-sortable" size="20"> <button type="button" style="float: none" class="close deleteEventButton">×</button></div>');
$(".datepickerClass").datepicker();
$('.sortable').sortable();
});
$('.multi-event').on('click', '.deleteEventButton', function() {
if ($('.multi-event', $wrapper).length > 1){
$(this).parent('.multi-event').remove();
}
});
});
});
And .html:
<div class="eventsRowsWrapper">
<div class="eventsRows sortable">
<div class="form-group multi-event controls form-inline">
<input name="date[]" maxlength="255" type="text" placeholder="Data" class="datepickerClass form-control sortable ui-sortable" size="20">
<button type="button" style="float: none" class="close deleteEventButton">×</button>
</div>
</div>
<button class="btn btn-warning btn-sharp addEventButton" type="button" name="addEvent">
<span class="glyphicon glyphicon-plus-sign"></span>Add event
</button>
</div>
Here is the Fiddle.
instead of:
$('.multi-event').on('click', '.deleteEventButton', function() {
write:
$(document).on('click', '.multi-event .deleteEventButton', function() {
You are trying to attach an handler on something that does not exist in the dom yet.

Show new field after button click

I want to make a field that only shows up after a button click.
Heres my code so far:
<div class="control-group" style="display:none" id="passwordfield">
<label class="control-label">Password:</label>
<div class="controls"><input id="pw" type="password"></div>
</div>
The "display:none" makes it invisible, after that I have my button and a javascript which should change the display to "block", thus making it visible again.
<div style="padding-left: 160px;padding-bottom:20px">
<button class="btn btn-primary" onclick="showPWField()">Log-In</button>
<script>
function showPWField() {
document.getElementByID("passwordfield").style.display = "block";
}
</script>
</div>
But it just doesnt work. The function gets called I tested that with an alert, but I just can't change the style :/
Thanks for help in advance
the error is that getElementByID does not exist, you should use getElementById:
function showPWField() {
document.getElementById("passwordfield").style.display = "block";
}
<div class="control-group" style="display:none" id="passwordfield">
<label class="control-label">Password:</label>
<div class="controls"><input id="pw" type="password"></div>
</div>
<div style="padding-left: 160px;padding-bottom:20px">
<button class="btn btn-primary" onclick="showPWField()">Log-In</button>
<script>
function showPWField() {
document.getElementById("passwordfield").style.display = "block";
}
</script>
</div>
Javascript is a case sensitive,the method you used is getElementByID() won't work in javascript, better to use getElementById()
function showPWField() {
document.getElementById("passwordfield").style.display = "block";
}enter code here

Categories