How to Validate Dynamically Added Input fields - javascript

I've the problem with div id in script. I just want to know how to control div id for using function id in another script. Here's my form:
<div class="container">
<div class="row">
<div class="col-md-7 field_wrapper">
<div data-role="dynamic-fields">
<div class="form-inline">
<div class="form-group" id="txtboxToFilter">
<label for="nip">NIP:</label>
<input type="text" class="form-control" id="UserName" onkeyup="checkname();" placeholder="Masukkan NIP" required/>
</div>
<div class="form-group">
<i class='fa fa-fw fa-plus'></i>
</div>
<span id="name_status"></span>
</div>
</div>
</div>
</div>
And here's my script:
$(document).ready(function(){
var addButton = $('.add_button'); //Add button selector
var wrapper = $('.field_wrapper'); //Input field wrapper
var fieldHTML = '<div data-role="dynamic-fields"><div class="form-inline"><div class="form-group" id="txtboxToFilter"><label for="nip">NIP:</label> <input type="text" class="form-control" id="UserName" onkeyup="checkname();" placeholder="Masukkan NIP" required/></div><div class="form-group"><label for="jabatan">Jabatan:</label><select class="form-control" id="jabatan" name="jeniskejadian" required><option value=""></option><option value="SMC / KAKANSAR">SMC / KAKANSAR</option><option value="STAFF OPERASI / KASIOPS">STAFF OPERASI / KASIOPS</option><option value="OSC / KORPOS">OSC / KORPOS</option><option value="DANTIM">DANTIM</option><option value="RESCUER">RESCUER</option><option value="STAFF KOMUNIKASI">STAFF KOMUNIKASI</option><option value="HUMAS">HUMAS</option><option value="STAFF ADMINLOG">STAFF ADMINLOG</option></select></div><div class="form-group"><i class="fa fa-fw fa-minus"></i></div><span id="name_status"></span></div></div>'; //New input field html
var x = 1; //Initial field counter is 1
$(addButton).click(function(){ //Once add button is clicked
x++; //Increment field counter
$(wrapper).append(fieldHTML); // Add field html
});
$(wrapper).on('click', '.remove_button', function(e){ //Once remove button is clicked
e.preventDefault();
$(this).parent('div').parent('div').remove(); //Remove field html
x--; //Decrement field counter
});
});
function checkname()
{
var name=document.getElementById( "UserName" ).value;
if(name)
{
$.ajax({
type: 'post',
url: 'checkdata.php',
data: {
user_name:name,
},
success: function (response) {
$( '#name_status' ).html(response);
if(response=="OK")
{
return true;
}
else
{
return false;
}
}
});
}
else
{
$( '#name_status' ).html("");
return false;
}
}
For the first time in
<div class="form-group" id="txtboxToFilter">
<label for="nip">NIP:</label>
<input type="text" class="form-control" id="UserName" onkeyup="checkname();" placeholder="Masukkan NIP" required/>
</div>
It can be used to using function checkname(), but if I would to click in
<div class="form-group">
<i class='fa fa-fw fa-plus'></i>
</div>
for adding the same input type text with function of my script $(addButton)
var fieldHTML = '<div data-role="dynamic-fields"><div class="form-inline"><div class="form-group" id="txtboxToFilter"><label for="nip">NIP:</label> <input type="text" class="form-control" id="UserName" onkeyup="checkname();" placeholder="Masukkan NIP" required/></div><div class="form-group"><i class="fa fa-fw fa-minus"></i></div><span id="name_status"></span></div></div>';
but the result is that var fieldHTML couldn't use function onkeyup checkname(). Please help me...

You should pass a reference of the element on which the inline event listener is attached to. You need to pass the this reference to the function and use the this reference to get the element.
Change you functions by adding this.
e.g.
<input type="text" class="form-control" id="UserName" onkeyup="checkname(this);" placeholder="Masukkan NIP" required/>
Also, for fieldHTML
var fieldHTML = '<div data-role="dynamic-fields"><div class="form-inline"><div class="form-group" id="txtboxToFilter"><label for="nip">NIP:</label>
<input type="text" class="form-control" id="UserName" onkeyup="checkname(this);" placeholder="Masukkan NIP" required/></div><div class="form-group"><label for="jabatan">Jabatan:</label><select class="form-control" id="jabatan" name="jeniskejadian" required><option value=""></option><option value="SMC / KAKANSAR">SMC / KAKANSAR</option><option value="STAFF OPERASI / KASIOPS">STAFF OPERASI / KASIOPS</option><option value="OSC / KORPOS">OSC / KORPOS</option><option value="DANTIM">DANTIM</option><option value="RESCUER">RESCUER</option><option value="STAFF KOMUNIKASI">STAFF KOMUNIKASI</option><option value="HUMAS">HUMAS</option><option value="STAFF ADMINLOG">STAFF ADMINLOG</option></select></div><div class="form-group"><i class="fa fa-fw fa-minus"></i></div><span id="name_status"></span></div></div>';
Function checkname(element) as :
variable element contains the element this is being used. You can access the element by using element variable.
function checkname(element)
{
var name= element.value;
console.log('Checkname '+name);
}

Related

Use data-attribute values to select form fields and autofill from MySQL

I am trying to succeed with populating dynamically generated form fields from a database via xmlhttp. First row is "static" and when I type in the SKU-field the name[] field gets the data correct from the database. When I click the "#addrow" button a new row is added and here I want to be able to type in the SKU-field and have the name[] field get data from the database. Right now what happens is that the row above gets updated when I type in the SKU-field.
I have added data-attributes for the SKU-field and name-field and also a counter so I somehow could select the field data-names and from this be able to parse the value to the right name-field in the right row?
I have tried to add a variable and see if I can get this to parse the database value to the right name-field, but it does not work:
var field = "name" + $(this).attr("data-dynid");
field.value = myObj[0];
I just need to figure out how to have the code recognize which SKU-field I am typing in (with the data-attribute counter) and from the counter select the name-field with the same counter value.
*** UPDATE ****
So I found a way to locate a form field from data-attribute and assign a value to it. Now I need to figure out how to have the code recognize the SKU field I am typing in, in order to retreive the SKU data-attribute number and use this dynamically to locate the form field to parse the data to.
var elements = document.querySelectorAll('[data-dynname="name-1"]');
elements[0].value = myObj[0];
HTML
<form method="post" action="">
<div class="row">
<div class="col-lg-12">
<div id="inputFormRow">
<div class="row">
<div class="form-group col-md-2">
<label class="form-control-label" for="sku">Varenummer</label>
<input type="text" class="form-control searchInput" name="sku[]" placeholder="Varenummer" autocomplete="off" onkeyup="GetDetail(this.value)" value="">
</div>
<div class="form-group col-md-4">
<label class="form-control-label" for="name">Navn</label>
<input type="text" class="form-control name" name="name[]" placeholder="Navn" autocomplete="off">
</div>
<div class="form-group col-md-2">
<label class="form-control-label" for="content">Tekst</label>
<input type="text" class="form-control" name="text[]" placeholder="Tekst" autocomplete="off">
</div>
<div class="form-group col-md-1">
<label class="form-control-label" for="normalprice">Normalpris</label>
<input type="text" class="form-control" name="beforeprice[]" placeholder="Normalpris" autocomplete="off">
</div>
<div class="form-group col-md-1">
<label class="form-control-label" for="offerprice">Tilbudspris</label>
<input type="text" class="form-control" name="offerprice[]" placeholder="Tilbudspris" autocomplete="off">
</div>
<div class="form-group col-md-1">
<label class="form-control-label" for="size">Størrelse</label>
<select class="form-control" name="size[]" placeholder="Størrelse" autocomplete="off">
<option value="A4" selected="">A4</option>
<option value="A5">A5</option>
<option value="A10">A10</option>
</select>
</div>
<div class="form-group col-md-1">
<label class="form-control-label" for="removeRow"> </label>
<button id="removeRow" type="button" class="form-control btn btn-danger">Fjern</button>
</div>
</div>
</div>
<div id="newRow"></div>
<button id="addRow" type="button" class="btn btn-info">Add Row</button>
</div>
</div>
</form>
Javascript
<script type="text/javascript">
// add row
var counter = 1;
$("#addRow").click(function () {
var html = '';
html += '<div id="inputFormRow">';
html += '<div class="row">';
html += '<div class="form-group col-md-2">';
html += '<input type="text" class="form-control searchInput" data-dynid ="' + counter + '" name="sku[]" placeholder="Varenummer" autocomplete="off" onkeyup="GetDetail(this.value)">';
html += '</div>';
html += '<div class="form-group col-md-4">';
html += '<input type="text" class="form-control name" data-dynname ="name-' + counter + '" name="name[]" placeholder="Navn" autocomplete="off">';
html += '</div>';
html += '<div class="form-group col-md-2">';
html += '<input type="text" class="form-control" name="text[]" placeholder="Tekst" autocomplete="off">';
html += '</div>';
html += '<div class="form-group col-md-1">';
html += '<input type="text" class="form-control" name="beforeprice[]" placeholder="Normalpris" autocomplete="off">';
html += '</div>';
html += '<div class="form-group col-md-1">';
html += '<input type="text" class="form-control" name="offerprice[]" placeholder="Tilbudspris" autocomplete="off">';
html += '</div>';
html += '<div class="form-group col-md-1">';
html += '<input type="text" class="form-control" name="size[]" placeholder="Størrelse" autocomplete="off">';
html += '</div>';
html += '<div class="form-group col-md-1">';
html += '<button type="button" class="form-control btn btn-danger removeRow">Fjern</button>';
html += '</div>';
html += '</div>';
html += '</div>';
$('#newRow').append(html);
counter++;
console.log(counter);
});
// remove row
$(document).on('click', '.removeRow', function () {
$(this).closest('#inputFormRow').remove();
});
</script>
<script>
// onkeyup event will occur when the user
// release the key and calls the function
// assigned to this event
function GetDetail(str) {
if (str.length == 0) {
document.getElementsByName("first_name")[0].value = "";
return;
}
else {
// Creates a new XMLHttpRequest object
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
// Defines a function to be called when
// the readyState property changes
if (this.readyState == 4 &&
this.status == 200) {
// Typical action to be performed
// when the document is ready
var myObj = JSON.parse(this.responseText);
// Returns the response data as a
// string and store this array in
// a variable assign the value
// received to first name input field
//var el = document.getElementsByName('name[]')[0];
//var el = document.getElementsByClassName("name");
//var r2 = console.log(el).closest("name[]");
document.getElementsByName("name[]")[0].value = myObj[0];
//r2.value = myObj[0];
}
};
// xhttp.open("GET", "filename", true);
xmlhttp.open("GET", "pages/actions/load-products.php?user_id=" + str, true);
// Sends the request to the server
xmlhttp.send();
}
}
</script>

Increment class/ID to carry function to cloned element

I have a section of code that contains a dropdown and 3 readonly input fields. The input fields are populated using javascript, this works fine on it's own using the below code -
$(document).on('change', '.unit', function(e) {
//Getting Value
var role = $('.unit option:selected').data('role');
var power = $('.unit option:selected').data('power');
var type = $('.unit option:selected').data('type');
//Setting Value
$(".role").val(role);
$(".power").val(power);
$(".type").val(type);
});
I am wanting to clone the element using this code -
//define template
var template = $('.duplicate-sections .form-section:first').clone();
//define counter
var sectionsCount = 1;
//add new section
$('body').on('click', '.addsection', function() {
//increment
sectionsCount++;
//loop through each input
var section = template.clone(true, true).find(':input').each(function(){
//set id to store the updated section number
var newId = this.id + sectionsCount;
//update for label
$(this).prev().attr('for', newId);
//update id
this.id = newId;
}).end()
//inject new section
.appendTo('.duplicate-sections');
return false;
});
//remove section
$('.duplicate-sections').on('click', '.remove', function() {
//fade out section
$(this).closest('.form-section').fadeOut(300, function(){
$(this).closest('.form-section').empty();
});
return false;
});
The cloning process works and the dropdown and the inputs are cloned. However when populating the cloned input fields it uses the values from the parent not the clone.
My html is -
<div class="duplicate-sections">
<div class="form-section">
<div class="form-group row">
<label for="inputFirstName" class="col-form-label col-sm-3 text-left text-sm-right">Unit Type</label>
<div class="col-sm-3">
<select name="unit" id="unit" class="form-control unit"><option value="">Select</option><option
data-role="HQ" data-power="4" data-type="Company Commander" value="1">Ehrwig Arellano</option>
<option data-role="HQ" data-power="6" data-type="Company Commander" value="2">Ehrwig
Arellano</option>
<option data-role="HQ" data-power="2" data-type="Tempestor Prime" value="3">Tempestor Prime</option>
</select></div>
<div class="col-sm-2 increment_controls">
<input type="text" id="role" name="role" class="form-control role" readonly placeholder="Role">
</div>
<div class="col-sm-1 increment_controls">
<input type="text" id="power" name="power" class="form-control power" readonly placeholder="PL">
</div>
<div class="col-sm-3 increment_controls">
<input type="text" id="type" name="type" class="form-control type" readonly placeholder="Type">
</div>
</div>
<label for="inputFirstName" class="col-form-label col-sm-3 text-left text-sm-right">
</label><input class="remove col-sm-9" type="button" value="Remove Unit"></input>
</div>
</div>
<label for="inputFirstName" class="col-form-label col-sm-3 text-left text-sm-right"></label>
<input class="addsection col-sm-9" type="button" value="Add Unit"></input>
The whole thing can be found here - JSFiddle
You need to update change event handler script for Unit as here you need to update input fields from the relevant form section only and not for all input fields.
see below code
$(document).on('change', '.unit', function(e) {
//Getting Value
var $option = $(this).find('option:selected');
var role = $option.data('role');
var power = $option.data('power');
var type = $option.data('type');
//Setting Value
var $parent = $(this).closest('.form-section');
$parent.find(".role").val(role);
$parent.find(".power").val(power);
$parent.find(".type").val(type);
});
Demo JSFiddle

Is it possible to change the jquery validation message to each element field of a collection?

The idea is to return an error message to each field, changing the original requied message of jquery. The way I'm doing it, returns: "The true field is required."
function addRequired() {
var container, inputs, index, input;
// Get the container element
container = $('#entityFields');
// Find its child `input` elements
inputs = container.find('input').not("#EntityWebsite, #EntitySocialMoney");
for (index = 0; index < inputs.length; ++index) {
input = inputs[index];
input.required = true;
$.validator.messages.required(input.labels[0].innerText);
}
}
$.validator.messages.required = function (label) {
var requiredMessage = "The " + label + " field is required."
return requiredMessage ;
}
My html is something like this:
<div class="modal-body">
<div id="seriesTab" class="tab-pane">
<div id="entityFields" class="form-row">
<label>Entity</label>
<input type="text" columnDivClass="col-md-6 form-group">
<label>Address:</label>
<input type="text" columnDivClass="col-md-6 form-group">
<label>Email:</label>
<input type="text" columnDivClass="col-md-6 form-group">
<label>Phone:</label>
<input type="text" columnDivClass="col-md-6 form-group">
<label>Website:</label>
<input type="text" columnDivClass="col-md-6 form-group">
<label>SocialMoney:</label>
<input type="text" columnDivClass="col-md-6 form-group">
</div>
</div>
</div>
input do not have label property. To fetch label which is before input then you can use input.previousElementSibling.innerText. So your updated code would be like below.
$.validator.messages.required(input.previousElementSibling.innerText);
Alternatively if you wish to use jquery then you can find text from previous label with $(input).prev('label').text()
$.validator.messages.required($(input).prev('label').text());

Separating the addition of different fields under the same key

Is there a way to add new fields with the same key, but independently of each other? I want both groups to be added using Enter.
Currently, fields with values are added with Enter, groups with Shift.
My actual code in form:
<div id="parent" class="list-group">
<div class="form-group form-filed horizontal">
<input name="values[]" class="input" type="text" autocomplete="off" placeholder="Enter value"
autofocus onkeypress='validate(event)' onkeydown="pressEnter(event)" required>
</div>
</div>
<div id="parent" class="list-group">
<div class="form-group form-filed horizontal">
<input name="groups[]" class="input" type="text" autocomplete="off" placeholder="Enter group"
autofocus onkeypress='validate(event)' onkeydown="pressEnter(event)" required>
</div>
</div>
Javascript:
function pressEnter(evt){
if(evt.which==13)
addDivValue();
if(evt.which==16)
addDivGroup();
}
function addDivValue(){
var newDiv = document.createElement("div");
newDiv.className= 'form-group form-filed horizontal';
var input=document.createElement("input");
input.placeholder='Enter value';
input.type='text';
input.className='input';
input.autocomplete='off';
input.name= 'values[]';
input.required=true;
input.addEventListener("keypress",validate);
input.addEventListener("keydown", pressEnter);
newDiv.appendChild(input);
var parentDiv = document.getElementById("parent");
parentDiv.appendChild(newDiv);
input.focus();
}
function addDivGroup(){
var newDiv = document.createElement("div");
newDiv.className= 'form-group form-filed horizontal';
var input=document.createElement("input");
input.placeholder='Enter group';
input.type='text';
input.className='input';
input.autocomplete='off';
input.name= 'groups[]';
input.required=true;
input.addEventListener("keypress",validate);
input.addEventListener("keydown", pressEnter);
newDiv.appendChild(input);
var parentDiv = document.getElementById("parent");
parentDiv.appendChild(newDiv);
input.focus();
}

adding input fields dynamically Jquery

I'm building this form were the user can add input field dynamically by clicking the + sign.
Then the user can remove the previously added input by clicking the - sign.
My problem is when the user removes one field, all fields are removed. I believe it depends on the position of the .field_wrapper.
I've moved the .field_wrapper to various positions but nothing seems to work. Either way the previously added input is not removed or all inputs are removed.
Can someone advise me on what I'm missing.
here is a link to a fiddle
$(document).ready(function() {
var max_fields = 10;
var add_input_button = $('.add_input_button');
var field_wrapper = $('.field_wrapper');
var new_field_html = '<input name="title[]" class="form-control form-item type="text" value="" data-label="title" />-';
var input_count = 1;
//add inputs
$(add_input_button).click(function() {
if (input_count < max_fields) {
input_count++;
$(field_wrapper).append(new_field_html);
}
});
//remove_input
$(field_wrapper).on('click', '.remove_input_button', function(e) {
e.preventDefault();
$(this).parent('div').remove();
input_count--;
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="form-horizontal">
<div class="row field_wrapper">
<label class="col-md-offset-1 col-sm-3 control-label" for="title">Title</label>
<div class="col-md-6 col-sm-9 col-10">
<input id="title" class="form-control form-item required" name="input_title[]" type="text" value="" data-label="title" />
+
</div>
</div>
</form>
The reason is because the parent('div') from the remove button is the div which holds all the content. The simple way to fix this would be to wrap the new input and remove link in its own div.
Also note that add_input_button and field_wrapper already contain jQuery objects, so you don't need to wrap them again. Try this:
$(document).ready(function() {
var max_fields = 10;
var $add_input_button = $('.add_input_button');
var $field_wrapper = $('.field_wrapper');
var new_field_html = '<div><input name="title[]" class="form-control form-item type="text" value="" data-label="title" />-</div>';
var input_count = 1;
//add inputs
$add_input_button.click(function() {
if (input_count < max_fields) {
input_count++;
$field_wrapper.append(new_field_html);
}
});
//remove_input
$field_wrapper.on('click', '.remove_input_button', function(e) {
e.preventDefault();
$(this).parent('div').remove();
input_count--;
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="form-horizontal">
<div class="row field_wrapper">
<label class="col-md-offset-1 col-sm-3 control-label" for="title">Title</label>
<div class="col-md-6 col-sm-9 col-10">
<input id="title" class="form-control form-item required" name="input_title[]" type="text" value="" data-label="title" />
+
</div>
</div>
</form>

Categories