reset() method for resetting form fields results in errors - html

I am using ngForm in html and in typescript implemented resetting form fields in OnCickSubmit(). It performs as expected and thus does clear the form's select field but resetting also seems to show 400 bad errors for api calls behind populating the form fields.Eg:dataChanged() is actually calling api in back-end to populate the field and after successful submit then reset happens which clears field but why is the function called again and indeed api called again. Is there a way to avoid this?
html :
<form id = "myForm" #myForm = "ngForm" (ngSubmit) = "onClickSubmit(myForm.value)">
<label>Name</label>
<select ngModel name= "cname" (ngModelChange)="dataChanged($event)" required>
<option [ngValue]="data.name" *ngFor = "let data of result">{{data.name}}</option>
</select><br/>
<input class = "button" align = "center" type = "submit" value = "Apply" [disabled]="!myForm.valid"><br/>
</form>
In typescript onClickSubmit():
anotherfunc();
var resetForm = <HTMLFormElement>document.getElementById("myForm");
resetForm.reset();

If I able to understand your problem properly, don't use getElementById to form reset in angular. we can do form reset in other ways and they are lot simpler than this.
do some changes in your component and template like below
yourComponent.html
<form id = "myForm" #myForm = "ngForm" (ngSubmit) = "onClickSubmit(myForm.value)">
<label>Name</label>
<select [(ngModel)]="dataName" name= "cname" (ngModelChange)="dataChanged($event)" required>
<option [ngValue]="data.name" *ngFor = "let data of result">{{data.name}}</option>
</select><br/>
<button class = "button" align = "center" type = "submit" value = "Apply" [disabled]="!myForm.valid">submit</button><br/>
</form>
yourComponent.ts
dataName: string;
onClickSubmit(event: any){
// this.service.sendPost(){ <= call your method here
on successful response clear the form
if(data.status == 200)
this.dataName = undefined;
//}
}
your using input for submitting the form, it's recommended to use button for that. I changed it in html

Related

How to assign formGroup to an array for form validation

I have a repeater section in angular, i followed the below method to achive it, but i want to validate the form (Enable or disable the final submit button based on the validation),Here is the sample code.
ts file:-
private formBuilder : FormBuilder
) { }
formInfoHolder = [];
onAdd(){
let newForm = {
let newForm = {
subText : new FormControl('',[Validators.required,Validators.maxLength(250)]),
header : new FormControl('',[Validators.required,Validators.maxLength(20)]),
link : new FormControl('',[Validators.required,Validators.pattern('[a-zA-Z]*')]),
}
}
this.formInfoHolder.push(this.formBuilder.group(newForm))
}
delete(toDelete){
let del : any[] = [];
for(let form of this.formInfoHolder){
if(toDelete !== form){
del.push(form);
}
}
this.formInfoHolder = del;
}
then in HTML Component
<div *ngFor="let form of formInfoHolder">
<form [formGroup]="form">
<label for="username"> Username </label>
<input id="username" type="text" formControlName="username">
<!-- insert other input elements with the formControlName -->
<label for="delete"> Delete </label>
<input id="delete" type="button" (click)="delete(form)">
</form>
</div>
<button (click)="onAdd()">Add</button>
<button [disabled]="//Here i want to validate" (click)="saveInfo()">Save</button>
How do i validate the form(enable the button only if all the fields are filled) which is stored in an array.
Here is a Stackblitz example for what you are looking for
I have used formarray and added formgroups into it, adding and removing formgroups becomes easy in formarray. Also validation also becomes easy because I only have check if the main form in valid

Angular 5 ngModel changes the value in UI without saving it

In my form I have a select with a bind variable. If I try to change and save the value it works fine but if I try to change the value in my modal and instead of save it, I close the modal (so I do not save the value) in my UI I see the changed value and obviously in my DB the value is not changed.
component.html
<select class="form-control m-input" id="type" formControlName="type"
[ngClass]="{ 'is-invalid': submitted && formcontrols.type.errors }" name="type"
(change)="changeType($event, newParameter.type)"
[(ngModel)]="newParameter.type">
<option [ngValue]="'STRUCT'">STRUCT</option>
<option [ngValue]="'NUM'">NUM</option>
<option [ngValue]="'BOOLEAN'">BOOLEAN</option>
<option [ngValue]="'DATE'">DATE</option>
</select>
component.ts
changeType(event, type){
type= this.createParameterForm.get('type').value;
if(type==="NUM"){
this.initNUMControlsForm();
}
else if(type ==="STRUCT"){
this.initStructControlsForm();
}
else{
this.initControlsForm();
}
}
How can I avoid this problem?
usually you need to create another instance of your object at beginning and modify that object by your form. You can create the new object by const newObj = {...originalObj} or const newObj = JSON.parse(JSON.stringify(originalObj))
if user tries to save, pass the new object to save function and after success save, copy it back to original object
if user cancels, do nothing because your original object is not changed

Creating Input element and appending it to form with ngModel

I have a select dropdown with its onChange event mapped to a function which should create an input element with ngModel along with other attributes, and append it to another element, like so:
<select class="form-control" id="addUsers" (change)='addProfession($event.target.value)'>
<option *ngFor='let profession of professions' [value]='profession.ProfessionTypeName'>
{{ profession.ProfessionTypeName }}
</option>
<div #addUsersProfessionsSelect></div>
Below you can finds the function bound to the select's change event:
addProfession(professionName: string) {
let profession = new Profession(Profession.nameToIdMap[professionName], professionName);
this.shouldDisplayProfessionsInputs = true;
let professionInput = `<div>${profession.professionName}
<input type="text" class="form-control" [id]='${profession.professionName}' name='${profession.professionName}'
[(ngModel)]="newCampaign.users[${profession.professionTypeId}]"></div>`
let safeHTML = this.sanitizer.bypassSecurityTrustHtml(professionInput);
let element = this.renderer.createElement(this.addUsersProfessionsSelect.nativeElement, 'div');
this.renderer.setElementProperty(element, 'outerHTML', safeHTML);
}
addProfession does create and append the element, but it ignores all attributes. Here's the added input element:
<input type="text" class="form-control" [id]="Stylist" placeholder="Stylist"
name="Stylist" [(ngmodel)]="newCampaign.users[6]">
Do note the lowercase attribute names, and ignored brackets on the [id] attribute.
I'd love any help on this subject. Thanks!
Instead of directly manipulating the DOM, I pushed the new profession to an array on which I used an *ngFor and bound the data I needed to the iterator.

Autocomplete with datalist [duplicate]

Currently the HTML5 <datalist> element is supported in most major browsers (except Safari) and seems like an interesting way to add suggestions to an input.
However, there seem to be some discrepancies between the implementation of the value attribute and the inner text on the <option>. For example:
<input list="answers" name="answer">
<datalist id="answers">
<option value="42">The answer</option>
</datalist>
This is handled differently by different browsers:
Chrome and Opera:
FireFox and IE 11:
After selecting one, the input is filled with the value and not the inner text. I only want the user to see the text ("The answer") in the dropdown and in the input, but pass the value 42 on submit, like a select would.
How can I make all browsers have the dropdown list show the labels (inner text) of the <option>s, but send the value attribute when the form is submitted?
Note that datalist is not the same as a select. It allows users to enter a custom value that is not in the list, and it would be impossible to fetch an alternate value for such input without defining it first.
Possible ways to handle user input are to submit the entered value as is, submit a blank value, or prevent submitting. This answer handles only the first two options.
If you want to disallow user input entirely, maybe select would be a better choice.
To show only the text value of the option in the dropdown, we use the inner text for it and leave out the value attribute. The actual value that we want to send along is stored in a custom data-value attribute:
To submit this data-value we have to use an <input type="hidden">. In this case we leave out the name="answer" on the regular input and move it to the hidden copy.
<input list="suggestionList" id="answerInput">
<datalist id="suggestionList">
<option data-value="42">The answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">
This way, when the text in the original input changes we can use javascript to check if the text also present in the datalist and fetch its data-value. That value is inserted into the hidden input and submitted.
document.querySelector('input[list]').addEventListener('input', function(e) {
var input = e.target,
list = input.getAttribute('list'),
options = document.querySelectorAll('#' + list + ' option'),
hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden'),
inputValue = input.value;
hiddenInput.value = inputValue;
for(var i = 0; i < options.length; i++) {
var option = options[i];
if(option.innerText === inputValue) {
hiddenInput.value = option.getAttribute('data-value');
break;
}
}
});
The id answer and answer-hidden on the regular and hidden input are needed for the script to know which input belongs to which hidden version. This way it's possible to have multiple inputs on the same page with one or more datalists providing suggestions.
Any user input is submitted as is. To submit an empty value when the user input is not present in the datalist, change hiddenInput.value = inputValue to hiddenInput.value = ""
Working jsFiddle examples: plain javascript and jQuery
The solution I use is the following:
<input list="answers" id="answer">
<datalist id="answers">
<option data-value="42" value="The answer">
</datalist>
Then access the value to be sent to the server using JavaScript like this:
var shownVal = document.getElementById("answer").value;
var value2send = document.querySelector("#answers option[value='"+shownVal+"']").dataset.value;
Hope it helps.
I realize this may be a bit late, but I stumbled upon this and was wondering how to handle situations with multiple identical values, but different keys (as per bigbearzhu's comment).
So I modified Stephan Muller's answer slightly:
A datalist with non-unique values:
<input list="answers" name="answer" id="answerInput">
<datalist id="answers">
<option value="42">The answer</option>
<option value="43">The answer</option>
<option value="44">Another Answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">
When the user selects an option, the browser replaces input.value with the value of the datalist option instead of the innerText.
The following code then checks for an option with that value, pushes that into the hidden field and replaces the input.value with the innerText.
document.querySelector('#answerInput').addEventListener('input', function(e) {
var input = e.target,
list = input.getAttribute('list'),
options = document.querySelectorAll('#' + list + ' option[value="'+input.value+'"]'),
hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden');
if (options.length > 0) {
hiddenInput.value = input.value;
input.value = options[0].innerText;
}
});
As a consequence the user sees whatever the option's innerText says, but the unique id from option.value is available upon form submit.
Demo jsFiddle
When clicking on the button for search you can find it without a loop.
Just add to the option an attribute with the value you need (like id) and search for it specific.
$('#search_wrapper button').on('click', function(){
console.log($('option[value="'+
$('#autocomplete_input').val() +'"]').data('value'));
})
to get text() instead of val() try:
$("#datalistid option[value='" + $('#inputid').val() + "']").text();
Using PHP i've found a quite simple way to do this. Guys, Just Use something like this
<input list="customers" name="customer_id" required class="form-control" placeholder="Customer Name">
<datalist id="customers">
<?php
$querySnamex = "SELECT * FROM `customer` WHERE fname!='' AND lname!='' order by customer_id ASC";
$resultSnamex = mysqli_query($con,$querySnamex) or die(mysql_error());
while ($row_this = mysqli_fetch_array($resultSnamex)) {
echo '<option data-value="'.$row_this['customer_id'].'">'.$row_this['fname'].' '.$row_this['lname'].'</option>
<input type="hidden" name="customer_id_real" value="'.$row_this['customer_id'].'" id="answerInput-hidden">';
}
?>
</datalist>
The Code Above lets the form carry the id of the option also selected.

Not send GET variable on submit if dropwdown not selected

I have a form that I used to filter search results that consist of only dropdowns. I use GET rather then post so that the results can easily be shared with the URL.
<form action="" name='filter' method="GET">
<select name="Make" id="Make">
<option selected="selected" value ="nothing">All</option>
<option value="Toyota">Toyota</option>
<option value="Honda">Honda</option>
</select>
<input type="submit" value="Filter">
</form>
As it is right now if It will submit the value "nothing" for the get variable Make if the user doesn't change the selection. They're are multiple drop downs identical as this one for model year etc.
Is it possible for the Make variable to not show up in the URL if it isn't used?
As it is now if that code is submited it will say website.com/?Make=nothing. I tried removing the value and then it says website.com/?Make=All. I do not want make to show up in the URL if "All" is selected. Is this possible?
You don't have a submit button :)
you can add a JS that runs on submit and checks the value of "Make" and in case it's "nothing" just do a simple redirect instead of submitting the form. Something like:
var e = document.getElementById("Make");
var val = e.options[e.selectedIndex].value;
if (val === 'nothing'){
window.location = "http://www.google.com/"
}