-Dman100-
asked on
Attaching click event to a JQuery object not yet added to the DOM
I have a button that adds table rows dynamically. On each button click I need to show/hide specific elements in the table row.
The first time the buttons is clicked, the first row is added in the table, but the table row has not been added to the DOM so I can't access the table row object.
First I tried this:
Then I tried this:
The problem is that the dataRows object is empty when the button is clicked because the first row of the table has not been added to the DOM.
If I click the button again and a second row is added, then I have access to the first table row. I need to access the row that is being created when the button is clicked.
How can I access the table row object when it is being created?
Thanks for any help.
The first time the buttons is clicked, the first row is added in the table, but the table row has not been added to the DOM so I can't access the table row object.
First I tried this:
j$('[id$=btnContact]').click(function(){
console.log('contact button was clicked');
var dataRows = j$('tr.dataRow');
console.log(dataRows);
});
Then I tried this:
j$('[id$=btnContact]').on("click", function(){
console.log('contact button was clicked');
var dataRows = j$('tr.dataRow');
console.log(dataRows);
});
The problem is that the dataRows object is empty when the button is clicked because the first row of the table has not been added to the DOM.
If I click the button again and a second row is added, then I have access to the first table row. I need to access the row that is being created when the button is clicked.
How can I access the table row object when it is being created?
Thanks for any help.
Please show your code that inserts the row.
For dynamic elements you have to use .on as you are doing but the targeting object must be an element that exists at load and then you target your dynamic element.
j$('#existing_element_cont ainer_id') .on("click ", "target_element",function( ){
...
j$('#existing_element_cont
...
This will fire for every row (and new ones after the DOM has loaded):
see the documentation http://api.jquery.com/on/ re Delegated events
$("#dataTable tbody tr").on("click", function(event){
alert($(this).text());
});
see the documentation http://api.jquery.com/on/ re Delegated events
You can do this too :
or just do the binding after your ajax call :
$(document).on("click", "[id$=btnContact]", function(event){
alert($(this).text());
});
or just do the binding after your ajax call :
var oDBGet = new htmldb_Get(p1, p2, p3, p4);
gReturn = oDBGet.get(); // your ajax call
j$('[id$=btnContact]').click(function(){
console.log('contact button was clicked');
var dataRows = j$('tr.dataRow');
console.log(dataRows);
});
ASKER
Hi tagit,
I'm having to make some modifications to the code you helped with me previously. After doing a review with the users, they wanted some changes to how the page worked.
It has been a few weeks, but if you recall the jquery was hiding images depending on what input field was selected on each row.
So, the change I'm trying to make is the following. The user wants there different buttons to create a new row for either a contact, user or account. So, if the user clicks the "Add New Contact" button, it would only show the lookup for the contact input field. If the user clicks the "Add New User" button, it would only show the lookup for the user input field. And finally, if the user clicks "Add New Account" button, it would only show the lookup for the account input field.
Previously, the images were getting hidden after the row was generated and the input field was populated from the lookup. The end users felt that was confusing and only want to see the one input field for the lookup they are trying to create.
I was trying to follow the code you helped me with, but the issue I was running into is that the table row hasn't been added to the DOM when the button is clicked.
I'm having to make some modifications to the code you helped with me previously. After doing a review with the users, they wanted some changes to how the page worked.
It has been a few weeks, but if you recall the jquery was hiding images depending on what input field was selected on each row.
So, the change I'm trying to make is the following. The user wants there different buttons to create a new row for either a contact, user or account. So, if the user clicks the "Add New Contact" button, it would only show the lookup for the contact input field. If the user clicks the "Add New User" button, it would only show the lookup for the user input field. And finally, if the user clicks "Add New Account" button, it would only show the lookup for the account input field.
Previously, the images were getting hidden after the row was generated and the input field was populated from the lookup. The end users felt that was confusing and only want to see the one input field for the lookup they are trying to create.
I was trying to follow the code you helped me with, but the issue I was running into is that the table row hasn't been added to the DOM when the button is clicked.
I'll have a look back as i remember what you were working on :-) makes sense what you're saying just need to review the code.
I think the same logic still applies in that you use the:
What does the updateImages() function do now?
A4J.AJAX.AddListener({
onafterajax: function(req,evt,data) {
var dataRows = j$('tr.dataRow');
dataRows.each(function(index, elem) {
updateImages(elem);
});
}
});
What does the updateImages() function do now?
ASKER
The updateImages() function is hiding the lookup icon images based on the input value that was populated.
Is there a way to determine which button was clicked from within that onafterajax code?
In this new scenario, I have to hide the input fields and lookup images based on which button was clicked.
Is there a way to determine which button was clicked from within that onafterajax code?
In this new scenario, I have to hide the input fields and lookup images based on which button was clicked.
ASKER
The main difference now is that the elements are not hidden after the user selects a value from one of the lookups. It should happen immediately based on the button that is clicked.
It prevents the user from being presented with all three inputs. They click one of the buttons and it shows them just one input field for the lookup they are trying to do...i.e. Contact, User, or Account.
Thanks for taking a look at this code again! :)
I thought I had it nailed down tight!
It prevents the user from being presented with all three inputs. They click one of the buttons and it shows them just one input field for the lookup they are trying to do...i.e. Contact, User, or Account.
Thanks for taking a look at this code again! :)
I thought I had it nailed down tight!
The first thing that comes to mind is using a cookie, which is easily achieved with jQuery or using the localStorage object to keep track of the clicked button:
so when each button is clicked it sets the storage value
$('#mybuttonid').on('click ', function() {
localStorage.activeBtn = $(this).name;
});
Then you access that data in the updateImages function. Can you post the latest version of that just to be sure as I don't have a copy of it.
so when each button is clicked it sets the storage value
$('#mybuttonid').on('click
localStorage.activeBtn = $(this).name;
});
Then you access that data in the updateImages function. Can you post the latest version of that just to be sure as I don't have a copy of it.
ASKER
Here is the current jquery code without any modifications:
<script type="text/javascript">
var j$ = jQuery.noConflict();
j$(document).ready(function() {
var dataRows = j$('tr.dataRow');
dataRows.each(function(index, elem) {
updateImages(elem);
});
j$("img[id$=':deleteImage']").on("click", function(event) {
updateImages(j$(this).closest('tr'));
});
j$('[id$=btnParticipant]').on("click", function(event){
var dataRows = j$('tr.dataRow');
dataRows.each(function(index, elem) {
updateImages(elem);
});
});
A4J.AJAX.AddListener({
onafterajax: function(req,evt,data) {
var dataRows = j$('tr.dataRow');
dataRows.each(function(index, elem) {
updateImages(elem);
});
}
});
});
function updateImages(myRow) {
var rowInputs = j$(myRow).find('input[type="text"]');
var contact = (j$(rowInputs[0]).val());
var user = (j$(rowInputs[1]).val());
var account = (j$(rowInputs[2]).val());
if (contact !== '') {
j$(rowInputs[0].parentNode).find('img').show();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').hide();
}
else if (user !== '') {
if(rowInputs.length == 3) {
j$(rowInputs[0].parentNode).find('img').hide();
j$(rowInputs[1].parentNode).find('img').show();
j$(rowInputs[2].parentNode).find('img').hide();
}
}
else if (account !== '') {
j$(rowInputs[0].parentNode).find('img').hide();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').show();
}
if (account !== '' && contact !== '') {
j$(rowInputs[0].parentNode).find('img').show();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').hide();
}
}
</script>
ASKER
oh, here are the new buttons:
<apex:commandButton id="btnContact" value="Add Contact" action="{!addParticipant}" reRender="participantTable" />
<apex:commandButton id="btnUser" value="Add ACI Employee" action="{!addParticipant}" reRender="participantTable" />
<apex:commandButton id="btnAccount" value="Add Company" action="{!addParticipant}" reRender="participantTable" />
So in the javascript
Then in your updateImages, though I can't test this without access:
j$(document).ready(function() {
...
$('#btnContact').on('click', function() {
localStorage.activeButton = 'contact';
});
$('#btnUser').on('click', function() {
localStorage.activeButton = 'user';
});
$('#btnAccount').on('click', function() {
localStorage.activeButton = 'account';
});
Then in your updateImages, though I can't test this without access:
function updateImages(myRow) {
var rowInputs = j$(myRow).find('input[type="text"]');
var contact = (j$(rowInputs[0]).val());
var user = (j$(rowInputs[1]).val());
var account = (j$(rowInputs[2]).val());
if (localStorage.activeButton === 'contact') {
// hide the other two
j$(rowInputs[1]).hide();
j$(rowInputs[2]).hide();
}
else if (localStorage.activeButton === 'user') {
// hide the other two
j$(rowInputs[0]).hide();
j$(rowInputs[2]).hide();
}
else if (localStorage.activeButton === 'account') {
// hide the other two
j$(rowInputs[0]).hide();
j$(rowInputs[1]).hide();
}
if (contact !== '') {
j$(rowInputs[0].parentNode).find('img').show();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').hide();
}
else if (user !== '') {
if(rowInputs.length == 3) {
j$(rowInputs[0].parentNode).find('img').hide();
j$(rowInputs[1].parentNode).find('img').show();
j$(rowInputs[2].parentNode).find('img').hide();
}
}
else if (account !== '') {
j$(rowInputs[0].parentNode).find('img').hide();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').show();
}
if (account !== '' && contact !== '') {
j$(rowInputs[0].parentNode).find('img').show();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').hide();
}
}
</script>
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Tagit helped me resolve this issue with the following updated code:
A million thanks to Tagit!
<script type="text/javascript">
var j$ = jQuery.noConflict();
j$(document).ready(function() {
var dataRows = j$('tr.dataRow');
localStorage.activeButtons = '';
var active = localStorage.activeButtons.split(',');
dataRows.each(function(index, elem) {
updateImages(elem, active[index]);
});
j$("img[id$=':deleteImage']").on("click", function(event) {
updateImages(j$(this).closest('tr'));
});
j$('[id$=btnContact]').on('click', function() {
localStorage.activeButtons += 'contact,';
});
j$('[id$=btnUser]').on('click', function() {
localStorage.activeButtons += 'user,';
});
j$('[id$=btnAccount]').on('click', function() {
localStorage.activeButtons += 'account,';
});
A4J.AJAX.AddListener({
onafterajax: function(req,evt,data) {
var lastRow = j$('table[id$=participantTable] tbody tr:last');
var active = localStorage.activeButtons.split(',');
var dataRows = j$('tr.dataRow');
dataRows.each(function(index, elem) {
updateImages(elem, active[index]);
});
}
});
});
function updateImages(myRow, myActive) {
var rowInputs = j$(myRow).find('input[type="text"]');
var contactId = (j$(rowInputs[0]).attr('id'));
var userId = (j$(rowInputs[1]).attr('id'));
var accountId = (j$(rowInputs[2]).attr('id'));
console.log(myActive);
if(contactId.indexOf("participant") != -1 || userId.indexOf("participant") != -1 || accountId.indexOf("participant") != -1) {
switch (myActive) {
case "contact":
// hide the other two
j$(rowInputs[1]).hide();
j$(rowInputs[2]).hide();
j$(rowInputs[1].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').hide();
break;
case "user":
// hide the other two
j$(rowInputs[0]).hide();
j$(rowInputs[2]).hide();
j$(rowInputs[0].parentNode).find('img').hide();
j$(rowInputs[2].parentNode).find('img').hide();
break;
case "account":
// hide the other two
j$(rowInputs[0]).hide();
j$(rowInputs[1]).hide();
j$(rowInputs[0].parentNode).find('img').hide();
j$(rowInputs[1].parentNode).find('img').hide();
break;
}
}
}
</script>
A million thanks to Tagit!
ASKER
Thank you Tagit! You are an exceptional expert here! :)