repeating form fields a user defined number of times - html

I am working on a web based form that needs to have the flexibility to add as many entries as the user needs. This means that a chunk of my form needs to be able to repeat it's self an undefined number of times it might be 1 or 2 or it could be 50. Is there a method of dynamically repeating form elements?

For completion, here is a pure JS solution:
You can create a JavaScript variable which contains the HTML text for the elements you want to create:
var formHtml = "<input type='text' name='inp'>"
And then you can insert the formHtml variable to the end of a DOM element called yourId by:
document.getElementById("yourId").innerHTML += formHtml;
Update: JSFiddle link: https://jsfiddle.net/zjd3g0cy/

You can append input field to the form using
$('.selector').append("<input type='text' name="xyz[]" />");

Related

How do I build a simple HTML form to construct a link from two form fields?

At work, one of the systems I use outputs voyage schedules. The URL for each voyage is constructed as the form address followed by ?voyageCode= followed by the voyage number, which is a two-letter route prefix and a three-digit voyage number.
Rather than use the standard form, which has a whole bunch of fields I never need to use, I want to build a simple page where I can just select the route and enter a voyage number.
In practical terms, I'm trying to build a form with the following:
A drop-down menu or set of radio buttons to select the two-letter route code;
A text field to enter the three-digit route code;
A button or link to combine those inputs into a link in the format [LINK]?voyageCode=[ROUTE CODE][VOYAGE NUMBER]
My HTML knowledge is pretty outdated, and I've never worked much with forms. Can anyone advise on how I can construct this?
Why don't you use a select tag for the dropdown and a classic input text for the route coude ?
Then for the link part, you should capture the click event on your button through onClick and then call a small function that'll basically do that :
function concatRouteCode(){
var select= document.getElementById("routeCodeLetters");
var routeCodeLetters = select.options[select.selectedIndex].value;
var routeCodeNumber = document.getElementById('routeCode').value;
return routeCodeLettres+routeCodeNumber;
}
If you really want to combine the codes into a single query parameter, you'll have to use Javascript to fetch the values of the two fields and change the location. You don't need Javascript if you put the values into separate parameters, as in ?routeCode=xx&voyageNumber=123. In that case you would just give the select element the attribute name=routeCode and the input field the attribute name=voyageNumber.
In case you want to go with the first approach, you'd have something like
document.getElementById("idOfSubmitButton").addEventListener("load", function() {
const routeCode = document.getElementById("idOfSelectElement").value;
const voyageNumber = document.getElementById("idOfInputField").value;
location.href = "base URL here" + "?voyageCode=" + routeCode + voyageNumber;
});

How to tell Chrome form does not contain credit card fields?

Chrome is being overzealous and thinks my HTML form contains credit card information and thus proposes to fill it in with credit card information.
Are there any attributes that I can use to tell Chrome that there is no credit card information to be filled in, in this form?
The field names it is trying fill in credit card information in are:
reg_id (it puts in a CC number here)
emergency_first_name (it puts in first name here)
emergency_last_name (it puts in last name here)
I don't want to have to disable autocomplete if I don't have to.
The frustrating thing here is the Chrome 'knows better' attitude, where it ignores any value to autocomplete, including off:
<input autocomplete="off" value="" size="10" maxlength="10" id="id_reg_id" name="reg_id" type="text">
Edit: updated following answers.
try
input type="custom"
or use textarea with a single row and resize off
Your browser shouldn't remember your credit card number by default -- I can only assume that you entered into a field that had a 'generic' autocomplete value on it. You can always force your browser to forget this information by simply hitting Delete when selecting it (with the arrow keys) in the dropdown of pre-fill options.
As for preventing it appearing in certain fields, it depends on what information you want each field to hold, but there's a wide array of autocomplete values that you can use. You can use number for IDs, and the other two fields you mentioned actually come with specialised autocomplete values, given-name and family-name:
<input name="reg_id" autocomplete="number" />
<input name="emergency_first_name" autocomplete="given-name" />
<input name="emergency_last_name" autocomplete="family-name" />
If number just won't cut it, you can also make use of a JavaScript regular expression to further restrict input:
const regex = new RegExp("^[a-zA-Z]+$");
const form = document.getElementsByTagName('form')[0];
const reg_id = document.getElementsByTagName('input')[0];
form.addEventListener('click', function(e) {
e.preventDefault();
if (regex.test(reg_id)) {
this.submit();
}
});
<form>
<input name="reg_id" autocomplete="number" />
<input name="emergency_first_name" autocomplete="given-name" />
<input name="emergency_last_name" autocomplete="family-name" />
</form>
I have been banging my head against the desk for a while because of this. We have forms to enter Instruments test data, and a field called "Test Card Number", as well as "Kit (Exp. Date)". Guess what Chrome thinks these fields are for?
Needless to say, I'm pretty sure the users would be VERY upset to see chrome us trying to pull their CC information when they're inputing clinical research data.
Even autocomplete="new-password" and autocomplete="nope" are failing to do any good, here.
I tried to load the field with no label and add it dynamically in javascript. No dice. Used html entities instead of characters. Nope.
Well, after a few hours of scouring the web with no solution in sight, I figured one out: insert a few random - within each word of the offending labels. (For me, with Test Card Number, it had to be in BOTH Card and Number. Test was fine left alone).
One could easily write a javascript extension/utility function to split the html of an offending label and slap that invisible span down the middle (and one to remove it in case of needing to use the label value).
Something like this (using jQuery and old js standards because we support old browsers, with no verifications if label is missing or empty, so adapt accordingly. In fact, I'm sure a regex or some other fancy stuff could be used, but I don't have the time to fiddle around with it atm):
jQuery.fn.breakAutofill = function () {
var $lbl = $("label[for='" + this[0].id + "']"),
finalText = $lbl.html().split(" "),
foilSpan = "<span style='display:none;'>-</span>";
for (var idx in finalText) {
var textVal = finalText[idx],
midPos = Math.floor(textVal.length / 2);
finalText[idx] = textVal.substr(0, midPos) + foilSpan + textVal.substr(midPos);
}
$lbl.html(finalText.join(" "));
}
Which you can then call on document ready :
$("your_input_selector").breakAutofill();
I hope that helps someone.

HTML: How to show a list whose size is unknown in advance on a webpage?

I'm like to admit that my knowledge of HTML is very little.
Assume we have a button on our pagepage that calls a javascript function: check().
The check() function withdraws an array (contantly updated) of values, e.g. string, from a server. If each element of the array has a certain property, e.g. contain a letter "a", then it wants to print those strings on the webpage.
The upperbound of the array size retrieved from the server is known but we do not know in advance how many elements satisfies the condition checked by check().
Question how to print the elements found by check() on a HTML file (a webpage).
Let's assume javascrip is in the the HTLM file too.
With something like <div id="destination"></div> in the HTML as a placeholder, you can use JavaScript to loop through your array of items and insert each one into the HTML with:
document.getElementById('destination').innerHTML += '<p>' + myData + '</p>';

Can ng-invalid parameters work similarly to a conditional ng-required?

This is my first time asking something here so I tried to put as much information as possible to help in my predicament.
I have a question pertaining to an HTML form I'm building that uses some AngularJS which I'm learning more about as I go along.
The form itself uses some mathematics in it which I'm generating a dividend from 2 fields at a time while also factoring in a total number of people. The page itself will generate the dividend on the page itself to give the user a real-time look at their math, so there are already ng-models on most if not all fields. The catch is that the dividend itself for the fields cannot exceed 1 as I'm doing percentages from 0-100%.
Previously if the numerator was higher than the denominator, or the denominator was higher than the max amount of people I would have an explanation field that was previously be a non-required field toggle to required like so:
<textarea rows="4.5" cols="50" id="My_Fields_Notation__c" tabindex="11"
name="My_Fields_Notation__c" maxlength="255"
ng-required='fieldDen < fieldNum || fieldDen > numberOfPeople'
type="text"></textarea>
My question is if I was to remove the ng-required on this field and add a separate ng-invalid on the numerator and denominator each
(ng-invalid='fieldDen < fieldNum' on the numerator and ng-invalid='fieldDen > numberofPeople' on the denominator)
Would that cause the field to not submit if those parameters are met? (ex. if a user has Numerator: 100, Denominator: 50 and/or Number of people: 100, Denominator: 101 would the form not submit since the numbers don't meet those parameters I'm trying to set)
EDIT: If this helps to better explain my situation. I have several numerators and denominators for this form all with their own ng-model names.
The numerator cannot be higher than the denominator
The denominator cannot be higher than the number of people
If either or happens on any of the numerators and denominators, I want to block submission of the form
At the same time the form is in a drupal page and the only JS file I've been able to successfully call in was the angular file so far, so I think any additional script needs to be coded in the page itself if I need to create any controllers.
If your form submit's or doesn't submit depends on how you do the submission.
It will submit if you use:
<button ng-click='mySubmitFunction()'>Submit</button>
It will not submit if you use:
<button ng-click='formValid() && mySubmitFunction()'>Submit only if valid</button>
To check if your validation condition is met add a validation function:
$scope.formValid = {
return ($scope.fieldDen < $scope.numberofPeople) && ($scope.fieldDen < $scope.fieldNum)
}
If you only want to validate a certain input you can also write a validation directive for this. This let's you show i.e. custom error messages if a certain condition is not met like the format, example plunkr taken from the docs: http://plnkr.co/edit/7ewLoTgWWwyeo7HAvTqU?p=preview
you can add a ngPattern to the input you want to validate and then you just can use the $valid given by angularjs to validate that element.
<form name="myForm">
<input type="text" name="userName" ng-model="user.name" ng-pattern="{string}" >
</form>
//to test just use
{myForm.userName.$valid}

Should I use one form on page or generate a form per item?

I want to display a list of items. Each item would have an edit and a delete icon next to it.
For obvious reasons I want to trigger the delete action with HTTP POST.
With jQuery, I would bind links to trigger form.submit.
However I'm not sure if I should generate a form next to each item or use just one form.
Below are pros and cons of two approaches as I see them.
Form Per Item:
easy to generate;
no need to fiddle in JS to set action and input value.
Single Form:
makes more sense semantically;
requires client JS to set hidden input;
requires client JS to set form action (e.g. id + '/delete/).
What is there to add? What is the preferred pattern in modern HTML apps?
I have used checkboxes in the past. This is better for usability, and each checked checkbox can pass its own ID to the form processing script.
The main disadvantage I see in having a single form enclosing all list elements is that you can end up with a huge POST if the list is long. As an advantage, you could mark multiple elements for deletion (checkboxes, for instance) and perform a single delete request.
I'd go for either
A single form for each list element. This would make deletion of multiple elements impossible, but would keep POST sizes minimal.
Using a single form, but in a way that doesn't include all the list elements. For instance, having a delete only form with a single hidden element in it, into which you would put all the id's marked for deletion with JS manipulation.
As a side note, you could also skip forms and perform the needed interactions through ajax. This would improve user experience notably. Take into account that forms would still be needed to provide fallback mechanisms in case it was required.
In the end, I decided to go with AJAX via jQuery.ajax.
The reason is semantically I don't even have forms—I have buttons.
Therefore, jQuery is an easier solution as it allows to keep posting logic in one place (as opposed to scattering it across HTML and JS).
I assigned row class to each semantical row and put corresponding database IDs in HTML5 data attribute called data-row-id for each row.
<div class="row" data-item-id="{{ product.id }}">
<!-- ... --->
<img src="/img/delete.png" alt="Delete">
</div>
Then I have something alone the lines of
$('.delete-btn').click(function() {
var row = $(this).closest('.row');
var id = row.data('item-id');
$.ajax({
url: id + '/delete/',
type: 'POST'
});
row.fadeOut().slideUp();
return false;
}
in my $() load handler.
This solution scales beautifully across the whole codebase because you only have to set row class and data-item-id attribute and the buttons will “just work”.