Dealing with multiple forms without unique id:s? - ecmascript-6

I'm rendering mulitple forms like this:
trait = (name, dice, mod) => {
return `
<tr><form action="#" onsubmit="renderRoll()">
<td><label>${name}</label></td>
<td><input type="text" name="dice" value="${dice}"></td>
<td><input type="text" name="mod" value="${mod}"></td>
<td><input type="submit" value="Slå" name="roll" ></td>
</form></tr>`;
};
document.getElementById('content').innerHTML += trait;
The forms don't have unique id:s and there are always more than one in the DOM. How can I run renderRoll() and access the values of the form that was triggered?

You have to pass an argument inside function "renderRoll()" to work.
<form action="#" onsubmit="renderRoll(event)">
function renderRoll(event) {
//here is your target...
var target = event.target;
alert(target.innerHTML);
}

I suggest you use a unique id as a name for the form element like as below:
 
const trait = (id, name, dice, mod) => {
return `
<tr><form name="${id}" action="#" onsubmit="renderRoll">
<td><label>${name}</label></td>
<td><input type="text" name="dice" value="${dice}"></td>
<td><input type="text" name="mod" value="${mod}"></td>
<td><input type="submit" value="Slå" name="roll" ></td>
</form></tr>`;
};
document.getElementById('content').innerHTML += trait("form", "test", "test", "test");
And use form data whenever form has triggered:
function renderRoll() {
let data = document.forms.namedItem("form").elements;
data = [...data].map(({name, value}) => ({name, value}));
console.log(data)
}
I hope it will be useful.

Related

Problem post data with Angular in MongoDB

i'm trying to do a crud in Angular 14.
All works fine, but when i put in my form an input to update my data, this crashed.
That input are the first of my form.
This is my component.html
<form>
<input type="hidden" name="_id" [(ngModel)]="orderService.selectedOrder._id">
<input id="client" type="text" class="form-control" name="client" placeholder="Client name" [(ngModel)]="orderService.selectedOrder.client"/>
<input id="client" type="text" class="form-control" name="price" placeholder="Price" [(ngModel)]="orderService.selectedOrder.price"/>
</form>
This is my component.ts
addOrder(form: NgForm){
if(form.value._id){
this.orderService.updateOrder(form.value).subscribe(
(res) => {
//console.log(res);
form.reset();
this.getOrders();
},
err => console.log(err)
);
}else{
// Here i want to skip form.value._id in createOrder()
this.orderService.createOrder(form.value).subscribe(
res => {
form.reset();
this.getOrders();
},
err => console.log(err)
)
}
}
And finally my orderService
createOrder(order: Order){
return this.http.post(this.URL_API, order);
}
updateOrder(order: Order){
return this.http.put(`${this.URL_API}/${order._id}`, order);
}
When i remove the hidden input, the problem of create new data are solved, but i cant update data.
I think the problem is when I create a new order, it takes the value of the _id input value from the createOrder method. I don't know how to remove this value when making the post from my method.

Stop chrome auto filling / suggesting form fields by id

Ok so...like many other posts this is driving me nuts. Chrome is continually offering autocomplete suggestions for fields that I would rather it not be on. It, along with the soft keyboard take up the whole page which blocks the view for the user / the form is not intended to fill our the users data but rather a new address that would be previously unknown.
So far I've got these both on
<form autocomplete="off">
and
<input autocomplete="randomstringxxx">
Their effect is noticed and chrome is no longer filling the whole form - but it STILL wants to suggest single field suggestions for each element in my form.
I've finally realised that its now picking up the id/name fields from my form elements.
i.e the below will give me a list of names I have used before.
<input id="contact_name" name="contact_name">
Can anyone suggest a way to stop this without renaming the elements? They are tied to fields in my database and ideally I would not have to manually rename and match up these together.
example -
https://jsfiddle.net/drsx4w1e/
with random strings as autocomplete element attribute - STILL AUTOCOMPLETING
https://jsfiddle.net/drsx4w1e/1/
with "off" as autocomplete attribute. - STILL AUTOCOMPLETING
https://jsfiddle.net/6bgoj23d/1/
example no autocomplete when labels / ids/ name attr are removed - NOT AUTOCOMPLETING
example
I know this isn't ideal because it changes the name of the inputs but it only does it temporarily. Changing the name attribute is the only way I found that completely removes the autocomplete.
This solution is all in JS and HTML but I think it would be better if it was implemented with a server side language such as PHP or Java.
I found autocomplete="none" works best for chrome but it doesn't fully turn off auto complete.
How it works
So, on page load this solution adds a string of random characters to each input name.
eg. 'delivery_contact_name' becomes 'delivery_contact_nameI5NTE'
When the form is submitted it calls a function (submission()) which removes the random character that were added. So the submitted form data will have the original names.
See solution below:
<html>
<body>
<form autocomplete="none" id="account_form" method="post" action="" onsubmit="return submission();">
<div class="my-2">
<label for="delivery_contact_name" class="">*</label>
<input autocomplete="none" class="form-control" id="delivery_contact_name" maxlength="200" minlength="2" name="delivery_contact_name" required="" type="text" value="">
</div>
<div class="my-2">
<label for="delivery_telephone" class="">Telephone*</label>
<input autocomplete="none" class="form-control" id="delivery_telephone" maxlength="200" minlength="8" name="delivery_telephone" required="" type="tel" value="">
</div>
<div class="my-2">
<label for="delivery_address_1" class="">Delivery Address*</label>
<input autocomplete="none" class="form-control" id="delivery_address_1" maxlength="50" minlength="2" name="delivery_address_1" required="" type="text" value="">
</div>
<div class="my-2">
<label for="delivery_address_2" class="">Delivery Address*</label>
<input autocomplete="none" class="form-control" id="delivery_address_2" maxlength="50" minlength="2" name="delivery_address_2" required="" type="text" value="">
</div>
<div class="my-2">
<label for="delivery_address_3" class="">Delivery Address</label>
<input autocomplete="none" class="form-control" id="delivery_address_3" name="delivery_address_3" type="text" value="">
</div>
<div class="my-2">
<label for="delivery_address_4" class="">Delivery Address</label>
<input autocomplete="none" class="form-control" id="delivery_address_4" name="delivery_address_4" type="text" value="">
</div>
<div class="my-2">
<label for="delivery_address_postcode" class="">Delivery Postcode*</label>
<input autocomplete="none" class="form-control" id="delivery_address_postcode" maxlength="10" minlength="6" name="delivery_address_postcode" required="" type="text" value="">
</div>
<input type="submit" name="submit" value="Send">
</form>
</body>
<script>
//generate a random string to append to the names
const autocompleteString = btoa(Math.random().toString()).substr(10, 5);
//get all the inputs in the form
const inputs = document.querySelectorAll("input");
//make sure script calls function after page load
document.addEventListener("DOMContentLoaded", function(){
changeInputNames();
});
//add random characters to input names
function changeInputNames(){
for (var i = 0; i < inputs.length; i++) {
inputs[i].setAttribute("name", inputs[i].getAttribute("name")+autocompleteString);
}
}
//remove the random characters from input names
function changeInputNamesBack(){
for (var i = 0; i < inputs.length; i++) {
inputs[i].setAttribute("name", inputs[i].getAttribute("name").replace(autocompleteString, ''));
}
}
function submission(){
let valid = true;
//do any additional form validation here
if(valid){
changeInputNamesBack();
}
return valid;
}
</script>
</html>
Thanks to #rydog for his help. I've changed it into a function that I've put into a my js file as I didn't want to manually add to each page / fire on every page - I have also added the submit event handler with js rather than adding to the on submit of the form.
GREAT SOLUTION by Rydog
function stop_autofill() {
//generate a random string to append to the names
this.autocompleteString = btoa(Math.random().toString()).substr(10, 5);
this.add_submit_handlers = () => {
document.querySelectorAll("form").forEach(value => {
value.addEventListener("submit", (e) => {
this.form_submit_override(e)
})
})
}
//add random characters to input names
this.changeInputNames = () => {
for (var i = 0; i < this.input_elements_arr.length; i++) {
this.input_elements_arr[i].setAttribute("name", this.input_elements_arr[i].getAttribute("name") + this.autocompleteString);
}
}
//remove the random characters from input names
this.changeInputNamesBack = () => {
for (var i = 0; i < this.input_elements_arr.length; i++) {
this.input_elements_arr[i].setAttribute("name", this.input_elements_arr[i].getAttribute("name").replace(this.autocompleteString, ''));
}
}
this.form_submit_override = (e) => {
e.preventDefault()
this.changeInputNamesBack()
e.currentTarget.submit()
return true
}
this.setup_form = () => {
//get all the inputs in the form
this.input_elements_arr = document.querySelectorAll("input");
this.changeInputNames();
this.add_submit_handlers();
}
//make sure script calls function after page load
this.init = () => {
if (document.readyState === "complete") {
this.setup_form()
} else {
let setup_form = this.setup_form
document.addEventListener("DOMContentLoaded", function (e) {
setup_form()
})
}
}
}
on the page that needs it
<script>
af = new stop_autofill()
af.init()
</script>

Dynamic html form elements as array

I have a dynamic section in my html form. When clicking on a button, user can add a tag name and tag type. At a point, imagine that there are 3 set of tag names and tag types, the data should be submitted in the following format.
Array[0][name] = tag1 name, Array[0][type] = tag1 type
Array[1][name] = tag2 name, Array[1][type] = tag2 type
Array[2][name] = tag3 name, Array[2][type] = tag3 type
Can someone help me on this ?
I think you are looking to have a multidimensional array that can store an array within each position of the array. Assuming you have already a form, html should look something like this:
<form class="" action="index.html" method="post">
<div class="inputs">
<input type="text" name="tagName" value="">
<input type="text" name="tagType" value="">
</div>
Add new tag name and type
<button type="submit" name="button">Submit form data</button>
</form>
For the functionality, you could have something like this to store the information and then submit the form:
//Initialization of array
var javascriptArray = [];
//Function to replicate fields in the form
function replicateFields(){
var elementToReplicate = $('.inputs').first(), //Only clone first group of inputs
clonedElement = elementToReplicate.clone();//Cloned the element
clonedElement.find('input').val(''); //Clear cloned elements value on each new addition
clonedElement.insertBefore($('form a'));
}
//Calling function on click
$('.addRow').click(function(){
replicateFields();
});
//Go through inputs filling up the array of arrays.
$('form').submit(function(){
$('.inputs').each(function(){
javascriptArray.push([$(this).find('input[name="tagName"]').val(), $(this).find('input[name="tagType"]').val()]);
});
console.log(javascriptArray);
return false; // remove this to submit the form.
});
You can check in the console in the developer tools for the information you are about to submit.
Let me know if this helps,
Leo.
//Initialization of array
var javascriptArray = [];
//Function to replicate fields in the form
function replicateFields(){
var elementToReplicate = $('.inputs').first(), //Only clone first group of inputs
clonedElement = elementToReplicate.clone();//Cloned the element
clonedElement.find('input').val(''); //Clear cloned elements value on each new addition
clonedElement.insertBefore($('form a'));
}
//Calling function on click
$('.addRow').click(function(){
replicateFields();
});
//Go through inputs filling up the array of arrays.
$('form').submit(function(){
$('.inputs').each(function(){
javascriptArray.push([$(this).find('input[name="tagName"]').val(), $(this).find('input[name="tagType"]').val()]);
});
console.log(javascriptArray);
return false; // remove this to submit the form.
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="" action="index.html" method="post">
<div class="inputs">
<input type="text" name="tagName" value="">
<input type="text" name="tagType" value="">
</div>
Add new tag name and type
<button type="submit" name="button">Submit form data</button>
</form>
here is another possibility for how to make this work. a simple form with a div to contain the tags and a small input field to add a new tag.
var tagid = 1;
function addTag() {
var div = document.getElementById("tags");
var name = document.getElementById("tname").value;
var type = document.getElementById("ttype").value;
div.innerHTML += "tag" + tagid + "<br><input type='text' name='tag[" + tagid + "][name]' value='" + name + "'><br><input type='text' name='tag[" + tagid + "][type]' value='" + type + "'><hr>";
tagid++;
}
<html>
<body>
<form id="form">
tags:<br>
<div id="tags">
</div>
<input type="submit" value="Submit">
</form>
<hr> tag name: <input id="tname" type="text" name="tname"><br> tag type: <input id="ttype" type="text" name="ttype"><br>
<button onclick="addTag()">add tag</button>
</body>
</html>

how to generate json data for a form fields in angularjs

I am new to JSON data so please help me out!!
I have single web page with multiple forms which are validated using angularjs,
I want to generate JSON data for the fields in that forms.So which methods should be used to generate JSON data and post syntax for that methods.
my html code is like
<td >
<input type="text" style="width:100px" ng-model="cost" ng-disabled="status!=true" required>
</td>
<td >
<input type="text" style="width:110px" ng-model="price" ng-disabled="status!=true" required>
</td>
My angularjs code is
var validationApp = angular.module('validationApp', ['ngFlag']);
// create angular controller
validationApp.controller('mainController', function($scope) {
$scope.style
{
$scope.buttonCSS= "clicked";
};
$scope.style2
{
}
$scope.invoice = {
items: [{
loyality: [{name:'points'},{name:'credits'}],
value:0,
period: [{name:'activity1'},{name:'activity2'}]
}],
items1:[{currency: [{name:'point'},{name:'credit'}], value1:0 }]
};
});
Angular allows you to bind your ng-model fields as part of an object. So instead of binding each form field to an individual value. Make them each an attribute in a single object.
<input type="text" ng-model="myForm.productName"/>
<input type="text" ng-model="myForm.productCount"/>
You then have a JSON object myForm that has all the values from your form and can be accessed from the controller.
Read about ng-model and how two way binding works.
<input type="text" ng-model="yourobj.name" />
<form name="myForm" ng-click="submit()">
And in your controller, you could grab the form input fields like below.
(function(){
angular.module("yourapp").controller(['$scope', function(){
$scope.submit=function(){
var jsonData = $scope.yourObj;
console.log(jsonData);
}
}])
})();

Add form information in to URL string and submit

I need to get information from my online form added in to my URL string and get it submitted to the dialler.
I have a working URL string that submits data to our dialler ok.
I need to get the first name, last name and phone number from the form submission in to the URL string.
This is how the URL string looks;
http://domain.com/scripts/api.php?user=admin&pass=password&function=add_lead&source=MobileOp&phone_number=07000000000&phone_code=44&list_id=3002&first_name=NAME&last_name=SURNAME&rank=99&campaign_id=campaign&callback=Y&callback_datetime=NOW
This is the form I have;
<form id="contact_form" method="post" action="">
<div class="contactform">
<fieldset class="large-12 columns">
<div class="required">
<label>Your First Name:*</label>
<input name="first_name" type="text" class="cms_textfield" id="first_name" value="" size="25" maxlength="80" required="required" />
</div>
<div class="required">
<label>You Last Name:*</label>
<input name="last_name" type="text" class="cms_textfield" id="last_name" value="" size="25" maxlength="80" required="required" />
</div>
<div class="required">
<label>Phone Number:*</label>
<input name="phone_number" type:"number" id="phone_number" size="25" maxlength="11" required="required"></input>
</div>
</fieldset>
<p class="right"><strong>Call us now on 01656 837180</strong></p>
<div class="submit"><input type="submit" value="Submit" class="button small radius"></div>
</div>
</form>
I am struggling to get anywhere with this. I have a basic knowledge of PHP.
If you change your form to method="GET" and the action to your url action="http://domain.com/scripts/api.php" it will include it in the URL string. That said, showing a user's password as a query string variable is probably a bad idea in the long run.
Instead, you can process the input from the form in PHP by referring to the $_POST array in your code. For example, to get the first name you'd just use $_POST['first_name']
Change
<form id="contact_form" method="post" action="">
to
<form id="contact_form" method="GET" action="">
(notice the method 'GET'). GET sends form variables through the URL.
You can use PHP for this.
if you have an input field of name attribue 'first_name', It'll be stored in the variable $_POST['first_name'] in case of POST as method and $_GET['first_name'] in case of GET method
If you have a url
http://domain.com/scripts/api.php?user=admin&pass=password&function=add_lead&source=MobileOp&phone_number=07000000000&phone_code=44&list_id=3002&first_name=NAME&last_name=SURNAME&rank=99&campaign_id=campaign&callback=Y&callback_datetime=NOW,
notice the x=y pattern repeating in it, like user=admin. Here, the first element, x becomes the key to tha PHP array and the second becomes the value.
You can use this function. on your submission page
<script type="text/javascript">
function iter() {
var str = "";
$("#contact_form .contactform .required :input").each(function () { // Iterate over inputs
if ($(this).attr('id')) {
str += $(this).attr('id') + "=" + $(this).val() + "&"; // Add each to features object
}
});
str = str.substring(0, str.length - 1);
$.ajax({
type: "GET",
url: "http://domain.com/scripts/api.php",
data: str,
async: true,
error: function (error) {
},
success: function (data) {
}
});
}
</script>
just attach it to the submit button as shown below
$("#contact_form .submit").on("click", function () {
iter();
return false;
});