I've got a conflict issue with a form. The idea is that I need to store the datas in the form field in a table with a local storage in Javascript, and I need to send an email simultaneously with the same button with PHP. When I try it, either the button implement the table, either it send the mail. It depends of the position of the action inside the arrows. Here is my code :
<script>
var Contacts = {
index: window.localStorage.getItem("Contacts:index"),
$table: document.getElementById("contacts-table"),
$form: document.getElementById("contacts-form"),
$button_save: document.getElementById("contacts-op-save"),
$button_discard: document.getElementById("contacts-op-discard"),
init: function() {
// initialize storage index
if (!Contacts.index) {
window.localStorage.setItem("Contacts:index", Contacts.index = 1);
}
// initialize form
Contacts.$form.reset();
Contacts.$button_discard.addEventListener("click", function(event) {
Contacts.$form.reset();
Contacts.$form.id_entry.value = 0;
}, true);
Contacts.$form.addEventListener("submit", function(event) {
var entry = {
id: parseInt(this.id_entry.value),
first_name: this.first_name.value,
last_name: this.last_name.value,
company: this.company.value,
address: this.address.value,
city: this.city.value,
zip: this.zip.value,
state: this.state.value,
country: this.country.value,
phone: this.phone.value,
email: this.email.value,
nature_of_contact: this.nature_of_contact.value,
};
if (entry.id == 0) { // add
Contacts.storeAdd(entry);
Contacts.tableAdd(entry);
}
else { // edit
Contacts.storeEdit(entry);
Contacts.tableEdit(entry);
}
this.reset();
this.id_entry.value = 0;
event.preventDefault();
}, true);
// initialize table
if (window.localStorage.length - 1) {
var contacts_list = [], i, key;
for (i = 0; i < window.localStorage.length; i++) {
key = window.localStorage.key(i);
if (/Contacts:\d+/.test(key)) {
contacts_list.push(JSON.parse(window.localStorage.getItem(key)));
}
}
if (contacts_list.length) {
contacts_list
.sort(function(a, b) {
return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
})
.forEach(Contacts.tableAdd);
}
}
Contacts.$table.addEventListener("click", function(event) {
var op = event.target.getAttribute("data-op");
if (/edit|remove/.test(op)) {
var entry = JSON.parse(window.localStorage.getItem("Contacts:"+ event.target.getAttribute("data-id")));
if (op == "edit") {
Contacts.$form.first_name.value = entry.first_name;
Contacts.$form.last_name.value = entry.last_name;
Contacts.$form.company.value = entry.company;
Contacts.$form.address.value = entry.address;
Contacts.$form.city.value = entry.city;
Contacts.$form.zip.value = entry.zip;
Contacts.$form.state.value = entry.state;
Contacts.$form.country.value = entry.country;
Contacts.$form.phone.value = entry.phone;
Contacts.$form.email.value = entry.email;
Contacts.$form.nature_of_contact.value = entry.nature_of_contact;
Contacts.$form.id_entry.value = entry.id;
}
else if (op == "remove") {
if (confirm('Are you sure you want to remove "'+ entry.first_name +' '+ entry.last_name +'" from your contacts?')) {
Contacts.storeRemove(entry);
Contacts.tableRemove(entry);
}
}
event.preventDefault();
}
}, true);
},
storeAdd: function(entry) {
entry.id = Contacts.index;
window.localStorage.setItem("Contacts:index", ++Contacts.index);
window.localStorage.setItem("Contacts:"+ entry.id, JSON.stringify(entry));
},
storeEdit: function(entry) {
window.localStorage.setItem("Contacts:"+ entry.id, JSON.stringify(entry));
},
storeRemove: function(entry) {
window.localStorage.removeItem("Contacts:"+ entry.id);
},
tableAdd: function(entry) {
var $tr = document.createElement("tr"), $td, key;
for (key in entry) {
if (entry.hasOwnProperty(key)) {
$td = document.createElement("td");
$td.appendChild(document.createTextNode(entry[key]));
$tr.appendChild($td);
}
}
$td = document.createElement("td");
$td.innerHTML = '<a data-op="edit" data-id="'+ entry.id +'">Edit</a> | <a data-op="remove" data-id="'+ entry.id +'">Remove</a>';
$tr.appendChild($td);
$tr.setAttribute("id", "entry-"+ entry.id);
Contacts.$table.appendChild($tr);
},
tableEdit: function(entry) {
var $tr = document.getElementById("entry-"+ entry.id), $td, key;
$tr.innerHTML = "";
for (key in entry) {
if (entry.hasOwnProperty(key)) {
$td = document.createElement("td");
$td.appendChild(document.createTextNode(entry[key]));
$tr.appendChild($td);
}
}
$td = document.createElement("td");
$td.innerHTML = '<a data-op="edit" data-id="'+ entry.id +'">Edit</a> | <a data-op="remove" data-id="'+ entry.id +'">Remove</a>';
$tr.appendChild($td);
},
tableRemove: function(entry) {
Contacts.$table.removeChild(document.getElementById("entry-"+ entry.id));
}
};
Contacts.init();
</script>
<form action="mailer.php" method="post" class="onerow">
<label class="col6">First name:
<input type="text" name="first_name" />
</label>
<label class="col6">Last name:
<input type="text" name="last_name" />
</label>
<label class="col6">Company:
<input type="text" name="company" />
</label>
<label class="col6">Address:
<input type="text" name="address" />
</label>
<label class="col6">City:
<input type="text" name="city" />
</label>
<label class="col6">Postal/zip code:
<input type="text" name="zip" />
</label>
<label class="col6">State/province:
<input type="text" name="state" />
</label>
<label class="col6">Country:
<input type="text" name="country" />
</label>
<label class="col6">Phone number:
<input type="text" name="phone" />
</label>
<label class="col6">Email:
<input type="text" name="email" />
</label>
<label class="col12">Why are you looking for our solutions ?
<SELECT name="nature_of_contact" size="1">
<OPTION>I'm a distributor and I want to sell your products in my country.
<OPTION>I'm a beautician I want to buy a product.
<OPTION>I'm a doctor.
<OPTION>I'm a distributor.
</SELECT>
</label>
<div class="col12">
<input type="button" id="contacts-op-discard" value="Discard" />
<input type="submit" id="contacts-op-save" value="Save" />
<input type="hidden" name="id_entry" value="0" />
</div>
</form>
</div>
<div></div>
<div id="tablecontrol" class="col12">
<h1>Contacts</h1>
<table id="contacts-table">
<tr id="contacts-head">
<th>ID</th>
<th>First name</th>
<th>Last name</th>
<th>Company</th>
<th>Address</th>
<th>City</th>
<th>Postal/Zip</th>
<th>State/province</th>
<th>Country</th>
<th>Phone number</th>
<th>Email</th>
<th>Kind of prospect</th>
<th>Actions</th>
</tr>
</table>
</div>
</div>
See JSFIDDLE
One way would be:
Change the submit button from type 'submit' to 'button' and add the event onClick()to it.
Create a function -let's say readFromdata()- that reads the values from your form. Store the data into a container.
Create a function -let's say sendFromdata()- that sends the data to your php script. Hint: Ajax would be your friend. Configure your Ajax so, that the data will be send asyncrosly.
Create a function -let's say printFOverview()- that extends your html table, for the displaying the result.
Call sendFromdata() and printFOverview() within the function readFromdata() and pass the data container to these methods.
Add the call readFromdata() to the attribute onClick().
You could do the following:
Add an event.preventDefault() to your handler
Then store things in localStorage
If things are stored submit the form with Contacts.$form.submit();
EDIT
Change the event handler from submit to click and remove it from the form to add it to the Contacts.$button_save button and add a preventDefault() just after.
As you changed the event handler from the form to the button you need to change the form values from this to Contacts.$form because this was in the scope of the form which is not the case anymore.
Contacts.$button_save.addEventListener("click", function(event) {
event.preventDefault();
var entry = {
id: parseInt(Contacts.$form.id_entry.value),
first_name: Contacts.$form.first_name.value,
last_name: Contacts.$form.last_name.value,
// and so on
Remove the input type="submit" and create a normal button instead:
<button id="contacts-op-save">Save</button>
Then you could submit the form after storing in storeAdd / storeEdit functions as said with Contacts.$form.submit();.
storeAdd: function(entry) {
entry.id = Contacts.index;
window.localStorage.setItem("Contacts:index", ++Contacts.index);
window.localStorage.setItem("Contacts:"+ entry.id, JSON.stringify(entry));
Contacts.$form.submit();
},
storeEdit: function(entry) {
window.localStorage.setItem("Contacts:"+ entry.id, JSON.stringify(entry));
Contacts.$form.submit();
},
storeRemove: function(entry) {
window.localStorage.removeItem("Contacts:"+ entry.id);
// eventually here too?
Contacts.$form.submit();
},
Also you call the form element by its id , but the form has no id assigned.
$form: document.getElementById("contacts-form")
So give your form that ID:
<form id="contacts-form" action="mailer.php" method="post" class="onerow">
Related
I have seen this method of serializing a form to JSON and it's working fine. My question is: How can I achieve this with pure JavaScript, without using any jQuery code? I am sorry if the question is dumb, but I'm still learning so if anyone can help me, I'll be grateful.
(function ($) {
$.fn.serializeFormJSON = function () {
var objects = {};
var anArray = this.serializeArray();
$.each(anArray, function () {
if (objects[this.name]) {
if (!objects[this.name].push) {
objects[this.name] = [objects[this.name]];
}
objects[this.name].push(this.value || '');
} else {
objects[this.name] = this.value || '';
}
});
return objects;
};
})(jQuery);
$('form').submit(function (e) {
e.preventDefault();
var data = $(this).serializeFormJSON();
console.log(data);
/* Object
email: "value"
name: "value"
password: "value"
*/
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post">
<div>
<label for="name">Name</label>
<input type="text" name="name" id="name" />
</div>
<div>
<label for="email">Email</label>
<input type="text" name="email" id="email" />
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" id="password" />
</div>
<p>
<input type="submit" value="Send" />
</p>
</form>
P.S.
Also in jQuery is this the right way to send multiple JSON objects from user input as One String, because I am searching for a way to do that?
You can try something like this:
function formToJson(){
var formElement = document.getElementsByTagName("form")[0],
inputElements = formElement.getElementsByTagName("input"),
jsonObject = {};
for(var i = 0; i < inputElements.length; i++){
var inputElement = inputElements[i];
jsonObject[inputElement.name] = inputElement.value;
}
return JSON.stringify(jsonObject);
}
This solution works only if you have a single form on the page, to make it more general the function could e.g. take the form element as an argument.
You can use Array.reduce, something like
// get array of all fields and/or selects (except the button)
const getFields = () => Array.from(document.querySelectorAll("input, select"))
.filter(field => field.type.toLowerCase() !== "button");
// get id, name or create random id from field properties
const getKey = field => field.name
|| field.id
|| `unknown-${Math.floor(1000 * Math.random()).toString(16)}`;
// get data, simple object
const getFormData = () => getFields()
.reduce( (f2o, field) => ({...f2o, [getKey(field)]: field.value}), {} );
// log the result
const logResult = txt => document.querySelector("#result").textContent = txt;
// get data, array of field objects
const getMoreFormData = () => getFields()
.reduce( (f2o, field) =>
f2o.concat({
id: field.id || "no id",
name: field.name || "no name",
idGenerated: getKey(field),
type: field.type,
value: field.value }
),
[] );
// handling for buttons
document.addEventListener("click", evt => {
if (evt.target.nodeName.toLowerCase() === "button") {
console.clear();
logResult(/simple/.test(evt.target.textContent)
? JSON.stringify(getFormData(), null, " ")
: JSON.stringify(getMoreFormData(), null, " ")
);
}
} );
<form action="#" method="post">
<div>
<label for="name">Name</label>
<input type="text" name="name" id="name" value="Pete"/>
</div>
<div>
<label for="email">Email</label>
<input type="text" name="email" id="email" value="pete#here.com"/>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" id="password" />
</div>
<div>
<label>Field without name or id</label>
<input type="number" value="12345" />
</div>
</form>
<p>
<button>Data simple object</button> <button>Data fields array</button>
</p>
<pre id="result"></pre>
Remember that for checkboxes, value attribute can be either on or off string. This is unwanted. Here is my solution, based on this codepen.
let json = Array.from(form.querySelectorAll('input, select, textarea'))
.filter(element => element.name)
.reduce((json, element) => {
json[element.name] = element.type === 'checkbox' ? element.checked : element.value;
return json;
}, {});
OR
let json = {};
Array.from(form.querySelectorAll('input, select, textarea'))
.filter(element => element.name)
.forEach(element => {
json[element.name] = element.type === 'checkbox' ? element.checked : element.value;
});
OR (with typescript)
export type FormJson = {[key: string]: boolean | string};
export const toJson = (form: HTMLFormElement): FormJson =>
Array.from(form.querySelectorAll<HTMLFormElement>('input, select, textarea'))
.filter(element => element.name)
.reduce<FormJson>((json, element) => {
json[element.name] = element.type === 'checkbox' ? element.checked : element.value;
return json;
}, {});
To serialize your form you can do this (note that I added an onsubmit in the form tag):
HTML and JavaScript:
function serializeForm(e) {
e.preventDefault(); // prevent the page to reload
let form = e.target; // get the form itself
let data = new FormData(form); // serialize input names and values
let objSerializedForm = {}; // creating a new object
for (let [name, value] of data) { // iterating the FormData data
objSerializedForm[name] = value; // appending names and values to obj
}
console.log(objSerializedForm);
}
<form action="#" method="post" onsubmit="serializeForm(event)">
<div>
<label for="name">Name</label>
<input type="text" name="name" id="name" />
</div>
<div>
<label for="email">Email</label>
<input type="text" name="email" id="email" />
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" id="password" />
</div>
<p>
<input type="submit" value="Send" />
</p>
</form>
Than you can do whatever you want with your objSerializedForm, getting each value by calling objSerializedForm.name.
I want to add: the name, phone and mail of the user in the localStorage using the method: addContact() and with the data that is there in localStorage, I create the table using the method show().
Also does not happen delete the contact, I'm trying to do with the method: deleteContact(e).
When I add contact I receive the following error: Uncaught TypeError: Cannot read property 'value' of undefined
When I deleting I receive the following error: Uncaught TypeError: Cannot read property 'splice' of undefined
Help me fix that
//Product Creation Class
class LocalStorage {
constructor(name, phone, email) {
this.name = name;
this.phone = phone;
this.email = email;
}
}
// Сlass where products are recorded
class Book {
constructor() {
this.products = [];
this.name = document.getElementById("name");
this.phone = document.getElementById("phone");
this.email = document.getElementById("email");
this.buttAdd = document.getElementById("add");
this.book = document.getElementById("addBook");
}
//method for adding a product
addContact() {
let isNull = this.name.value != '' && this.phone.value != '' && this.email.value != '';
if (isNull) {
let obj = new LocalStorage(this.name.value, this.phone.value, this.email.value);
this.products.push(obj);
localStorage['addbook'] = JSON.stringify(this.products);
this.show();
}
}
//method for remove product by name
deleteContact(e) {
if (e.target.className === "delbutton") {
let remID = e.target.getAttribute('data-id');
this.products.splice(remID, 1);
localStorage['addbook'] = JSON.stringify(this.products);
this.show();
}
}
// method to draw the table with product property (
// name, phone, email)
show() {
if (localStorage['addbook'] === undefined) {
localStorage['addbook'] = '';
} else {
this.products = JSON.parse(localStorage['addbook']);
this.book.innerHTML = '';
for (let e in this.products) {
let table = ` <table id="shop" class="entry">
<tr>
<th>Name:</th>
<th id="filter">Phone:</th>
<th>Email:</th>
<th class="dels"></th>
</tr>
<tbody>
<tr class="data">
<td>${this.products[e].name}</td>
<td>${this.products[e].phone}</td>
<td>${this.products[e].email}</td>
<td class="del">Delete</td>
</tr>
</tbody>
</table>`;
this.book.innerHTML += table;
}
}
}
OperationsWithContacts() {
// add new product by click
this.buttAdd.addEventListener('click', this.addContact);
// delete product by name after click
this.book.addEventListener('click', this.deleteContact);
console.log(this.products);
}
}
let shop = new Book();
shop.show();
shop.OperationsWithContacts();
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form name="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="phone">Price of product</label>
<input type="number" id="phone" class="input-product">
<label for="email">Count of product</label>
<input type="text" id="email" class="input-product">
<button id="add" type="button">Add</button>
</form>
</div>
<div class="product-table">
<h2>Address book</h2>
<div id="delete-form">
<label for="name-delete">Search product by name</label>
<input type="text" id="name-delete" class="input-delete">
</div>
<div id="addBook"></div>
</div>
</div>
enter code here
The obivous issue I see is that this in both your functions addContact() and deleteContact() represents a button-HTML-Element and not the class you think it does.
Just change the code a bit and you will see:
//method for adding a product
addContact() {
console.log('addContact()', this);
let isNull = this.name.value != '' && this.phone.value != '' && this.email.value != '';
if (isNull) {
let obj = new LocalStorage(this.name.value, this.phone.value, this.email.value);
this.products.push(obj);
localStorage['addbook'] = JSON.stringify(this.products);
this.show();
}
}
So you might want to change your bind from:
document.querySelector('#add').addEventListener('click', this.addContact);
to
document.querySelector('#add').addEventListener('click', this.addContact.bind(this));
to properly reuse the this shortcut.
Edit:
//Product Creation Class
//REM: Not the best name choice here.. localStorage <> LocalStorage
class LocalStorage{
constructor(name, phone, email){
this.name = name;
this.phone = phone;
this.email = email
}
};
//Сlass where products are recorded
class Book{
constructor(){
this.products = [];
this.name = document.getElementById("name");
this.phone = document.getElementById("phone");
this.email = document.getElementById("email");
this.buttAdd = document.getElementById("add");
this.book = document.getElementById("addBook")
};
//method for adding a product
addContact(){
let isNull = this.name.value != '' && this.phone.value != '' && this.email.value != '';
if(isNull){
let obj = new LocalStorage(this.name.value, this.phone.value, this.email.value);
this.products.push(obj);
localStorage['addbook'] = JSON.stringify(this.products);
this.show();
}
};
//method for remove product by name
deleteContact(e) {
if(e.target.className === "delbutton"){
let remID = e.target.getAttribute('data-id');
this.products.splice(remID, 1);
localStorage['addbook'] = JSON.stringify(this.products);
this.show();
}
};
//method to draw the table with product property (
//name, phone, email)
show(){
if(localStorage['addbook'] === undefined) {
//REM: An empty string is no valid JSON to be serialised
localStorage['addbook'] = '[]'
}
else{
this.products = JSON.parse(localStorage['addbook']);
this.book.innerHTML = '';
for(let e in this.products){
let table = ` <table id="shop" class="entry">
<tr>
<th>Name:</th>
<th id="filter">Phone:</th>
<th>Email:</th>
<th class="dels"></th>
</tr>
<tbody>
<tr class="data">
<td>${this.products[e].name}</td>
<td>${this.products[e].phone}</td>
<td>${this.products[e].email}</td>
<td class="del">Delete</td>
</tr>
</tbody>
</table>`;
this.book.innerHTML += table;
}
}
};
OperationsWithContacts(){
// add new product by click
this.buttAdd.addEventListener('click', this.addContact.bind(this));
// delete product by name after click
this.book.addEventListener('click', this.deleteContact.bind(this));
console.log(this.products);
}
};
;window.onload = function(){
let shop = new Book();
shop.show();
shop.OperationsWithContacts()
};
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form name="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="phone">Price of product</label>
<input type="number" id="phone" class="input-product">
<label for="email">Count of product</label>
<input type="text" id="email" class="input-product">
<button id="add" type="button">Add</button>
</form>
</div>
<div class="product-table">
<h2>Address book</h2>
<div id="delete-form">
<label for="name-delete">Search product by name</label>
<input type="text" id="name-delete" class="input-delete">
</div>
<div id="addBook"></div>
</div>
</div>
So, let's say I have an HTML form like this:
<form id="myForm">
<input type="text" name="dummy">
<input type="text" name="people[0][first_name]" value="John">
<input type="text" name="people[0][last_name]" value="Doe">
<input type="text" name="people[1][first_name]" value="Jane">
<input type="text" name="people[1][last_name]" value="Smith">
</form>
And I want to get a JavaScript array that matches the values of real. For example:
// If there was a sweet function for this...
var people = getFormDataByInputName( 'people' );
// Value of `people` is...
// [
// {
// 'first_name' : 'John',
// 'last_name' : 'Doe'
// },
// {
// 'first_name' : 'Jane',
// 'last_name' : 'Smith'
// }
// ]
Is there any easy way of doing that for just a specific form item (in this case, people)? Or would I have to serialize the entire form an then just extract the element I want?
I also thought of potentially using the following approach:
var formData = new FormData( document.querySelector( '#myForm' ) );
var people = formData.get( 'people' );
But that doesn't appear to work; people is just null after that.
You could do this with plain js using reduce method and return each person is one object.
const form = document.querySelectorAll('#myForm input');
const data = [...form].reduce(function(r, e) {
const [i, prop] = e.name.split(/\[(.*?)\]/g).slice(1).filter(Boolean)
if (!r[i]) r[i] = {}
r[i][prop] = e.value
return r;
}, [])
console.log(data)
<form id="myForm">
<input type="text" name="dummy">
<input type="text" name="people[0][first_name]" value="John">
<input type="text" name="people[0][last_name]" value="Doe">
<input type="text" name="people[1][first_name]" value="Jane">
<input type="text" name="people[1][last_name]" value="Smith">
</form>
function getObject(name, key) {
if(key.includes(name)) {
var splitStr = key.split(/\[|\]/g);
return {
index: splitStr[1],
key: splitStr[3],
}
}
return null;
}
function getFormDataByInputName(name) {
var formData = new FormData( document.querySelector('#myForm'));
var results = [];
for (var key of formData.keys()) {
var obj = getObject(name, key);
if (obj) {
if (results[obj.index]) results[obj.index][obj.key] = formData.get(key);
else results[obj.index] = { [obj.key]: formData.get(key) };
}
}
return results;
}
var people = getFormDataByInputName('people');
console.log(people);
<form id="myForm">
<input type="text" name="dummy">
<input type="text" name="people[0][first_name]" value="John">
<input type="text" name="people[0][last_name]" value="Doe">
<input type="text" name="people[1][first_name]" value="Jane">
<input type="text" name="people[1][last_name]" value="Smith">
</form>
Your code won't work because to HTML/JS name is just a string that it sends to the server when the form is submitted (the name in the name/value pairs). You might think it is arrays, but HTML/JS doesn't.
So no one-liner to get the job done. Try this: In your HTML, add <div class="name"> ...
(UPDATE: thanks for the idea, #Nenad, I've never tried one of these snippets)
var people = [];
$('.name').each(function() {
people.push({
first_name: $('input:nth-child(1)', this).val(),
last_name: $('input:nth-child(2)', this).val()
});
});
console.log(people);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="myForm">
<input type="text" name="dummy">
<div class="name">
<input type="text" value="John">
<input type="text" value="Doe">
</div>
<div class="name">
<input type="text" value="Jane">
<input type="text" value="Smith">
</div>
</form>
Use CSS attribute prefix selector, such as
form.querySelectorAll('[name^="people[]"]')
You can use a for-loop to get all peoples, as such
const MAX_PEOPLES = 2;
const list = [];
for (i = 0; i <= MAX_PEOPLES; i++) {
const eles = form.querySelectorAll(`[name^="people[${i}]`);
if (eles.length !== 2)
break;
list.push({
first_name: eles[0].value,
last_name: eles[1].value
});
}
that yields
[
{
"first_name":"John",
"last_name":"Doe"
},
{
"first_name":"Jane",
"last_name":"Smith"
}
]
I have used the struts json plugin and tried to convert the form data to json format to submit by ajax.
I have two cases in the HTML
<form>
<input type="text" name="user.name" value="Tom"></p>
<input type="text" name="user.location" value="China"></p>
<input type="text" name="user.data[0].id" value="993"></p>
<input type="text" name="user.data[0].accountId" value="123"></p>
<input type="text" name="user.data[1].id" value="222"></p>
<input type="text" name="user.data[1].accountId" value="333"></p>
</form>
What I expected is to convert it to the json structure:
{
user : {
name: "Tom",
location : "China",
data: [
{
id : 993,
accountId : 123
},
{
id : 222,
accountId : 333
}
]
}
}
I know how to declare the json data and declare the attributes one by one.
I would like to have the better way to make each form to be in json format using simple way rather than declaring the parameter one by one in json format.
Appreciate for any suggestion or advice. Thank you.
Provided your form is exactly like that
Using a plain JS approach
<form class="userform">
<input type="text" class="username" value="Tom"></p>
<input type="text" class="userlocation" value="China"></p>
<input type="text" class="userid" value="993"></p>
<input type="text" class="useraccountid" value="123"></p>
<input type="text" class="userid2" value="222"></p>
<input type="text" class="useraccountid2" value="333"></p>
</form>
Then assign the values to the object
var frm = document.getElementsByClassName('userform');
//initialize blank object and keys
var user = {},
user.name = "",
user.location = "",
user.data = [];
//get all child input elements
for(var i = 0; i < frm.length; i++){
var uname = frm[i].getElementsByClassName('username')[0];
var uloc = frm[i].getElementsByClassName('userlocation')[0];
var uid = frm[i].getElementsByClassName('userid')[0];
var uaccid = frm[i].getElementsByClassName('useraccountid')[0];
var uid = frm[i].getElementsByClassName('userid2')[0];
var uaccid = frm[i].getElementsByClassName('useraccountid2')[0];
//assign values to object here
user[name] = {}; //assigning a parent property here, the name for example.
user[name].name = uname.value;
user[name].location = uloc.value;
user[name].data.push({
'id': uid.value
'accountId': uaccid.value
});
user[name].data.push({
'id': uid2.value
'accountId': uaccid2.value
});
}
JSON.stringify(user); //convert to JSON (or ignore if you want a plain object)
Output would be this in JSON format
{
user :{
Tom: {
name: "Tom",
data: [
{
id : 993,
accountId : 123
},
{
id : 222,
accountId : 333
}
]
},
Jerry: {
//more data
},
Courage: {
//more data
}
}
}
Hope this helps
If your input fields are many, like id3, accountid3, 4, 5, 6. You have to loop through the classes that you assign to these two repetitive fields
Here you go with a solution using jQuery https://jsfiddle.net/pnz8zrLx/2/
var json = {};
$('button').click(function(){
$('form').each(function(i){
json["user" + i] = {};
json["user" + i].data = [];
var tempJSON = {};
$('form:nth-child(' + (i+1) + ') input[type="text"]').each(function(){
if($(this).attr('name') === 'name' || $(this).attr('name') === 'location'){
json["user" + i][$(this).attr('name')] = $(this).val();
} else {
tempJSON[$(this).attr('name')] = $(this).val();
if(tempJSON != {} && $(this).attr('name') === 'accountId'){
json["user" + i].data.push(tempJSON);
tempJSON = {};
}
}
});
});
console.log(json);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" name="name" value="Tom">
<input type="text" name="location" value="China">
<input type="text" name="id" value="993">
<input type="text" name="accountId" value="123">
<input type="text" name="id" value="222">
<input type="text" name="accountId" value="333">
</form>
<form>
<input type="text" name="name" value="Test">
<input type="text" name="location" value="Test112">
<input type="text" name="id" value="22">
<input type="text" name="accountId" value="78">
<input type="text" name="id" value="00">
<input type="text" name="accountId" value="44">
</form>
<button>
Submit
</button>
Hope this will help you.
<tr ng-repeat="labour in labourdata">
<td>{{$index+1}}</td>
<td data-title="'Mobile No'" sortable="Mobile no">
<input type="text" class="form-control" name="mobile" id="mobile" ng-model="labour.mobile" value={{labour.mobile}} placeholder="Enter Aadhaar" typeahead="mobile.Mobileid for mobile in MobileArray" ng-blur="change_mobile(mobile)" >
</td>
<td data-title="'NAME'" sortable="NAME">
<input type="hidden" ng-model="labour.lid" id="lid" name="lid" />
<input type="text" class="form-control" id="name" ng-model="labour.name" placeholder="Name" readonly>
</td>
<td>
<input type="button" ng-click="addFormField(mobile)" class="btn btn-default" value="Add " />
</td>
</tr>
Here is Js code
//Get Mobile Number
$scope.labourdata = [{}];
$scope.MobileArray = [];
$http({method: 'GET',url: 'get-num.php',labourdata: { applicationId: 3 }})
.success(function (labourdata)
{
$scope.MobileArray = labourdata;
});
// Change Mobile number
$scope.change_mobile=function(mobile)
{
var j=-1;
var mobile = "";
for (var i = 0; i < $scope.labourdata.length; i++)
{
j++;
mobile = $scope.labourdata[i]["mobile"];
}
$http.post('get-labour-details.php', {'selectedmobile': mobile})
.success(function (data, status, headers, config)
{
var comArr = eval($scope.labourdata);
comArr[j].lid = data[0]["LabourId"];
comArr[j].name = data[0]["Name"];
});
}
//Add one more Field
$scope.labourdata = [{}];
$scope.addFormField = function(mobile)
{
var mobile = "";
var found = $scope.labourdata.reduce(function(previous, i)
{
if (mobile === i) return true;
return previous;
}, false);
if (found){
alert('already taken.');
}
else
{
alert('ok');
$scope.labourdata.push({});
}
}
Unable to validate input field in ng-repeat.
if we given Mobile No input filed as a '9999999999'. it displaying 'XXX' name in NAME input field.
When i click on Add button, the next row appears. Problem is while adding one more time Mobile No input filed as a '9999999999'.
it should be alert as a it's already taken. because i already selected Mobile no '9999999999' previously.
How to validate input data in iteration while clicking Add button.
Is there is any way to solve this problem?