I'm trying to create form for printing with dynamically generated inputs.
Contents of the fields is shown later in PreviewDiv.
It works fine as long as I specify where they should be, for example:
$('#Prw_CapacityA_1').text($('#CapacityA_1').val());
$('#Prw_CapacityB_1').text($('#CapacityB_1').val());
$('#Prw_CapacityC_1').text($('#CapacityC_1').val());
But if the user creates 100 fields this would be a lot of code to write.
There must be other methods to fix this dynamically, for example:
$('#Prw_CapacityA_'+ counter).text($('#CapacityA_'+ counter).val());
Here's the js fiddle
You could try using attribute starts with selector to select the elements starting with the specific id's and then loop through them using the each() function.
There is no need to have html within your preview table. You can generate it when the user clicks on preview. Modified fiddle
$('#PreviewButton').click(function(){
var capB = $('td input[id^=CapacityB_]');
var capC = $('td input[id^=CapacityC_]');
var table = $("#AddFieldsToPreviewDiv");
table.empty(); //build table everytime user previews so that previously appended values are removed
table.append('<tr><td>ID</td><td>Text 1</td><td>Text 2</td><td>Text 3</td></tr>');
$('td input[id^=CapacityA_]').each(function(i){
table.append('<tr><td>#'+(i + 1)
+'</td><td>'+$(this).val()
+'</td><td>'+$(capB[i]).val()
+'</td><td>'+$(capC[i]).val()
+'</td></tr>');
});
// Show PreviewDiv and hide FormDiv if PreviewButton clicked
$('#PreviewDiv').show();
$('#FormDiv').hide();
});
You could try giving them a unique class (Normally I'd suggest ID but you're using one) say a class of "getinfo"
You could then try the .each() function
https://api.jquery.com/each/
$( ".getinfo" ).each(function( index ) {
var text = $(this).val();
alert(text);
});
This will make an alert box for every element it finds with the class 'getinfo' and then retrieve the value and display it, I hope this gives you a better idea.
If the amount of inputs can change from one page load to the next then you need to use a loop, rather than pulling all the values by 'hand', More code will help better understand what you're trying to achieve and from what.
Related
I currently have made a way so the user can add another text field to the form by pressing on a 'add_another' div, this uses basic JS so when the user presses on the div 'add_another' the div 'author_2' is toggled.
I would like to make it so that when the user presses on the 'add_another' div for a second time it shows 'author_3' div, and when they press 'add_another' again, it then shows 'author_4'. I have put all the CSS and HTML divs in place to support this, I am just trying to adapt my code so it shows one div after another, rather then toggling a single div.
Here is my JS:
<script>
$(document).ready(function() {
$('.add_another').on('click', function(){
$('.author_2').toggle();
});
});
</script>
I have tried altering this code, however with no luck.
I haven't added my HTML as it is just 4 divs, 'author_1' 'author_2' ... 3...4
Thankyou for your help
There are two solutions to Your problem.
First one - use static code
It means the max author count is 4 and if user gets to 4, this is it.
If so - You need to store the number of authors already shown.
var authors_shown = 1;
$(document).ready(function() {
$('.add_another').on('click', function(){
authors_shown++;
if (!$('.author_'+authors_shown).is(":visible")) {
$('.author_'+authors_shown).toggle();
}
});
});
But there is also a second - more dynamic option.
What if user wants to input 10 or 20 authors? You don't want to pre render all that html code and hide it. You should clone the div and change its id or if the (HTML) code (for another author) is not too long, you can render it within JS code.
var div = document.getElementById('div_id'),
clone = div.cloneNode(true); // true means clone all childNodes and all event handlers
clone.id = "some_id";
document.body.appendChild(clone);
If it's a form, then change names of input fields to array as author_firstname[]
Also You can store number of added authors in another hidden field (so you know how long to loop the form fields on the server side.
The second option is a bit more complex and longer, but way more dynamic.
You should make another div when clicked on add_another:
something like this:
<script>
$(document).ready(function() {
$('.add_another').on('click', function(){
$('<div><input type="text" name="name[]" /></div>').appendTo('.your_container');
});
});
</script>
as you see, input's name has [] which means you should treat with the inputs as an array.
let me know if you got any further questions
good luck.
Suppose there is Table with variable number of rows of fixed number of columns, and suppose each row has a button too, now I want to select for example a column's value(let's say this selected column is textarea, so I select it's content) when that row's button is clicked.
For example in above image I want that if submit is pressed than all data of 'textarea' of corresponding row should be stored in a variable.
You can use the jQuery closest() function to find an element near the clicked button. Add click handlers to the buttons and then traverse up to find the textarea.
$('.button').on("click",function(){
var thisRowsTA = $(this).closest("textarea");
console.log($(thisRowsTA).val());
});
A simply way is to:
Put an ID pattern to your textareas, like: txt_area_1, txt_area_2, txt_area_3.
Then, on the Click Event of your buttons, make them catch the corresponding textarea in their row. Use the ID patterns to do this.
Post your code for further help.
You will need to ad an event handler for each button. Inside of that you can write something like this.
function eventHandler(e){
var row = this; // start at the button
while(row.nodeName != 'TR' && row.parent){
// go up till we find the row
row = row.parent;
}
var textArea = row.querySelector('textarea');
var value = textArea.value;
// do something with supplied feedback.
}
In order to attach the handlers, you would do something like this.
function attachTableEvents(){
var table = document.querySelector('table'); // or more specific selector if needed
var buttons = table.querySelectorAll('button');
for (var i = buttons.length; i--;){
buttons[i].addEventListener(eventHandler);
}
}
Counting on the DOM structure is really BAD.
I would put an attribute in my controls that holds the line number. Then when clicking an element you can easily query the DOM by element type and the property value to get any elements in this line.
Later if you change to DIVs or change structure your will still run correctly
I am trying to implement a simple update functionality for the values in my table. I have an edit button, which triggers a modal where I edit the values and save them. In order the values to be immediately update in the DOM I am using the following jquery code on save:
$('#lblEditDeleteProducts').find("tr .nameDom").text("new val");
$('#lblEditDeleteProducts').find("tr .brandDom").text("new val");
$('#lblEditDeleteProducts').find("tr .priceDom").text("new val");
The problem is that with this code intead of one row in my table all the rows get updated with the "new value". I am very new to jquery and I am out of ideas how to solve this, so any help will be appreciated.
Here is my table structure :
As there is not much information of your HTML code
var selectedTR;
$("#lblEditDeleteProducts tr").click(function(){
selectedTR=$(this);
//init your modal pop up here or do it globally
})
Let assume the ID of save button is #save
$("#save").click(function(){
selectedTR.find(".nameDom").text("new val"); // get relative value from the mdoal input
selectedTR.find(".brandDom").text("new val");
selectedTR.find(".priceDom").text("new val");
})
If you are interested you can use this plugin also (advanced feature) datatable inline edit
The selectors that find is using are too general, so they're selecting all matching rows.
$('#lblEditDeleteProducts').find("tr .nameDom").text("new val");
Here's what jQuery is doing with that particular line of code (the same thing applies to all the others, too):
Get lblEditDeleteProducts by ID
Using that node, find() all descendant elements that match the selector tr .nameDom
Update the text of all nodes that it finds.
In your case, that selector matches every element in every row because they're all descendants of #lblEditDeleteProducts; there's no way to filter out just those you want with the code that you've written.
You'll need a way of explicitly determining which row to update.
Based on your comment that the edit button is in the each row, you can reference the corresponding row with closest
$("EDIT BUTTON SELECTOR").click(function(){
var $btn = $(this);
var $row = $btn.closest("tr");
$("DIALOG SELECTOR").dialog({
buttons:{
Save: function(){
//bunch of stuff
$row.find("td.nameDom").text("new val");
}
}
});
});
I have a while loop in my php page which sets a different id for every button and form through a counter variable. Every button has to open a different form (they each have different default information preselected, this is for a prescription renewal ability). I can get this to work by having in my javascript a click function for every id which calls a show on the right form. But, obviously this is not scalable, and so it cannot adapt to the amount of prescriptions I have. Looking through the web, I saw people using classes and the id starts with solutions to this problem. However, when I use this solution, the buttons open all the forms... not the desired behavior. Currently my javascript function is the following:
$('[id^="add-renew-link"]').click(function () {
$('[id^="add-renew-form"]').show();
});
Like mentioned above, the function does get called by all different IDs button. That code however opens all the forms every time one of the buttons get click. IDs are actually of the form add-renew-form0, add-renew-form1, add-renew-form2... (same pattern for add-renew-link). Forms and links with the same number at the end are meant to be linked. Does anybody know how I can achieve this? Thanks a lot!!
You can't have multiple DOM elements with the same ID. What you can do here is to assign classes for the elements:
<div class="add-renew-link"></div> <div class="add-renew-form"></div>
And then use .each
$('.add-renew-link').each( function(x){
$(this).click(function(){
$(".add-renew-form:eq("+x+")").show();
});
});
You can check out the JSFiddle here.
You're close. The $('[id^="add-renew-form"]').show(); is going to match ALL ELEMENTS that start w/ "add-renew-form" as the id, so that's why you're experiencing all forms being shown when clicking any link/button.
You can use a regex to pull the number from the end of the id to find a match on the associated form as below:
$('a[id^="add-renew-link"]').click(function() {
var idx = $(this).attr("id").match(/\d+$/)[0]; // Pull index number from id
$("#add-renew-form" + idx).show();
});
This jsbin has a full working example.
http://jsbin.com/xicuwi/1/edit
Try, using the .each() method:
$('[id^="add-renew-link"]').each(function(i){
var ths = $(this);
(function(i){
ths.click(function(){
$('#add-renew-form'+i).show();
}
})(i);
});
On my aspx page I dynamically create html controls on client side using javascript. For example, after page load you can click button in a browser, by clicking button html input and select elements appear. You may click once again, and this elements (input and select) will added again. So, you can create so many inputs and selects as you want (all this using javascript, no postbacks)
After user created some inputs and selects and entered some information in it, he posted form. I want on server side to find all this dynamically added elements and perform some actions depends on values in this controls.
How can I find dynamically added elements, and what is the best and elegant way to achieve this?
Thanks in advance.
In the Javascript that creates the new elements, increment a counter each time an element is created. Add the value of the counter to the name of the input element so each element has a unique name.
Add the final value of the counter to a hidden form field when the form is posted.
In your server side code, create a loop that starts at zero and continues until you have reached the value of the counter. Within the loop, fetch the posted value of the corresponding form field.
When you add the elements, assign unique IDs to them, and then retrieve their values using Request.Form["UniqueIdHere"] (C#) or Request.Form("UniqueIdHere") (VB.NET).
Create a loop that loops through each input and select object, that grabs the name/id of the current object and its corresponding value. Then add those items to an array and once the loop is completed, pass those values to your aspx file.
You can view an example with this approach at: http://jsfiddle.net/euHeX/. It currently just alerts the values, but you could easily modify it to pass the values as a parameter via ajax to your handler aspx file. The code will add new inputs or select boxes based off of the input provided. This would of course be modified to reflect your current setup.
HTML:
<div id="dynamic"></div>
<input type="button" id="submit-form" value="Submit>>">
JavaScript (using jQuery):
function createInput(type){
for(var i=0; i<5; i++){
if(type==0){
var obj = '<input type="text" id="'+i+'" class="dynamicContent">';
}else if(type==1){
var obj = '<select id="'+i+'" class="dynamicContent"><option>--Select--</option></select>';
}
$("#dynamic").append(obj);
}
}
function getContent(){
var inputArray = [];
$(".dynamicContent").each(function(k,v){
var o = $(this);
var oType;
if(o.is("input")){ oType = "input"; }
if(o.is("select")){ oType = "select"; }
var oID = oType+o.attr("id");
var oValue = o.val();
inputArray.push(oID+'='+oValue);
});
alert(inputArray);
}
$("#submit-form").click(function(){
getContent();
});
// Set type to 0 for input or 1 for select
var type = '1';
createInput(type);
If you're using jQuery you can use .live() to achive this like a peace of cake!
http://api.jquery.com/live/
I don't know if your controls will survive the postback the way you're creating them, but a good technique for accessing dynamically generated controls (assuming that you've figured out how to persist them) is to do something like the following:
Add a panel to your page. Add your dynamically created controls to this panel.
In the OnClick event handler (or other method), do something like the following:
foreach (DropDownList ddl in Panel1.Controls.OfType<DropDownList>())
{
//put code here
}
foreach (TextBox txt in Panel1.Controls.OfType<TextBox>())
{
//put code here
}