Angular 5 ngModel changes the value in UI without saving it - html

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

Related

How do I reset select and ng-select to first option dynamically

UPDATE ::
https://stackblitz.com/edit/angular-ivy-tggo2e?file=src%2Fapp%2Fapp.component.ts
This stack is basically a TLDR of this post.
UPDATE 2::
Ok basically in that blitz, example 2 works. haha. in my code I was resetting that arr2 in my subscribe after the API call but doing it before the API call fixed it. Now I just have to figure out how to give it that first option (Pick something..) on initial load instead of a blank box.
///////////////////
So basically I have a cascade of select dropdowns. Lets call them form1, form2, form3.
When I select form1, it will call an API using that selection and dynamically give me an array to use for form2 options. same for form3,4,5,etc.
Now this is no problem up to here. But when I have selected form1,2,3 and then I select form1 again, I want form 2 and 3 to reset to my disabled option 1 but I can't seem to be able to get that to happen.
Component.ts
dropdownForm() {
this.dropdownForm = new FormGroup({
form1: new FormControl(),
form2: new FormControl(),
form3: new FormControl(),
form4: new FormControl()
)}
callAPI(query) {
// API CALL
}
changeONE(e) {
// this.arr2 = [];
// reset this.dropdownForm.form2 back to the first option 1('Pick something..) to be 'selected' and 'disabled'
// this.callAPI(e)
}
changeTWO(e) {
// this.arr3 = []
// reset this.dropdownForm.form3
this.callAPI(e)
}
changeTHREE(e) {
// this.arr4 = []
// reset this.dropdownForm.form4 -- this one is ng-select so it is way different than the others.
// this.callAPI(e)
}
HTML
<form [formGroup]="dropdownForm">
<div>
<div>
<label for="form1">Form1</label>
<select id="form1"
(change)="changeONE($event)">
<option [value]="" selected disabled>Pick something..</option>
<option [value]="item" *ngFor="let item of arr">{{item}}</option>
</select>
</div>
<div>
<label for="form2">Form2</label>
<select id="form2"
(change)="changeTWO($event)">
<option [value]="" selected disabled>Pick something..</option>
<option [value]="item" *ngFor="let item of arr2">{{item}}</option>
</select>
</div>
<div>
<label for="form3">Form3</label>
<select id="form3"
(change)="changeTHREE($event)">
<option [value]="" selected disabled>Pick something..</option>
<option [value]="item" *ngFor="let item of arr3">{{item}}</option>
</select>
</div>
<div>
<label for="form4">Form4:</label>
<ng-select [multiple]="true" placeholder="Pick something" (change)="changeFOUR($event)" >
<ng-option *ngFor="let item of arr4">{{item}}</ng-option>
</ng-select>
</div>
I've tried adding formControlname in my selects but that makes the select act weird for some reason... maybe its because my 'new FormControl('')' is wrong? But it makes my form1,2,3 just preselect something random in my optionsArr.
And even then, if i do this.dropdownForm.controls.form1.reset() or something like that, it doesn't do anything. it will just reset the value instead of the resetting the dropdown box(which I'm not even using anyways.. haha. I should be but I'm using using that changeONE() and $event to get the value)
Thank you
EDIT::
I just tried
component.ts
this.dropdownForm.get('form2').reset()
HTML
<select id="form1"
(change)="changeONE($event)" formControlName='form1'>
And basically when I have form1 and form2 selected and I go back and select form1 with that this.dropdownForm.get('form2').reset(), it won't reset form2. Instead, it will select the first item in the new updated arr2 (after i get arr2 from that API call) on the second option of that select instead of going to that disabled option one.

How can I change the index of array using angular 6?

I have this array in my typescript. I'm using angular 6.
formats: any = ['Years/Months/Days', 'Years/Months/Week', 'Months/Days', 'Week/Days', 'Week/Half Days', 'Week/4 Hours', 'Week/Hours', 'Days/Hours/30Min', 'Days/Hours/15Min'];
and this is my html code.
<select class="form-control" formControlName="format">
<option [ngValue]="null">{{'Select Type' | translate}}</option>
<option *ngFor="let format of formats" [ngValue]="format">{{format}}</option>
</select>
I want to change the dropdown value with help of next and prevoius button.
I recommend you to have a variable for storing the index of the selected option and initialize it to zero, every time the selected value gets changed update the index.
then you can create two buttons for next and previous with click event mapped to both buttons
the .ts file and function might look something like this
selectedindex:any = 0;
changed(event : Event):any{
console.log(event)
if( event.target){
console.log( this.formats.indexOf(this.yourformobject.controls['format'].value))
this.selectedindex = this.formats.indexOf(this.yourformobject.controls['format'].value;
}
}
next():any{
if(this.selectedindex < this.formats.length-1){
this.selectedindex++;
this.yourformobject.controls['format'].setValue(this.formats[this.selectedindex]);
}
}
previous():any{
if(this.selectedindex>0){
this.selectedindex--;
this.yourformobject.controls['format'].setValue(this.formats[this.selectedindex]);
}
}
and the Html look like this
<form [formGroup]="yourformobject">
<select class="form-control" formControlName="format" (click)="changed($event)">
<option [ngValue]="null">Select Type</option>
<option *ngFor="let format of formats" [ngValue]="format">{{format}}</option>
</select>
<button (click)="next()">next</button>
<button (click)="previous()">previous</button>
</form>

reset() method for resetting form fields results in errors

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

How i should set javascript global variable to get its value properly

I have two html elements on my page. One is dropdown and other is text field(which is working as autocomplete).
<select id="match_engine_brand" name="match_engine[brand]" class="hidden-field"><option value="">Select Brand</option><option value="3">addidas</option>
<option value="5">cat</option>
<option value="2">nike</option>
<option value="4">panther</option>
<option value="6">tower</option></select>
while text field is
<input class="string required ui-autocomplete-input" id="match_engine_shoe_model" name="match_engine[shoe_model]" placeholder="select model of shoe using autocomplete" required="required" size="50" type="text" autocomplete="off">
My cofeescript code is below
$(document).ready ->
$("#match_engine_brand").change ->
window.flag_value = $(this).val()
alert(window.flag_value) #value display in alert
$('#match_engine_shoe_model').autocomplete
source: "/user/match_shoes/shoes?id="+window.flag_value
select: (event, ui) -> $("#match_engine_shoe_model").val(ui.item.id)
In autocomplete function
window.flag_value #give me undefined value
$('#match_engine_brand :selected').val() #give me undefined value
How i can get dropdown value in autocomplete function.
Thanks for help
You need to have an initiated value of window.flag_value. Otherwise if you don't change #match_engine_branch, this var has no value. That's the reason of undefined value.
The way to solve it is to define this var before
$(document).ready ->
window.flag_value = "something"
...
However I think it's unnecessary to use global var. Check it in function should work.
$('#match_engine_shoe_model').autocomplete ->
dropdown_value = $("#match_engine_brand").val() ? "something"

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/"
}