I use Bootstrap and have a form with 2 textfields and 2 checkboxes. With an add-Button, I want to add (per click) an additional textfield with checkbox. Currently I'm using this JS:
$("#addButton").click(function () {
var newTextBoxDiv = $(document.createElement('div'))
.attr("id", 'TextBoxDiv' + counter);
/* TODO: patterns festlegen */
newTextBoxDiv.after().html('<div class="form-group label-floating">' +
'<label class="control-label">Answer' + counter + '</label>' +
'<input type="text" class="form-control"/>' +
'</div><div class="togglebutton"><label><input type="checkbox" checked="">Toggle is on</input></label></div>');
newTextBoxDiv.appendTo("#AnswerGroup");
counter++;
});
It adds successfully the textfield, but the checkbox isn't showing up, only the text "Toggle is on".
How can I solve this? I inserted the JS inside $(document).ready(function () {.
EDIT I think the CSS causes the problem. When I simply add '</div><input type="checkbox" checked=""/></div>', it only shows the checkbox without UI. After adding the rest (like class="togglebutton", I see nothing.
The markup for your checkbox is not correct:
<label><input type="checkbox" checked="">Toggle is on</input></label>
should be
<label><input type="checkbox" checked="" />Toggle is on</label>
May be because input tag has no closing pair.
Try
'<input type="checkbox" checked="">'
And it has to have "name" attribute
Tested answer
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$( document ).ready(function() {
$("#addButton").click(function () {
var counter = 2; //for sample
var newTextBoxDiv = $(document.createElement('div'))
.attr("id", 'TextBoxDiv' + counter);
/* TODO: patterns festlegen */
newTextBoxDiv.after().html('<div class="form-group label-floating">' +
'<label class="control-label">Answer' + counter + '</label>' +
'<input type="text" class="form-control"/>' +
'</div><div class="togglebutton"><label><input type="checkbox" checked="">Toggle is on</input></label></div>');
newTextBoxDiv.appendTo("#AnswerGroup");
counter++;
});
});
</script>
</head>
<body>
<input type="button" id="addButton" value="hello"/>
<div id="AnswerGroup"> </div>
</body>
</html>
First, instead of $("#addButton").click(function () { get in the habit of doing $("#addButton").on('click', function () {, you'll have more control of the event listener in the future.
Next, var newTextBoxDiv = $(document.createElement('div')).attr("id", 'TextBoxDiv' + counter); should be var newTextBoxDiv = $('<div/>').prop('id', 'TextBoxDiv' + counter);.
Next it seems you are creating content newTextBoxDiv and then inserting content after it. I'm not sure you want to do that. I would think you would want to add content to the box you just made. Additionally, according to .after(), it accepts html as an argument. I believe you calling .html() afterward is just setting the inner HTML of newTextBoxDiv anyway.
As your question specifically; you should be able to create a checkbox with the following syntax:
var checkbox = $('<input/>').attr('type', 'checkbox');
To set it to checked (or unchecked) you use .prop() like this:
checkbox.prop('checked', true); //checks the box.
To set it as an HTML string (and have it checked) I believe you should use the following syntax:
<input type="checkbox" checked>
Try use:
newTextBoxDiv.append(...)
instead of
newTextBoxDiv.after().html(...)
Related
Here is my code. In that code the remove function works on only one input box, however I want that, it work on every input box which created through the append function.
<script>
$(document).ready(function(){
var one=1;
$("#add").click(function(){
one++;
$("#form_value").append("<div id=\"man"+one+"\"><br><input type=\"text\" placeholder=\"Product\"name=\"product["+one+"]\"><div class=\"w3-col l4\"> <input type=\"text\" placeholder=\"Product description\"></div><button type=\"button\" id=\"rem"+one+"\">Remove</button></div>");
$("#rem"+one+"").click(function(){
$("#man"+one+"").remove();
});
});
});
</script>
This happens because the value of one will increase each time you click on the add button, and this is the value that is used within the remove event.
If you add console.log(one) within the remove event you will see that one is always the last number.
A better way to do this would be to assign the div/remove elements to jquery objects and remove that instead.
e.g.
var one = 1;
$("#add").click(function() {
one++;
var $div = $("<div id='man" + one + "'></div>");
$div.append("<br><input type=\"text\" placeholder=\"Product\"name=\"product[" + one + "]\"><div class=\"w3-col l4\"> <input type=\"text\" placeholder=\"Product description\"></div>");
var $remove =
$("<button type='button' id='rem" + one + "'>Remove</button>")
.click(function() {
$div.remove();
});
$("#form_value").append($div.append($remove));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="form_value"></div>
<button id="add">Add</button>
Hi I want to add some jquery code into my angular 2 projet to add input text field dynamically, its work, but the removeTextField doesnt execute when I click on it heres the code:
addTextField(){
var newTextBoxDiv = $(document.createElement('div'))
.attr("id", 'TextBoxDiv' + this.counter);
newTextBoxDiv.after().html('<label>Textbox #'+ this.counter + ' : </label>' +
'<input type="text" name="textbox' + this.counter +
'" id="textbox' + this.counter + '" value="" >'+'<span (click)="removeTextField(this.counter)" class="glyphicon glyphicon-remove pull-right" style="z-index:33;cursor: pointer"> </span>');
newTextBoxDiv.appendTo("#TextBoxesGroup");
this.counter++;
}
removeTextField(currentTextField){
alert(currentTextField);
}
any suggestions, please!!!
Try like this
For example if your input text field is like
<input type="text" class="my-input-field">
In your controller
$(document).click("on", ".my-input-field", ()=>{
//capture the currentTextField using jquery
this.removeTextField(currentTextField);
})
removeTextField(currentTextField){
}
Example
Its a datatable implemented in angular 2.. The update and delete buttons are rendered on the fly.
HTML
<table class="datatable table table-striped table-bordered" (click)="onTableClick($event)"></table>
Controller
onTableClick(event){
if(event.target.className.indexOf('update-row')!= -1){ //will get the class name and check if matches update button class
this.updateRow($(event.target).attr("data-id"))
}
if(event.target.className.indexOf('delete-row')!= -1){ //will get the class name and check if matches delete button class
this.deleteRow($(event.target).attr("data-id"))
}
}
I'm learning and trying to put together a little bit of jquery. Admittedly I'm finding it difficult to find a good basics guide, particularly, when adding multiple actions to one page.
I read somewhere that the document listener should only be used once. I believe I'm using it twice here, but not 100% sure how to bring it into one listener.
Also because I've been hacking bits of script together, I think I'm using parts of javascript and parts of jQuery. Is this correct?
A critique of the code below [which does work] and any advice on how best to approach learning jQuery would be most helpful. Thanks.
Script 1 styles a group of 3 radio buttons depending on which one is clicked.
Script 2 appends new inputs to the bottom of a form.
var stateNo = <?php echo $HighestPlayerID; ?> + 1;
$(document).on('click', 'input', function () {
var name = $(this).attr("name");
if ($('input[name="' + name + '"]:eq(1)')[0].checked) {
$('label[name="' + name + '"]:eq(1)').addClass('nostate');
$('label[name="' + name + '"]').removeClass('selected');
}
else {
$('label[name="' + name + '"]').removeClass('nostate selected');
if ($('input[name="' + name + '"]:eq(0)')[0].checked) {
$('label[name="' + name + '"]:eq(0)').addClass('selected');
}
else {
$('label[name="' + name + '"]:eq(2)').addClass('selected');
}
}
});
$(document).on('click', 'button[name=btnbtn]', function () {
var stateName = 'state[' + stateNo + ']';
var newPlayerAppend = `` +
`<tr><td>` +
`<input type="hidden" name="state['` + stateNo + `'][PlayerID]" value="` + stateNo + `" /></td>` +
`<td><input name="` + stateName + `[Name]" value="Name"></td>` +
`<td><input name="` + stateName + `[Team]" type="radio" value="A">` +
`<td><input name="` + stateName + `[Team]" type="radio" value="">` +
`<td><input name="` + stateName + `[Team]" type="radio" value="B">` +
`</td></tr>`;
$("tbody").append(newPlayerAppend);
stateNo++;
});
HTML for the 3 radio button inputs
<td class="Choice">
<label name="state[1][Team]" class="teampick Astate ">A
<input name="state[1][Team]" type="radio" value="A" />
</label>
<label name="state[1][Team]" class="smallx nostate ">X
<input name="state[1][Team]" type="radio" value="" checked />
</label>
<label name="state[1][Team]" class="teampick Bstate">B
<input name="state[1][Team]" type="radio" value="B" />
</label>
</td>
Some of the code can be written more concisely, or more the jQuery way, but first I want to highlight an issue with your current solution:
The following would generate invalid HTML, if it were not that browsers try to solve the inconsistency:
$("tbody").append(newPlayerAppend);
A tbody element cannot have input elements as direct children. If you really want the added content to be part of the table, you need to add a row and a cell, and put the new input elements in there.
Here is the code I would suggest, that does approximately the same as your code:
$(document).on('click', 'input', function () {
$('label[name="' + $(this).attr('name') + '"]')
.removeClass('nostate selected')
.has(':checked')
.addClass(function () {
return $(this).is('.smallx') ? 'nostate' : 'selected';
});
});
$(document).on('click', 'button[name=btnbtn]', function () {
$('tbody').append($('<tr>').append($('<td>').append(
$('<input>').attr({name: `state[${stateNo}][PlayerID]`, value: stateNo, type: 'hidden'}),
$('<input>').attr({name: `state[${stateNo}][Name]`, value: 'Name'}),
$('<input>').attr({name: `state[${stateNo}][Team]`, value: 'A', type: 'radio'})
)));
stateNo++;
});
There is no issue in having two handlers. They deal with different target elements, and even if they would deal with the same elements, it would still not be a real problem: the DOM is designed to deal with multiple event handlers.
There are 2 places you are using anonymous functions. If the code block moves to a named function, the entire code becomes more maintainable. It also helps better in debugging by telling you upfront which function name the error may lie in.
Once you have named functions you will realise that you really do have 2 event listeners for click. So there isn't much benefit of moving them in one listener (or one function you may be referring to). These both event listeners attach on document object and listen to a click event.
Class names are always better when hyphenated. a-state over Astate.
If it works it is correct code, for once you asked about correctness.
It is absolutely fine to have multiple listeners but I usually prefer making everything under one roof. Consider making code as simple as possible which saves lot of time during maintenance.
you can use $(function() {}) or document.ready().
$(document).ready(function() {
$('input[type="radio"]').click(function() {
var thisa = $(this).parent();
var name = $(this).attr("name");
// Remove :selected class from the previous selected labels.
$('label[name="' + name + '"]').removeClass('selected');
// Add conditional class with tenary operator.
thisa.parent().hasClass("smallx") ? thisa.addClass('nostate') : thisa.addClass('selected');
});
$('button[name=btnbtn]').click(function() {
var stateName = 'state[' + stateNo + ']';
// Add TR and TD before appending the row to tbody
var newPlayerAppend = `<tr><td>` +
`<input type="hidden" name="state['` + stateNo + `'][PlayerID]" value="` + stateNo + `" />` +
`<input name="` + stateName + `[Name]" value="Name">` +
`<input name="` + stateName + `[Team]" type="radio" value="A"></td></tr>`;
$("tbody").append(newPlayerAppend);
stateNo++;
});
});
Hope this helps.
I am running a loop which is appending input fields. Now, as I am using a loop, all the attributes are similars. So, when I need to grab any one of the then I am grabbing more than one field.
How do I dynamically change the attributes according to the index, so that I can grab the correct input field ?
ebs_no = data.number_ebs;
for(i=0;i<ebs_no;i++){
$('form.ebs').append("<br>EBS"+(i+1)+"</br>");
$('form.ebs').append('<br> SNAPSHOTNO <input type="text" name="'+i+'"></br>');
$('form.ebs').append('<input type="submit" name="submit">');
$('[name='+i+']').on('submit',function(){
alert($('[name='+i+']').val());
});
}
Replace this:
alert($('[name='+i+']').val());
by this:
alert($(this).val());
The code $(this) refers to the element being treated
Your are looking for event delegation.It is used for created Dynamically DOM elements and use class instead of iterare i in the loop
ebs_no = data.number_ebs;
for (i = 0; i < ebs_no; i++) {
$('form.ebs').append("<br>EBS" + (i + 1) + "</br>");
$('form.ebs').append('<br> SNAPSHOTNO <input type="text" class="someClass" name="' + i + '"></br>');
$('form.ebs').append('<input type="submit" name="submit">');
$('[name=' + i + ']').on('submit', function () {
alert($('[name=' + i + ']').val());
});
}
$(document).on('submit', '.someClass', function () {
alert($(this).val());
});
I have a script which adds a new form when a button is clicked to a HTML page with the code as following:
<script>
var counter = 1;
var limit = 10;
function addInput(divName){
if (counter == limit) {
alert("Max number of forms, " + counter );
}
else
{
var newdiv = document.createElement('div');
newdiv.innerHTML = "<form name='frmMain' action='prelucrare.php' method='POST'><div class='slot' id='dynamicInput' align='center'> Masina " + (counter +1 ) + "<table border='1'><tr><td align='right'><label for='marca'>Marca:</label></td><td colspan='2' align='left'>"
+ "<select id='marc' name='marc'><option selected value=''></option>"
+ "<tr><td align='right'><label for='motorizare1'> Motorizare:</label></td> <td><input type='range' name='motorizare1[]Input' min='0.6' max='5' step='0.1' value=2 id=motor1 oninput='outputUpdate1(value)'></td><td><output for=motorizare1 id=moto1>2</output></td></tr>"
+ "</div></form>"
;
}
document.getElementById(divName).appendChild(newdiv);
counter++;
}
</script>
<input type="button" value="Adauga" onClick="addInput('dynamicInput');">
And I have the script bellow which changes the value from the slider.
<script>
function outputUpdate1(mot1) {
document.querySelector('#moto1').innerHTML = mot1;
}
</script>
My problem is that the JS code only changes the input for the first form, even if the slider is activated from another form. In short, the slider should return the value in the form from which it is activate; not only in the first form added.
Thank you!
Going along with my comment, the problem is stemming from the id value being the same across all of your output elements (moto1). You've actually got all the variables you need to make them unique since you're tracking a count of the number of forms on the page (your counter variable). You can use this in place of your current output HTML:
"<input type='range' name='motorizare1[]Input' min='0.6' max='5' step='0.1' value=2 id='motor_" + counter + "' oninput='outputUpdate1(value)'/>"
"<output for=motorizare1 id='moto_" + counter + "'>"
You can update your function to parse out the correct index for the output you want to update since they should be in sync if you use the HTML above:
function outputUpdate1(mot) {
// Get the counter part of the range element's id
var index = mot.id.split('_')[1];
document.querySelector('#moto_' + index).innerHTML = mot;
}
You may need to make some tweaks to code you haven't provided in the question, but that's one way of making the id values unique and how to access them without knowing the exact id ahead of time.