I have a dynamic input field that gets appended after a plus button.
The corresponding id of these fields are answer0, answer1, answer2 and so on. That means after button click the id will be dynamically appended to the text field.
Now I want to validate these fields. My validation code is as follows
function showValidation(response) {
var respArray = JSON.parse(response.responseText).errors;
for(var i=0;i<=(Object.keys(respArray).length);i++){
var optionss= 'Enter Answers.';
if($("#answer"+i).val()==''){
$('#answer'+i+' + span').html('');
$('#answer'+i).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss+ '</span>');
$('#answer'+i).focus();
}
}
}
I am checking till response error length. But before giving values in these fields, validation works properly(fig 1). But if I enter values for first 2 fields as in the image above, the validation message does not shows for the third field (fig 2). Because at this stage the id is answer2 and the loop 'i' value checks 0 first and next checks 1. So inside loop answer0 and answer1 are having values so the validation stops there. I need to get validation for the next fields too. Thanks in advance.
My HTML and corresponding append function
<input class="form-control" name="answer0[]" id="answer0" placeholder="OPTION 1">
<a class="add-option" onclick="AppendOption()"><img src="{{asset('admin/images/icn-add-option.png')}}" alt=""></a>
function AppendOption(){
var k=1;
$('#appendOption').append('<div class="form-group row"><div class="col-md-4"><input class="form-control" name="answer0[]" id="answer'+k+'" placeholder="OPTION" ></div></div>');
k++;
}
In your AppendOption function, you set k=1 This is an invalid option once you reach the third entry (option 2). You should instead detect that, better yet still make it context sensitive when it executes. I did this by adding a answer-item class and detecting how many we have and using that number instead.
I wrapped all this in a <div id="options-container"> so I would have a place to hook the event handler (delegateTarget) https://api.jquery.com/event.delegateTarget/
I would not have used an ID here and instead used classes, but that is not part of the question but more rather the cause of it.
$('.options-container').on('click','.add-option',function(event){
let k= $(event.delegateTarget).find('.answer-item').length;
$(event.delegateTarget).append('<div class="form-group row"><div class="col-md-4"><input class="form-control answer-item" name="answer0[]" id="answer' + k + '" placeholder="OPTION" ></div></div>');
});
function showValidation(response) {
var respArray = JSON.parse(response.responseText).errors;
for (var i = 0; i <= (Object.keys(respArray).length); i++) {
var optionss = 'Enter Answers.';
if ($("#answer" + i).val() == '') {
$('#answer' + i + ' + span').html('');
$('#answer' + i).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss + '</span>');
$('#answer' + i).focus();
}
}
}
<div id="options-container">
<input class="form-control answer-item" name="answer0[]" id="answer0" placeholder="OPTION 1">
<a class="add-option"><img src="{{asset('admin/images/icn-add-option.png')}}" alt=""></a>
</div>
If the fields are required you should mark them as required otherwise you validate every field. In your case another way for validating could look like this
function showValidation(response) {
var respArray = JSON.parse(response.responseText).errors;
$('.form-group input.form-control').each(function(){
if ($(this).val() == '') {
$(this).next('span').html('');
$(this).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss+ '</span>');
$(this).focus();
}
});
}
Since I don't know how and where the showValidation() is called I can't improve it further.
I tried to display the error messages inside an input array loop and I got the answer.
var result = document.getElementsByTagName("input");
var optionss= 'Enter Answers.';
for (var j = 0; j < result.length; j++) {
if($("#answer"+j).val()==''){
$('#answer'+j+' + span').html('');
$('#answer'+j).after('<span class="' + errTextboxClass + '" style="color:#e03b3b">' + optionss+ '</span>');
$('#answer'+j).focus();
}
Related
Goal: Show a label, and input value from a different div and display it in a different section
I have a div that dynamically generates a set of input fields, and I am trying to then display that input fields value and their corresponding labels in a different section.
For example:
Step 1 - User enters in the number 5 into an input field.
Step 2 - There are 5 input fields created (based on value entered from step 1). Those input fields are labeled #1, #2, #3, etc... all the way to #5 or whatever number the user entered in Step 1.
Step 3 - User is presented with a new HTML section that lists off the labels (#1, #2, #3, etc.) and next to the labels is the value the user entered for those corresponding input fields.
Here is the code created for Step 2:
<label>#' + count + '</label>
<input type="number" name="length_field" value="" class="form-control length_field" />
Then, I need some javascript/jquery to take the labels and their corresponding input values and display then something like this:
<p>[LABEL #1] <span>[LABEL #1 INPUT VALUE]</span></p>
<p>[LABEL #2] <span>[LABEL #2 INPUT VALUE]</span></p>
<p>[LABEL #3] <span>[LABEL #3 INPUT VALUE]</span></p>
Etc...
For step 2 you need to check the value of your length_field input and create that many inputs by JavaScript. Set some helper ID and CLASS attributes so you can get values later.
For step 3 use that attributes to get input field values and set them as result div's html.
$(document).on('change', '#length_field', function() {
var inputsCount = parseInt($(this).val());
$('#inputsWrapper').html('');
$('#result').html('');
for (var i = 1; i <= inputsCount; i++) {
// Create custom input with label
var tempInput = document.createElement('input');
tempInput.setAttribute('name', i);
tempInput.setAttribute('id', i);
tempInput.setAttribute('class', 'customInputs');
var tempInputLabel = document.createElement('label');
tempInputLabel.setAttribute("for", i);
tempInputLabel.innerHTML = 'Input #' + i + ": ";
$('#inputsWrapper').append(tempInputLabel);
$('#inputsWrapper').append(tempInput);
// Create corresponding value presenter in result div
var resultRow = document.createElement('p');
resultRow.setAttribute('id', 'result-' + i);
resultRow.innerHTML = 'Label #' + i + ':';
$('#result').append(resultRow);
}
});
$(document).on('keyup', '.customInputs', function() {
var id = $(this).attr('id');
var inputValue = $(this).val();
$('#result-' + id).html('Label #' + id + ': <span> ' + inputValue + '</span>');
});
#inputsWrapper input {
display: block;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="length_field">Enter the number of inputs you want:</label>
<input type="number" name="length_field" id="length_field" />
<br/>
<div id="inputsWrapper">
</div>
<hr>
<div id="result">
</div>
This is really quick'n'dirty but it works.
I'm using a for-loop in both steps, in the first step the for-loop is generating the input fields and outputting them after.
In the second step I'm saving the html of the resulting paragraphs in a variable, because I can't override the document, because my wanted values are in the input fields.
The on keypress listener is optional and ensures that you don't have to press the Submit button with your mouse ;)
If I could help you i would appreciate if you could mark this answer as accepted.
let number = 0;
$(document).on("click", "#step1", function() {
number = $("input").val();
if (number > 0) {
let html = "", i;
for (i = 1; i <= number; i++) {
html += "<label for='input_" + i + "'>#" + i + "</label>: <input type='text' id='input_" + i + "'><br>";
}
html += "<button id='step2'>Submit</button>"
$("body").html(html);
}
})
$(document).on("click", "#step2", function() {
let html = "", i;
for (i = 1; i <= number; i++) {
html += "<p>Label #" + i + ": <span>" + $("#input_" + i).val() + "</span></p>";
}
$("body").html(html);
})
$(document).on('keypress', function(e) {
if (e.which == 13) {
$("button").trigger("click");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" placeholder="Number of fields">
<button id="step1">Submit</button>
I have the following JS code which use's local storage to display the 'name' and 'age' entered previously:
This HTML code currently displays the date, time, name and age of a person in a table. how can i pass these values to be displayed in a HTML form as labels instead of in that table?
HTML only bringing back the start time, name and age aren't being displayed:
<div id="history_list"></div>
<div id="name"> </div>
<div id="age"></div>
JS:
function loadHistoryList() {
for(var i = numberOfHistory; i >= 1; i--) {
var historyData = new historyElement(db.getItem(i.toString()));
if(historyData === null) {
console.error('error');
continue;
}
$('#history_list').append(historyData.startTime);
$('#name').append(historyData.name);
$('#age').append(historyData.age);
}
}
instead of
var div = '<div id="history_element"><div id="element_title">' + historyData.startDate + ' ' + historyData.startTime + '</div><table>';
var div = '<div id="name"><tr><td>name: </td><td>' + historyData.name+ '</td></tr>';
var div = '<div id="age"><tr><td>age: </td><td>' + historyData.age+ '</td></tr>';
div += '</table></div>';
$('#history_list').append(div);
$('#name').append(div);
$('#age').append(div);
Do this:
$('#history_list').append(historyData.startTime);
$('#name').append(historyData.name);
$('#age').append(historyData.age);
In short: you can (and should in this case) simply add the desired value to the container (the DIV, Form field, or whatnot)
those three lines starting witn var div (...) are overwriting each previous line, but that is a side note.
Overall, you should read up more on JavaScript and/or JQuery.
To populate the form field First you have to add a form element like input field
HTML
<div id="history_list">
</div>
<input type="text" id="name" name="name">
JS
function loadHistoryList() {
for(var i = numberOfHistory; i >= 1; i--) {
var historyData = new historyElement(db.getItem(i.toString()));
if(historyData === null) {
console.error('error');
continue;
}
$('#name').val(historyData.name);
}
}
I'm trying to create a form where users can select a month, and then it shows checkboxes with all the days in that month.
Now, I've got this:
<form name="form">
<div>
<label for="month">Maand:</label>
<select id="month" name="month" onChange="selMonth()">
<option value="-1" disabled selected>--Pick A Month--</option>
<option value="4" >april</option>
<option value="5" >mei</option>
<option value="6" >juni</option>
</select>
</div>
<div>
Days:<br />
<script type="text/javascript">
function daysInMonth(month,year)
{
return new Date(year, month, 0).getDate();
}
function selMonth() {
var slctdM = document.form.month.value;
var dys = daysInMonth(slctdM,2014);
for(i = 1; i <= dys ; i++)
{
document.write('<span style="width:10%;display:inline-block;"><input type="checkbox" id="' + i + '" /><label for="day_' + i + '">Dag ' + i + '</label></span>');
}
}
</script>
</div>
</form>
I get the correct values, and the correct number of boxes get displayed, but erase everything on the page (so, the rest of the page and form gets erased. Also, the page keeps loading after all the boxes are shown on screen.
There is probably a simple fix for this or a stupid mistake I made, since I'm not that familiar with javascript.
At first I wrote the for loop with php, but I decide to use javascript instead, because I want the number of boxes to update dynamically when a certain month is selected.
UPDATES
I now see that the page only keeps loading in Firefox, in Chrome the page finishes loading, but only shows the boxes.
I think the problem lies with the function selMonth(), because it is called with onChange, so when the month is changed, it only does document.write, and thinks it can forget the rest. But I don't know how to solve this. Moving the loop outside of the function doesn't solve my problem.
You might want to use .innerHTML instead of document.write().
I guess what you would like to do is something like this:
DEMO :http://jsfiddle.net/UaAX5/
HTML:
Days:<br />
<div id="days_area"></div>
JavaScript:
function selMonth() {
var slctdM = document.form.month.value;
var dys = daysInMonth(slctdM,2014);
var boxes = "";
for(i = 1; i <= dys ; i++)
{
boxes += '<span style="width:10%;display:inline-block;">'+
'<input type="checkbox" id="' + i + '" />'+
'<label for="day_' + i + '">Dag ' + i + '</label></span>';
}
document.getElementById('days_area').innerHTML = boxes;
}
The document of innerHTML is here :
https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML
Hope this helps.
document.write overwrites your entire document.
What you should do instead is append to the innerHTML of your form.
function selMonth() {
var slctdM = document.form.month.value;
var dys = daysInMonth(slctdM,2014);
var frm = document.forms[0];
for(i = 1; i <= dys ; i++)
{
frm.innerHTML += '<span style="width:10%;display:inline-block;"><input type="checkbox" id="' + i + '" /><label for="day_' + i + '">Dag ' + i + '</label></span>';
}
}
I've created a portion of my content through using jQuery to make the same content for each item in my list. It has all worked perfectly except for the last entry. For some reason it acts weird.
An input field is created for each entry that only accepts 2 characters. I have an error script that will parse the entry and see if it's valid. I am only accepting numbers below 61 in this case. All the inputs work except for the last entry.
Additionally, the labels for the 3 inputs created are not putting focus on the respected input value for this entry.
My problem is I don't know why the last entry doesn't work whereas the others will. Can someone explain?
Below are a few functions used.
Populate.js (Used to create content from list)
var $parent = $('div#heroes');
var prestige = '<option value="0">None</option><option value="1">Prestige 1</option><option value="2">Prestige 2</option><option value="3">Prestige 3</option><option value="4">Prestige 4</option><option value="5">Prestige 5</option>'
$.each(heroes, function(index,value) {
$div = $('<div id="hero' + index + '"></div>');
$div.append('<h6>' + value + '</h6>');
$div.append('<span id="active"><input type="checkbox" id="isActive' + index + '" /><label for="isActive' + index + '">Is Active?</label></span>');
$div.append('<span id="level"><label for="level' + index + '">Level: </label><input type="text" size="2" maxlength="2" id="level' + index + '" /></span>');
$div.append('<span id="prestige"><label for="prestige' + index + '">Prestige: </label><select id="prestige' + index + '">' + prestige + '</select></span>');
$parent.append($div);
});
errors.js (Parses the input value and prints the error if not a integer below 61)
$.each(heroes, function(index,value){
$('input#level' + index).change(function() {
var val = $('input#level' + index).val();
if(val > 60) {
alertify.log("Hero " + value + " cannot be above Level 60!", "", 0);
$('#level' + index).addClass('error');
} else if( isNumeric(val) ) {
if( $('#level' + index).hasClass('error') ) {
$('#level' + index).removeClass('error');
}
} else {
alertify.log("Only numbers are accepted.");
$('#level' + index).addClass('error');
}
});
});
function isNumeric(num){
return !isNaN(num);
}
The list used:
var heroes = ["Black Panther","Black Widow","Cable","Captain America","Colossus","Cyclops","Daredevil","Deadpool",/*"Doctor Strange",*/"Emma Frost",
"Gambit","Ghost Rider","Hawkeye","Hulk","Human Torch","Iron Man","Jean Grey",/*"Juggernaut",*/"Loki","Luke Cage",/*"Magneto","Moon Knight",*/"Ms Marvel",
"Nightcrawler",/*"Nova","Psylocke",*/"Punisher","Rocket Raccoon",/*"Silver Surfer",*/"Scarlet Witch","Spider-Man","Squirrel Girl",/*"Star-Lord",*/"Storm",
/*"Sue Storm",*/"Thing","Thor","Wolverine"/*,"Venom"*/];
You can view the page at http://spedwards.cz.cc/new.html
I am still accepting answers. I am stumped to why this isn't working as expected.
Ok I figured out my problem. I'm using the bx-slider plugin and it creates a clone of the last element before the first and a clone of the first, after the last. So my function was getting the clone.
All I had to do was add :not(.bx-clone) to the selector.
So instead of $('input#level' + index); it changed to $('input#level' + index + ':not(.bx-clone)');
I have this fiddle which is having user tab.In user tab ,there are three fields which accepts name,mobile and email.When a user fills all the three and hits add button then a row is inserted.Now i want to make the new added row editable.This means that I want to keep 2 bootstrap buttons edit and delete.So if delete is pressed then the entire row will be deleted and if edit is pressed then the entire will be editable where user can change the mobile number,name and email.Can any body please tell me how to do.
This js code adds new rows
$('#btn1').click(function () {
if ($(".span4").val() != "") {
$("#mytable").append('<tr id="mytr' + val + '"></tr>');
$tr=$("#mytr" + val);
$tr.append('<td class=\"cb\"><input type=\"checkbox\" value=\"yes\" name="mytr' + val + '" unchecked ></td>');
$(".span4").each(function () {
$tr.append("<td >" + $(this).val() + "</td>");
});
var arr={};
name=($tr.find('td:eq(1)').text());
email=($tr.find('td:eq(2)').text());
mobile=($tr.find('td:eq(3)').text());
arr['name']=name;arr['email']=email;arr['mobile']=mobile;
obj[val]=arr;
val++;
} else {
alert("please fill the form completely");
}
This question is so specific to the OP scenario, so i will try to make the answer a bit more general.
I'm no expert here, but it seems you already capture the user's input and cloned it when they click Add to a new td. Therefore from what I understood is that you need to edit/delete the data from the new created td.
We have a table that contains several fields. We want to apply the following action on them
1- Add
2- Edit
3- Delete
Maybe this isn't the best practice, in short, my approach for this was to insert two spans for each data value:
One hidden that contains an input text field (inputSpan).
Another just contains plain text value (dataSpan).
Whenever you want to edit, dataSpan (just a data container) will disappear and inputSpan (text input field) appears instead enabling you to edit the text field. Once you edit and click Save the data in the text field will be cloned to replace the data in dataSpan. So basically dataSpan is just a reflection to inputSpan text field.
Here is an updated demo:
JSFiddle >> FullView Fiddle
I suggest for readability purposes, you break your code down into small function, it will make life easier, just sayin. So here general logic for your idea:
deleteRow = function (trID) {
// delete code goes here, remove the row
$(trID).remove();
}
manageEdit = function (tdNo) {
if ($("#edit-btn" + tdNo).html() === "Edit") {
$("#save-btn" + tdNo).show();//show save button
$("#edit-btn" + tdNo).html("Cancel");//change edit to cancle
editRow(tdNo);//call edit function
} else if ($("#edit-btn" + tdNo).html() === "Cancel") {
$("#save-btn" + tdNo).hide();//hide save button
$("#edit-btn" + tdNo).html("Edit");//change back edit button to edit
cancelEditRow(tdNo);
}
}
editRow = function (tdNo) {
$(".inputSpan" + tdNo).show();//show text input fields
$(".dataSpan" + tdNo).hide();//hide data display
}
cancelEditRow = function (tdNo) {
//looop thru 3 input fields by id last digit
for (var i = 0; i < 3; i++) {
//get input span that contain the text field
var inputSpan = $("#inputSpan" + tdNo + "-" + i);
//get the data span that contain the display data
var dataSpan = $("#dataSpan" + tdNo + "-" + i);
//text field inside inputSpan
var textField = inputSpan.find('input:text');
inputSpan.hide();//hide input span
textField.val(dataSpan.html());//take original data from display span and put it inside text field to cncle changes.
dataSpan.show();//show data span instead of edit field
}
}
saveRow = function (tdNo) {
//same as edit, but we reverse the data selection.
for (var i = 0; i < 3; i++) {
var inputSpan = $("#inputSpan" + tdNo + "-" + i);
var dataSpan = $("#dataSpan" + tdNo + "-" + i);
var textField = inputSpan.find('input:text');
inputSpan.hide();
dataSpan.html(textField.val());//take data from text field and put into dataSpan
dataSpan.show();
}
$("#edit-btn" + tdNo).html("Edit");//change text to edit
$("#save-btn" + tdNo).hide();//hide same button.
}
Here where I add the spans:
var tdCounter = 0;
$(".span4").each(function () {
var tid = val+"-"+tdCounter;
$tr.append("<td id='#mytd"+tid+"'>
<span id='inputSpan"+tid+"' class='inputSpan"+val+"' style='display:none'>
<input type='text' id='#input"+tid+"' value='"+ $(this).val() + "' /></span>
<span id='dataSpan"+tid+"' class='dataSpan"+val+"'>"+$(this).val()+"</td>");
tdCounter++;
});
Here I just append the buttons to call the functions, each button works for it's own row:
$tr.append("<td><botton id='edit-btn" + val + "' class='btn' onclick=manageEdit('" + val + "');>Edit</botton></td>");
$tr.append("<td><botton style='display:none' id='save-btn" + val + "' class='btn' onclick=saveRow('" + val + "');>Save</botton></td>");
$tr.append("<td><botton id='delete-btn" + val + "' class='btn' onclick=deleteRow('" + trID + "');>Delete</botton></td>");
Below is a sample function, it wont do everyhing you need, but it shows the jquery functions and one possibility how to do it. I only enabled editing name field, and deleting.
You would have to add other fields, + copy id data for the input.
js Fiddle
window.deleteRow = function (tar) {
$(tar).parent().remove();
}
window.editRow = function (tar) {
var row = $(tar).parent(),
cells, name;
cells = row.find("td");
name = $(cells.get(1)).text();
$(cells.get(1)).text('');
$(cells.get(1)).append('<input type="text" value="' + name + '">');
}
window.saveData = function() {
var data = {};
data.name = "some name";//get this from your input
data.email= "some email";//get this from your input
data.phone= "some phone";//get this from your input
$.get("http://yourphpsite.com", data, function(data, status) {
//data contains your server response
if (data.somepositiveservermessage) {
$("#user_notification_field").text("data saved");
$("#user_notification_field").show();
});
}