dynamic button does not call javascript function? - javascript

I have a button wich im dynamically adding to my page like this.
if (adminInd =='X'){
var adminDiv = $(
'<label id=Delegatelbl>Miscellaneous label prototyping.:</label>'+
'</br></br>'+
'<div style="padding-right:152px;"> '+
'<form action="userfop.jsp" id="userForm" >'+
'<label for="tuid">TU-ID:</label>'+
'<input type="text" name="tuid" id="tuid" maxlength="9"/>'+
'<button type="button" id="RoleChanger" style="cursor:pointer" class="ab_submit" onclick="validateTuid()"> Change Role </button>'+
'</form>'+
'</div>');
adminDiv.insertBefore('#FormDiv');
}
as you can see from the button tag im trying to call a javascript function and
i just about tried everything and the function does not trigger. What im i doing wrong. I've been trouble shooting this for 2 hours now with no success.
here is the function I dont see what I'm doing wrong. Someone please point me in the right direction.
function validateTuid(){
var textTuid = document.getElementById(tuid).value
$.ajax({ type: "POST",
url: "dbfunctions.jsp",
data: {TYPE:"V", tuidval:textTuid }}).done(function( msg )
{
alert("Data Saved: " + $.trim(msg));
if (msg != null || msg != ''){userForm.submit()}
return "N";
});

You should delegate the click event, you can use on() method, try the following:
$(document).on('click', "#RoleChanger", validateTuid)

Maybe have a look at http://api.jquery.com/live/. Also, instead of hardcoding onClick in the button bind a listener to it instead.

Related

Form reloads page 2nd time with preventDefault when using custom DOM function

I have a login form, and when submitted it calls this function
login = (that) ->
header =
"X-CSRFToken": window.csrftoken
$('body').toggleDOM('.loading', true)
fermata.json("/login").post(header, that, (err, data) ->
$('body').toggleDOM('.loading', false)
if !data.success
htAlert.error 'Incorrect username and/or password.'
)
This will add a "loading spinner" while the API is being called, and then it's removed. This works fine the first time you submit the form, because I'm using preventDefault so the page doesn't reload. However on the 2nd try, the page will reload, and I don't know why it's behaving like that.
My DOM function to add an element to the body:
$.fn.toggleDOM = (domName, b) ->
dom = domName[domName.search(/([\.\#])/)]
newDom = domName.substring(1)
if dom == '#'
if b
document.body.innerHTML += '<div id="' + newDom + '"></div>'
else
document.getElementById(newDom).remove()
else
if b
document.body.innerHTML += '<div class="' + newDom + '"></div>'
else
document.getElementsByClassName(newDom)[0].remove()
The event for form submit:
$ ->
trigger = document.querySelectorAll("[data-trigger]")
trigger.forEach((i) ->
i.addEventListener "submit", (e) ->
e.preventDefault()
# We have to pass the event instead of the element.
switch i.attributes["data-trigger"].nodeValue
when "[form/login]" then login(e)
HTML:
<form data-trigger="[form/login]" class="login">
<input type="hidden" class="uuid hidden">
<input placeholder="Username" class="username">
<input placeholder="Password" type="password" class="password">
<button type="submit">Login</button>
</form>
I need to know why it reloads the page on the 2nd try. If I remove the $('body').toggleDOM('.loading', true) it does not behave like that and works as intended.
Also, I'm not using jQuery, I'm using this small library: https://github.com/finom/balalaika
The problem lies in how you attach event listeners to your elements.
What you're trying to do doesn't work in plain JavaScript.
What you need to utilize is event delegation; it won't change much code wise but it'll change how it works.
By removing your for loop and attaching the handler to the document instead, you'll get what you're after.
document.addEventListener "submit", (e) ->
e.preventDefault();
switch e.target.attributes["data-trigger"].nodeValue
when "[form/login]" then login(e)
There is a great article that covers the how and why

how to get the value of dynamically created selectbox

I am creating a div dynamically with ajax. Now if the ajax call is success then i created a string for div element and append it to the original div id.
here is my code
$.ajax({
type:"GET",
url:"resources/json/asnData.json",
dataType:"json",
success:function(data){
$.each(data.Payload, function(index, val){
i=i+1;
stmt+='<div class="row">'+
'<section class="col col-2">'+
'<label class="input"><i class="icon-append fa fa-key"></i>'+
'<input type="text" name="keyName" value="'+val.key+'" readonly/>'+
'</label>'+
'</section>'+
'<section class="col col-3">'+
'<label class="select">'+
'<select id="dataConversionType'+i+'" class="dataConversionType">'+
'<option value="HEX">HEX</option>'+
'<option value="ALL">Compare All</option>'+
'<option value="ASCII">ASCII</option>'+
'<option value="STRING">STRING</option>'+
'<option value="INT">INTEGER</option>'+
'<option value="BINT">BIG INTEGER</option>'+
'</select><i></i>'+
'</label>'+
'</section>'+
'<section class="col col-5">'+
'<label class="input"><i class="icon-append fa fa-dashcube "></i>'+
'<input id="convertedType'+i+'" type="text" value="'+val.value+'" readonly/>'+
'</label>'+
'</section>'+
'</div>';
});
$(".dataParser").append(stmt);
Now there is function where if someone select a value in selectbox then fire and show.
$('#dataConversionType'+i).change(function(e) {
e.preventDefault();
var conversionType=$(this).val(); //I have doubt here also..
console.log(conversionType);
if(conversionType == 'ALL') {
console.log('ALL-Show a modal with each possible conversion');
}
but this is not working. this function works if I called using the class name. But i have to call the function using id with the i value, so that with that i value i can also set some value in other fields.
any help will be appreciated...
Use class instead of id (replace document with some non dynamic container)
$(document).on('change','.dataConversionType',function(e) {
e.preventDefault();
var conversionType=$(this).val();
console.log(conversionType);
var index_val = $(this).attr('data-index')
if(conversionType == 'ALL') {
console.log('ALL-Show a modal with each possible conversion');
}
)};
And when you are generating your element add a data attribute
'<select id="dataConversionType'+i+'" class="dataConversionType" data-index="'+i+'">'
Also if you are inside a loop you need to wrap your ajax within a closure if you want to get correct value and not the latest one.
(function(idx) {
//ajax stuff here
}(i)
Do one thing, Listen to the change event using class name itself, instead of Id.
Put value of i as a custom attribute into the select box. In the listener function, read this attribute and call or perform whatever actions you have to do.
A sample is as below:
'<section class="col col-3">'+
'<label class="select">'+
'<select id="dataConversionType'+i+'" class="dataConversionType" data-count=i>'+
'<option value="HEX">HEX</option>'+
'<option value="ALL">Compare All</option>'+
'<option value="ASCII">ASCII</option>'+
'<option value="STRING">STRING</option>'+
'<option value="INT">INTEGER</option>'+
'<option value="BINT">BIG INTEGER</option>'+
'</select><i></i>'+
'</label>'+
'</section>'
Event listener:-
$('.dataConversionType').change(function(e) {
e.preventDefault();
var conversionType=$(this).val(); //selected value
var valueofI = $(this).attr("data-count");// Value of i
}
data-count is the custom attribute.
Try On change method
$(document).on('change','.dataConversionType',function(e) {
// Paste Your Code
});
OR
$(document).on('change','#dataConversionType',function(e) {
// Paste Your Code
});
$('#dataConversionType1').change(function(e) {alert("Changed")});
this code will not work for dynamically append select box.
you should try-
$(document).on("change","#dataConversionType1",function(){
alert($('#dataConversionType1 option:selected').val());
});
This works for me.
The value of i has been now changed to the latest one and this would not give you all the selectboxes anyways.
If you want to be specific about any select box, do it like:
$('#dataConversionType1').change(function(e) {
// code here
});
If you want to do something on all the selectboxes you have created, you can do it like:
$('[id^="dataConversionType"]').change(function (e) {
// Find the index: Count of i
var elmIndex = $(this).attr("id").replace("dataConversionType", "");
// Reflects the value of it in related input field
$("#convertedType3" + elmIndex).val($(this).val());
});
If you want to use the value of i later for operations, you can do it in 2 ways:
set the value of i in some data- attribute like: data-index=i (example below):
'<select id="dataConversionType'+i+'" class="dataConversionType" data-index="' + i + '">'+
Get the index from the id itself doing split or regex (example: /\d/).

Ajax request stores old data

I have a litte problem with my ajax request and I haven't found a solution yet.
What I am trying to accomplish:
I have simple search form, when I submit I send the data to a PHP file which returns the result as json. Then I add the returned data in a clickable list and when I click on one list item I want to display the data in a new div. This actually works fine. Even if I start a new search I get the correct json objects and the list updates as expected but now I have following problem. If I start a new search without refreshing the whole page and again click on a list item, in the console log i see that the new but also the previous data is still kinda stored in the list or wherever and this is the problem because I then display the wrong data if I click on the list items.
I hope you understand my question and I am thankful for every hint. And btw, is my approach even possible or is there a better way to solve this?
Javascript code
$('#searchbar').submit(function(e){
e.preventDefault();
var query = $('#searchQuery').val();
if (query != ''){
loadData();
}else{
alert('Empty searchform!');
}
});
function loadData(){
var query = $('#searchQuery').val();
$.ajax({
type: "POST",
url: "search.php",
data: {'query': query},
dataType: 'json'
}).done(function(res) {
console.log(res);
resetInfos();
generateList(res);
$('.list-group').on('click', '.list-group-item', function(e){
var index = $(this).index();
console.log(res[index].Name);
$('#locationName').text(res[index].Name);
$('#locationAddress').text(res[index].Zip
+ ' '
+ res[index].State);
$('#locationContact').text(res[index].Internet);
init_map(res[index].Latitude, res[index].Longitude);
});
});
}
function resetInfos(){
$('.list-group').empty();
$('#listItems').remove();
$('#searchQuery').val('');
$('#locationName').text('');
$('#locationAddress').text('');
$('#locationContact').text('');
}
function generateList(result){
$.each(result, function(i){
$('.list-group').append('<li class="list-group-item" id="listItems">'
+ result[i].Name
+ ", "
+ result[i].Zip
+ " "
+ result[i].State);
});
}
HTML search form
<form id="searchbar">
<div class="input-group form-group-lg">
<input type="text" id="searchQuery" name="query" class="form-control" autocomplete="off" placeholder="Name, ZIP, State">
<span class="input-group-btn"><button class="btn btn-success btn-lg" id="searchButton" type="submit">Search</button></span>
</div>
<form>
Ok I solved it. I had to remove the click event handler with
$('.list-group').off('click');
in my resetInfos function.
You are using id selector to remove multiple elements.
$('#listItems').remove();
It will only remove the first matched reference. Please add some class to li element and then use class selector to remove.

How to refresh DOM with newly created elements

I know this question was asked several times, but couldn't get the answer that works for me so here I am with my case.
I'm trying to make a jQuery plug-in that's add contact form to a certain page(It's not like there is no such a plug-ins but let's say I do this just for educational reasons). It is searching for <div id="add_contacts"></div> and creates the form in this div.
jQuery
$(document).ready(function(){
$('#add_contacts').append('<div class="contact-from"></div>');
$('<form></form>',{id:'new_contact'}).appendTo('.contact-form');
$('<div>',{class:'contact_user_name'}).appendTo('#new_contact');
var name_field = $('<input>',{
name:"contact_broker_fullname",
id:"contact_user_name",
}).appendTo('.contact_user_name');
var input_button = $('<input>',{
name:"submit",
type:"submit",
value:"Send"
}).appendTo('#new_contact');
var full_name=name_filed.val();//I'm not sure that this should be here at all.
input_button.on('click',function(){
ajax_send_contact(full_name);
return false;
});
});
And here is the ajax_send_contact(full_name) function:
$.ajax({
url:'../some.php',
type:'post',
data:{name:full_name},
success: function (response){
if (response) {
$('#success').append('<span>All right.</span>');
}
else{
$('#errors').append('<span>Something went wrong.</span>');
}
},
error: function () {
$('#errors').append('<span>ERROR!</span>');
}
});
I've read that when adding dynamically element to HTML they're not included into the DOM, so how can i operate with them. How i can get the value of the input so once the user click the Submit button the value is sent to ajax function. And I'm not asking only for this particular case but for the whole logic as I'm missing something quite important.
Thank you.
I don't know where you read this but it's not true.
Adding elements to your page is DOM manipulation.
In fact there is a lot of DOM manipulation in your ready function.
DOM manipulations are costly, try to reduce them by grouping operations :
var formHtml = '';
formHtml += '<div class="contact-form">';
formHtml += '<form id="new_contact">';
formHtml += '<div class="contact_user_name">';
formHtml += '<input type="text" name="contact_broker_fullname" id="contact_user_name">';
formHtml += '</div>';
formHtml += '<input type="submit" name="submit" value="send">';
formHtml += '</form>';
formHtml += '</div>';
$('#add_contacts').append(formHtml); // Only 1 DOM manip.
There are errors in your code :
$('#add_contacts').append('<div class="contact-from"></div>');
...
var name_field = $('<input>',{
And then :
$('<form></form>',{id:'new_contact'}).appendTo('.contact-form');
...
var full_name=name_filed.val();
'contact-from' then 'contact-form'.
'name_field' then 'name_filed'.
In your code, you get the value of your input#contact_user_name right after you created the form,
that is to say before the user had any chance to input something in it.
You have to do this in your click handler.
Pretty simple, set the data with the value of the field right before firing the request:
data: { name: $('.contact_user_name input').val() }
And you can remove var full_name=name_filed.val(), it would only get the value the field had at the moment it was created, and apparently that variable wouldn't be in scope when you actually need it.
The rest of your code looks okay.

jquery ajax method being repeated even though click event not correct

I have some ajax on my web page, that is triggered via a click event, the javascript in question looks like this,
$('.career_select .selectitems').click(function(){
var selectedCareer = $(this).attr('id');
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
buildSelects();
$('.grade_options .selectitems').addClass('select_1')
}
});
});
This part of the ajax request works fine. What happens on success is that I load in another view into my page, this view has some more user interaction that fires some more ajax however, it just fires the previously used method, where as it should be doing the following,
$('.grade_options .selectitems').click(function(){
var selectedGrade = $(this).attr('id');
alert(selectedGrade);
})
The HTML+PHP looks like this,
<div class="grade_options">
<input value="" name="grade" class="customselect" type="hidden">
<div class="iconselect">Have you got any of the following?</div>
<div style="display: none;" class="iconselectholder">
<div class="selectoptions">
<div id="1" class="selectitems hoverclass selectedclass select_1">
<span>Accountant</span>
</div>
<div id="2" class="selectitems">
<span> Grade D's at GCSE including English and Maths</span>
</div>
<div id="3" class="selectitems">
<span>3 GCSE's at grade B and 3 GCSEs at grade C or equivalent and you must have achieved at least a grade C in GCSE English Language & B in Maths</span>
</div>
</div>
</div>
<noscript>
<input type="submit" value="Next" name="submit_grades" class="arr" />
</noscript>
</div>
The .selectitems get created from a select menu using this plugin,
$.fn.customSelect = function() {
// define defaults and override with options, if available
// by extending the default settings, we don't modify the argument
return this.each(function() {
obj = $(this);
obj.after("<div class=\"selectoptions\"> </div>");
obj.find('option').each(function(i){
$(".selectoptions").append("<div id=\"" + $(this).attr("value") + "\" class=\"selectitems\"><span>" + $(this).html() + "</span></div>");
});
obj.before("<input type=\"hidden\" value =\"\" name=\"" + this.name + "\" class=\"customselect\"/><div class=\"iconselect\">" + this.title + "</div><div class=\"iconselectholder\"> </div>")
.remove();
$('.iconselectholder').hide();
$(".iconselect").click(function(){
$(".iconselectholder").toggle("slow");});
$(".iconselectholder").append( $(".selectoptions")[0] );
$(".selectitems").mouseover(function(){
$(this).addClass("hoverclass");
});
$(".selectitems").mouseout(function(){
$(this).removeClass("hoverclass");
});
$(".selectitems").click(function(){
$(".selectedclass").removeClass("selectedclass");
$(this).addClass("selectedclass");
var thisselection = $(this).html();
$(".customselect").val(this.id);
$(".iconselect").html(thisselection);
$(".iconselectholder").toggle("slow")
});
});
// do the rest of the plugin, using url and settings
}
I am struggling to see any reason as to why my second ajax request is running the method of the first ajax request.
Your code seems somewhat incomplete, but I think I can help you.
Where is the class .career_select in the HTML+PHP example you have given? My guess is that .career_select is wrapping .grade_options due to your append:
$('.hfeed').append(html) am I correct? .grade_options was part of the html that got appended right?
If I am correct, then the newly appended HTML would not have had event handlers tied to it ahead of time and hence your second event handler is not firing. I think there are two things you can do:
Declare the new event handler for $('.grade_options .selectitems') in the success function of the first event handler AFTER the append.
If that doesn't work then just do what Paul Sweatte instructed you to do (look at the comments), unbind the original click event in the success callback or if you are sure it is a one-off thing, take a look at jQuery's $(selector).one().
I hope this helps. If the second one works, please remember to give points to Paul Sweatte's comment.

Categories

Resources