Store multiple inputs in JSON key as part of array - javascript

Good evening,
I am trying to make a form that is dynamic, meaning that some <input> tags can be added by the user with the click of a button. Such behaviour is easely done with javascript, adding an element whenever the user feels like it, appending it to the parent element, in this case a form.
The dynamic nature of the input tags comes from the need to store a bunch of values inside an array that must be later pushed inside a mongodb document and the number of elements is not set, hence the dynamic nature. An example, to show what I mean:
<form>
<fieldset>
<legend>Username and ID</legend>
<input type="text" name="username" />
<input type="text" name="uniqueId" />
</fieldset>
<fieldset>
<legend>Places the user can go to</legend>
<input type="text" /> <!-- user input would be "pub" -->
<input type="text" /> <!-- user input would be "market" -->
<input type="text" /> <!-- user input would be "cinema" -->
<input type="text" /> <!-- user input would be "computer store" -->
<!-- other elements, added dynamically -->
<!-- the user might be able to go also to the gym, or the park,
he is the one that decides the number of places to add to the
input -->
</fieldset>
</form>
The thing I would like is for this input values to be stored all together inside an array which is already part of an object, like so:
myObject = {
username: "Ryan",
uniqueId: "A001",
canGoTo : [
"pub",
"market",
"cinema",
"computer store",
...other inputs that the user might have added and wrote]
}
The canGoTo key would be filled with the values inserted by the user inside the various inputs of that form. How would I go about storing them inside the array canGoTo?
EDIT: I am using AngularJS with ng-submit

You can use ng-model to target specific indices of an array. Something like:
<form>
<fieldset>
<legend>Username and ID</legend>
<input type="text" name="username" />
<input type="text" name="uniqueId" />
</fieldset>
<fieldset>
<legend>Places the user can go to</legend>
<input type="text" ng-repeat="input in myObject.canGoTo"
ng-model="myObject.canGoTo[$index]" />
</fieldset>
</form>
To add a new input:
$scope.myObject.canGoTo.push ('');
You'll need to run some testing on the various functions you offer in terms of manipulating the actual form, but this should be a good launching point.

If you give all the relevant inputs the same class, you can use getElementsByClassName(), and then cycle through the returned array, and do something along the lines of canGoTo.push(elementArray[i].value) after creating an empty canGoTo array.
If you want to add one at a time, all you need to add is a variable keeping track of the current inputs index number.

Related

Angular 2+ multi-part form validation, how to check validity of single input

I have a form, and the form has multiple inputs that are all bound to different variables. Before submitting the form, I need to do validity checks, pristine checks, etc. For example, I want my submit button to be disabled if every part of the form is pristine, or if something is invalid.
Using Angular 5, I am trying to get access to the .pristine, .valid, and .invalid flags for each input field, but the values are either undefined or "cannot get .pristine of undefined".
I am able to get these flags on the entire form itself, but this doesn't help, because I want to know how to get it for each individual input.
Here is my current code (I've removed a number of my inputs to simplify the example).
<form #editDetailsForm="ngForm" name="editDetailsForm" >
<label for="name"> Name </label>
<input type="text" id="name" name="name" maxlength="40" [(ngModel)]="myName" required />
<label for="description"> Description </label>
<textarea id="description" name="description" maxlength="250" [(ngModel)]="myDescription" required ></textarea>
<button id="submit" type="button"
[disabled]="saveButtonDisabled(editDetailsForm.invalid, editDetailsForm.name.invalid, editDetailsForm.description.invalid)"
(click)="updateDetails()" >
Save
</button>
</form>
If you see, I bind disabled attribute on the Save button to saveButtonDisabled() function, where I want to pass in information about each input's validity. The first argument, editDetailsForm.invalid returns a true or false, but the other values return undefined.
How do I check validity of these individual inputs?
EDIT: I realize I can derive all of this info inside my component because all of the input values are bound. However, it'd be easier just to check a flag or two.
I'm not sure I totally understand what you want to do, but this is how you get access to the form controls .pristine, .invlaid
<input type="text" id="name" name="name" #name="ngModel" maxlength="40" [(ngModel)]="myName" required />
The #name="ngModel" sets a template reference to the FormControl angular creates
Then you should be able to do something like this:
<input type="text" id="name" name="name" #name="ngModel" maxlength="40" [(ngModel)]="myName" required />
<div *ngIf="name.pristine">
Name is Pristine
</div>
Just to clarify, the individual form fields bubble up to the form itself. So if any field has been touched, then the whole form will be pristine == false.
You can access the input controls using the .controls property, like:
<button id="submit" type="button"
[disabled]="editDetailsForm.controls.name?.invalid || editDetailsForm.controls.description?.invalid">
Created a stackblitz. https://stackblitz.com/edit/angular-5ir4k7
Added template reference variable for ngModel and validate using isValid.

jQuery, input elements with the same data attribute value but one is hidden, fill in same data on keyup

jQuery, input elements with the same data attribute value but one is hidden, fill in same data on keyup.
I have 2 forms on a page with dynamically created form fields from a database via .NET MVC.
I have one form visible and one form that is hidden.
I know how to copy, on keyup, the values from one form field to another IF I have known element classes or Id's. This is not the case on dynamically created fields. I can not guarantee that all fields will come back in the same order in each form.
So what I did was I created a 'data' attribute and output the "Model.Name" on the input field. In my case I am lucky enough that the 2 forms have fields with the same "Model.Name" values. So I am able to do a match on that. But since the forms are built dynamically I need a few things to happen and I need some pointers.
I need to know how to copy field inputted values from the visible form fields to their matching hidden form fields with the same "data" attribute value. I won't necessarily know the actual data-attribute value since the input fields are getting created dynamically.
How would this work to get the matching form fields.
I have a basic JS Fiddle set up.
https://jsfiddle.net/mb91ktbg/6/
HTML
<!--I know the class of the wrapping form -->
<!--All data values are dynamic, so I don't know then on page load-->
<div class="masterFieldWrapper">
<!--Need to copy these input values to the sub field wrapper input values-->
<label>Field one</label>
<input type="text" data-myattribute="dynamicvalue" />
<label>Field Two</label>
<input type="text" data-myattribute="dynamicvalue2" />
<label>Field Three</label>
<input type="text" data-myattribute="dynamicvalue3" />
<!--I know the class of the sub field wrapper-->
<!--I would like to copy the inserted values from the parent wrapper fields to the sub field wrapper fields with the same data-myattribute value-->
<!--I can not assume the fields come back in the same order. This is why I need to use the data attribute value-->
<div class="subFieldWrapper">
<label>Field One</label>
<input type="text" data-myattribute="dynamicvalue" />
<label>Field Two</label>
<input type="text" data-myattribute="dynamicvalue2" />
<label>Field Three</label>
<input type="text" data-myattribute="dynamicvalue3" />
</div>
</div>
jQuery Started but not working. need some help please.
$(".masterFieldWrapper input").each(function() {
var fieldVal = $(this).val();
var fieldDataAttr = $(this).data("myattribute");
console.log(fieldDataAttr);
$(this).keyup(function() {
$(this).parent('.masterFieldWrapper').find(".subFieldWrapper input").data("myattribute").val($(this).val());
});
});
Don't know if this would help but, you could dynamically add a class or id to the element and then access like so:
$(".bodyWrapper").on("change", ".form-control", event => {
let value = $('.dynamicValueInput').val();
$('.dynamicValueInputCopy').val(value);
console.log(`body-input-has-changed`);
});
//Try this :)
var mainForm = $(".masterFieldWrapper");
var Input_type = $("input[type='text']");
var Totalinputs = mainForm.find(Input_type).length;
var Visible_inputs = Totalinputs/2;
var auto_fulfill = function(){
for(i=Visible_inputs; i<Totalinputs;i++){
Input_type.eq(i).val(Input_type.eq(i-Visible_inputs).val());
}
}
Input_type.keyup(function(){
auto_fulfill();
})

What is this : document.reservation.submit(); supposed to do?

I am reworking on a code of an old developer and I'm trying to do a form for reservation.
I've looked across the whole code the only thing called reservation is the name and the id of the form.
Form who's is in style : display:none ...
So two question in one : First of all what the heck is supposed to do
document.reservation.submit(); Is it suppose to get the form by his name ?
Shouldn't it be something like document.getElementById('reservation').submit() instead ?
And my second question is : How the form can be sent if all the value are set to display:none I tough it couldn't work and if you want to hide them you shall use hidden property...
I need a bit of help on this guys pls :)
Form for beter comprehension :
<form name='reservation' action='http://xxxx/reservationFormAction.to' method="POST" id="reservation">
<input type="hidden" id="productLive" name="product" value="{$product.info.code}"/>
<input type="hidden" name="complementaryParameters" value=""/>
<input type="text" name="depCityCode" id="depCityCode" style="display:none" />
<input type="text" name="dateDep" id="dateDep" style="display:none" />
<input type="text" name="nightDuration" id="nightDuration" style="display:none" />
<input type="text" name="dayDuration" id="dayDuration" style="display:none" />
<input type="text" name="provider" value="{$product.tourOperator.code}" style="display:none" />
<input type="text" id="toProduct" name="toCode" value="{$product.info.toProductCode}" style="display:none" />
<input type="text" name="catalogCode" value="{$product.info.code}" style="display:none" />
{if $ecall}
<input type="text" name="reservationProfileChannelCode" value="ECALL" style="display:none" />
{else}
<input type="text" name="reservationProfileChannelCode" value="ADV" style="display:none" />
{/if}
<input type="text" name="nbAdults" id="nbAdults" style="display:none" />
<input type="text" name="nbChildren" id="nbChildren" style="display:none" />
<input type="text" name="nbBabies" id="nbBabies" style="display:none" />
<input type="text" name="productUrl" id="productUrl" style="display:none" value="http://www.xxxx.com/{$product.slug}_{$product.info.code}.html" />
<input type="text" name="homeUrl" id="homeUrl" style="display:none" value="http://www.xxxx.com" />
<span id="ageChild" style="display:none"></span>
<div class="update-search clearfix">
document.reservation gets the HTMLFormElement for the form with the name reservation. Then calling submit submits the form (without triggering the submit event).
So why not document.getElementById? That would also work, but document.reservation works because the document object gets various properties created on it automagically, including properties referring to forms by their name. This is covered in ยง3.1.3 of the HTML5 spec *(you have to scroll down a fair bit):
The Document interface supports named properties. The supported property names at any moment consist of the values of the name content attributes of all the applet, exposed embed, form, iframe, img, and exposed object elements in the Document that have non-empty name content attributes, and the values of the id content attributes of all the applet and exposed object elements in the Document that have non-empty id content attributes, and the values of the id content attributes of all the img elements in the Document that have both non-empty name content attributes and non-empty id content attributes.
The value of those properties is the element the name or id came from.
The window object also gets properties for every element with an id, as described here:
The supported property names at any moment consist of the following, in tree order, ignoring later duplicates:
the browsing context name of any child browsing context of the active document whose name is not the empty string,
the value of the name content attribute for all a, applet, area, embed, form, frameset, img, and object elements in the active document that have a non-empty name content attribute, and
the value of the id content attribute of any HTML element in the active document with a non-empty id content attribute.
Where again the value of those properties is the element the name or id came from.
In both cases, this is the HTML5 specification standardizing the previously-widespread-but-nonstandard practice most browsers had, which is widely used on pages in the wild.
How the form can be sent if all the value are set to display:none I tough it couldn't work and if you want to hide them you shall use hidden property...
It's best to ask one question per question.
The CSS display property has no effect at all on whether form fields are submitted; you're probably thinking of the field's disabled state: Disabled form fields are indeed left out of the form on submission.
the display none or hidden info will always be sent even that you can't see.... Usually we pass some info that the user doesn't need to know, like USER_ID=20 .....---- and the
document.reservation.submit
------- it submits the form with name="reservation"

I want to use Jquery to live swap input field names

I have a webpage where I am using Jquery to add form fields dynamically and all is well. Below is a sample of how the fields are named. Basically when the user wants more fields then they hit a button and it inserts the two fields and increments the values of the next inputs and creates a container div surrounding the fields.
<fieldset id="dynamicField">
<div id="fieldID1"><ul><li>
<label for="headertext_1">Header Text</label>
<input id="headertext_1" name="headertext_1" size="70" value="My Header Text" />
</li>
<li>
<label for="blurblink_1">Link</label>
<input id="blurblink_1" name="blurblink_1" value="http://foo.bar" size="70" />
</li></ul></div>
<div id="fieldID2"><ul><li>
<label for="headertext_2">Header Text</label>
<input id="headertext_2" name="headertext_2" size="70" value="My Next Header Text" />
</li>
<li>
<label for="blurblink_2">Link</label>
<input id="blurblink_2" name="blurblink_2" value="http://bar.foo" size="70" />
</li></ul></div></fieldset>
Okay, so now what I need to add is a way for these fieldsIDs to be reordered - not only on the page, that would be easy enough, but I also need to rename the field names so that my backend server processing still works.
So for example:
If I have 1,2,3,4,5 different group of fields on the page I want to be able to click a few buttons to move 5 to this order on the screen and named correctly as well:
1,5,2,3,4
Thoughts?

Best practice for handling multiple copies of the same input fields client side?

I have a set of input fields that are "stacked" on top of each other.
<!-- This controls which data set you're looking at -->
<select class="EditorInput" id="Selector" name="Selector">
<option value="0">Link a new vendor</option>
<option value="1">The ACME Company</option>
<option value="2">Widgets Unlimited</option>
</select>
<!-- These values change based on the selection above -->
<input type="text" name="Price" />
<input type="text" name="SKU" />
<input type="text" name="Field3" />
<input type="text" name="Field4" />
<input type="text" name="Field5" />
<input type="text" name="Field6" />
<input type="text" name="Field7" />
<input type="text" name="Field8" />
Only one set shows at a time, but all set's values are kept in browser until submit. When you make a selection in the drop down, all of the input fields in the group change to show the user the values relevant to the selection. For example, choosing "The ACME Company" in the select field would make The ACME Company's price show in the price field, The ACME Company's SKU show in the SKU field, etc.
All data and all changes are stored client side. When data is saved (via AJAX), all of the values for each set are saved to the server at the same time.
Since submission is via AJAX, all the values don't necessarily have to be stored in input elements.
I can think of two main ways to do this:
Method 1
A single set of input elements, with data stored in a javascript object. On change of the select, the correct data is read out of the javascript variable and inserted into the fields. Any changes the user made to the first set are saved into the variable first. Choosing to add a new set saves the current values to a variable, then clears the values in the form.
Method 2
Have one whole set of input fields per option. Hide the non-active input sets. Changing the select shows/hides the right set. Adding a new set copies one of the existing sets, inserts the new input elements into the dom and clears the values of those new input elements.
Method 3
Use HTML 5 data to store multiple values, like:
<input type="text" name="Field8" value="$7.95" data-value-vendor-1="$6.99" data-value-vendor-2="$2.65" data-value-vendor-3="$12.24"/>
Then use javascript to switch the values into and out of "storage".
Which option make more sense? Or is there a better way? Also, with Method 1, where would the values for each set be stored? On the Select Option?
I would use a JSON-based data store and recycle the inputs, then submit the JSON store instead of form data. There are plenty of libraries (you're already using jQuery) to help with this on both the client and server end of things.

Categories

Resources