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

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.

Related

Thymeleaf attribute and modal

Edited:
Just figured out that i need JS. Plase, help me with this. I have a th:attr="data-object-id=${department.id}" who store Department id, which i need to put in the modal in the <input id="ids" name="ids" type="text" class="validate">.
How will JS or JQuery looks like? I am trying to write, but all time null or undefined.
<tr th:each="department : ${departments}">
<td class="dep_id" th:text="${department.id}">1</td>
<td th:text="${department.name}"></td>
<td>
<div class="dep_edit">
<a class="settings_dep" th:href="#{'/departments/' + ${department.id} + '/'}"><i class="material-icons">settings</i></a>
<a class="edit_dep modal-trigger" href="#modal3" th:attr="data-object-id=${department.id}"><i
class="material-icons">edit</i></a>
<form method="post" th:action="#{'/departments/' + ${department.id} + '/delete'}" class="inline">
<button type="submit" value="" class="link-button delete_dep">
<i class="material-icons">delete</i>
</button>
</form>
</div>
</td>
</tr>
<div id="modal3" class="modal modal-departments">
<div class="modal-dep modal-content">
<h4>Update Department</h4>
<a href="#" class="dep-modal-close modal-close"><i
class="material-icons icon_close">close</i></a>
<p>Update Department name</p>
</div>
<div class="dep-modal">
<form id="dep-update" class="col s12" th:action="#{'/departments/update'}" method="POST">
<div class="row-modal-dep">
<div class="input-field col s6">
<input id="depName" name="name" type="text" class="validate">
<input id="ids" name="ids" type="text" class="validate">
<label for="name">Department Name</label>
<i class="edit-dep-marker material-icons prefix">mode_edit</i>
</div>
</div>
</form>
<div class="modal-footer">
<input class="modal-close waves-green green btn-dep btn" type="submit" form="dep-update">
</div>
</div>
</div>
I need to give ID value of department to MODAL, so i can update it
My Departments class is easy. Only ID and name;
The 2 tricks to achieve the same (PS - I'm not a Frontend expert):-
1.) Is to create a hidden html-element on your html page & set the value and then get the value of that element using jquery on your modal.
2.) create a function on that html-element and pass the dynamic value to it and then implement your modal hide/show code inside that function, something like this :- -
<a class="edit_dep modal-trigger" th:onclick="'javascript:showFunctionModal(\'' + ${department.id} +'\');'"><i
class="material-icons">edit</i></a>
and your function would be something like this :-
function showFunctionModal(id) {
//logic to hide & show function
}
You can listen to the show.bs.modal event and capture the department id as shown below:
$('#modal3').on('shown.bs.modal', function (e) {
var target = e.relatedTarget;
var departmentId = $(target).data('object-id');
$("#ids").val(departmentId);
});
Problem solved. Huge thanks #Sumit.
th:onclick="'javascript:showFunctionModal(\'' + ${department.id} +'\');'"> on the field which id i want to fetch and then in ready modal function set id.
function showFunctionModal(id) {
$(document).ready(function () {
$('.modal3').modal();
$("#ids").val(id);
});

Why my <script> doesn't enable/disable the specific submit-button?

I'm working with Laravel 5 and I've the following HTML pages:
HTML 1
<div class="row">
#foreach($postList as $post)
#include('Pages.Post.postInGroup', ['post'=>$post, 'commentsList'=>$commentsList])
#endforeach
</div>
HTML 2
<form id="msform" action="{{route('comments.store')}}" method="post">
{{ csrf_field() }}
<div class="row align-items-center">
<div class="col-3 col-sm-3 col-md-2 col-lg-2 col-xl-1" style="display: inline-block;">
<img src="{{url(Auth::user()->picture_path)}}" style="border-radius: 50%;" width="30" height="30" alt="User Picture">
</div>
<div class="col-9 col-sm-9 col-md-6 col-lg-6 col-xl-9" style="display: inline-block;">
<textarea class="form-control" placeholder="Post a comment" id="comment_content {{$post->id}}" name="comment_content" rows="1"></textarea>
</div>
<div class="col-1 col-sm-1 col-md-1 col-lg-1 col-xl-1" >
<input type="submit" name="comment_button {{$post->id}}" class="btn btn-primary" value="Comment" style="background-color: #228B22;"/>
<input type="hidden" value="{{$post->id}}" name="postId" id="postId">
<input type="hidden" value="{{$theGroup->id}}" name="groupId" id="groupId">
</div>
</div>
</form>
<script src="{{ url('js/jquery-3.3.1.min.js') }}"></script>
<script>
$(document).ready(function() {
$('#msform > div > div > input[name=comment_button {{$post->id}}]').prop('disabled', true);
//while user is typing disable and enable based on the value.
$('#msform > div textarea').on("input", function() {
$(this).parents('.row').find('input[name=comment_button {{$post->id}}]').prop('disabled', $(this).val() == '');
});
});
</script>
The HTML 1 code explains how the HTML 2 code is repeated based on the number of objects in $postList.
What I'm trying to do is disable the button corresponding to the textarea, as long as its textarea is empty, but I do not get the desired result, because when I fill in any textarea, all the buttons are re-abilitated, and that's not what I want. For reasons of data extrapolation, I cannot change the name of the textarea and I would like this script works only on the submit button in HTML 2.
To explain better my problem, I'll made an example:
I have cycled 3 times HTML 2 by HTML 1, so I'll have:
Textarea(id="comment_content 1") - Button (name="comment_button 1")
Textarea(id="comment_content 2") - Button (name="comment_button 2")
Textarea(id="comment_content 3") - Button (name="comment_button 3")
If I want to write in the 2nd textarea with id comment_content 2, then I will have to enable only the button adjacent to that textarea, comment_button 2. I hope my problem is clear.
You're including the same external script and same inline script multiple times, as many times as there are posts. This is inefficient, you should include the external Javascript only once per page.
You can refactor this code to address your bug by creating a listener that listens to all textareas and then uses a data attribute on the textarea to determine which button should have a state change.
Step 1: Add the post ID to the textarea in a data attribute
<textarea data-post="{{ $post->id }}"
class="form-control"
placeholder="Post a comment"
id="comment_content {{$post->id}}"
name="comment_content" rows="1"></textarea>
Step 2: Add the post ID to the button in a data attribute
<input data-post="{{ $post->id }}"
type="submit"
name="comment_button {{$post->id}}"
class="btn btn-primary"
value="Comment"
style="background-color: #228B22;"/>
Step 3: Refactor your Javascript to use the data-post value when determining what the user is interacting with, e.g:
$(document).ready(function() {
$('#msform > textarea[data-post]').on("input", function() {
var id = $(this).data('post');
$('input[data-post="' + id + '"]').prop('disabled', $(this).val() == '');
});
});
Here's an example of how it'll work, click "Run code snippet" to see it in action.
$(document).ready(function() {
$('textarea[data-post]').on("input", function() {
var id = $(this).data('post');
$('input[data-post="' + id + '"]').prop('disabled', $(this).val() == '');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<textarea data-post="1"></textarea>
<input data-post="1" type="submit" disabled="true"/>
</div>
<div>
<textarea data-post="2"></textarea>
<input data-post="2" type="submit" disabled="true"/>
</div>
<div>
<textarea data-post="3"></textarea>
<input data-post="3" type="submit" disabled="true"/>
</div>

selecting all class within this in query

well right now I am doing something like this to find all textbox values which has the same class name.
function generalBottom(anchor) {
var sends = $('input[data-name^="noValues"]').map(function(){
$(this).attr('value',$(this).val());
return $(this).val();
}).get();
}
and i call this function on a onclick of submit button like generalBottom(this)
and I have something like as per my requirement
When I click submit button of User I call a general function passing this as a parameter, but the above code gives me the text values of client as well
["perfect", "hyperjack", "julie", "annoying", "junction", "convulated"], which is undesired, I want only ["annoying", "junction", "convulated"] using my anchor params.
How to do this via my this parameter, I thought to traverse through my tags using children(), parent() but I won't be knowing how many fields user have added as its all dynamic, user can add as many values(text boxes).
I tried this
1) $(anchor).find('.rightAbsNo')
2) $(anchor).find('input[data-name^="noValues"]')
3) $(anchor).find('.rightAbsNo').map(function () {
console.log($(this).find('. showNoButton')); })
None of this worked for me.
My html is somewhat like this, code
<div id="attach0" class="leftbottomno">
<div style="overflow: hidden" class="leftbottomAbsolute" id="">
<form>
<span class="absno"><input type="text" required=""
id="absdelete" data-inputclass="leftbottomAbsoluteNo_class"
value="" class="leftbottomabsolutenotest keys" data-value=""
style="margin-bottom:4px; color: #1c1c1c;"> </span>
<a onclick="addAbsoluteValues(this);" style="margin-left: 50px">
<i class="fa fa-plus-circle color-blue-grey-lighter"></i> </a>
</form>
<a onclick="deleteAbsoluteEmpty(this);> </a><br>
<div class="rightAbsNo" id="yesValueattach">
<div class="rightAbsNoValue">
<input type="text" id="nonattach" placeholder="values"
data-name="noValues" data-inputclass="absYes_class" value="annoying"
class="showNoButton showActivity value" data-value="">
<button type="button" onclick="generalBottom(this);">
<i class="glyphicon glyphicon-ok"></i></button>
</div>
</div>
<div class="rightAbsNo" id="yesValueattach">
<div class="rightAbsNoValue" id=""> <input type="text"
data-name="noValues" data-inputclass="absYes_class" subattribute=""
value="" class="showNoButton showActivity value" data-value="">
<button type="button" onclick="generalBottom(this);">
<i class="glyphicon glyphicon-ok"></i></button>
</div>
</div>
<div class="rightAbsNo" id="yesValueattach">
<div class="rightAbsNoValue" id="">
<input type="text" data-name="noValues"
data-inputclass="absYes_class" placeholder="values" subattribute=""
value="junction" class="showNoButton showActivity value"
data-value="" >
<button type="button" style="display: none;"
onclick="generalBottom(this);">
<i class="glyphicon glyphicon-ok"></i>
</button>
</div>
</div>
</div>
</div>
First of all, you need to define a container to the groups with something like :
<div class="container">input groups</div>
<div class="container">input groups</div>
and change <button type='submit'> to <button type='button'> to prevent submitting the form.
Then change your function to this:
function generalBottom(anchor) {
var all_inputs = $(anchor).parent(".container").find("input");
var input = $(anchor).siblings('input').first();
all_inputs.each(function(){
$(this).val(input.val());
});
}
Here's Jsfiddle
first $(anchor).siblings(input) find inputs
then go through each element from first step and return their value
function generalBottom(anchor) {
var input = 'input[data-name^="noValues"]'
var values = $.map($(anchor).siblings(input), (elemnt, index)=>{
return elemnt.value
})
$('#shows').val(values.join())
}
$('button').on('click',function(){
generalBottom(this)
})
hope this helps

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

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>

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...

Categories