Angular 4 select element multiple value and - html

I am trying to add a select HTML element with multiple attribute set to it in a normal Angular 4 reactive form.
When checked in Chrome developer console, it shows following HTML:
Actual:
<select class="form-control ..." formcontrolname="..." id="..." multiple="" name="..." required="" ...>
<option value="0: 'MBA'" ng-reflect-value="MBA">MBA</option>
<option value="1: 'MSc'" ng-reflect-value="MSc">MSc</option>
</select>
Expected:
<select class="form-control ..." formcontrolname="..." id="..." multiple="" name="..." required="" ...>
<option value="MBA" ng-reflect-value="MBA">MBA</option>
<option value="MSc" ng-reflect-value="MSc">MSc</option>
</select>
Why is the value and ng-reflect-value different.
This is creating problem for me to get selected values, set default values, etc.
This does not happen when multiple attribute is removed.
Any idea what is going wrong here. Yes, I have google this issue but couldn't find any solution.
Edit:
In Component:
//variables
form: FormGroup;
degrees: FormControl;
degree_list = ['MBA', 'MCA', ...];
//through constructor parameters
private _fb = FormBuilder;
//in ngOnInit
this.form = this._fb.group({
...
degrees: this._fb.control('');
...
});
In Template file:
...
<select class="form-control" name="degrees" id="degrees" formControlName="degrees" multiple required>
<option *ngFor="let degree of degree_list" [value]="degree">{{degree}}</option>
</select>
...

According to this: https://github.com/angular/angular/issues/12074#issuecomment-251475820 you can initialize your formcontrol with an empty array. Also since you are using a reactive form, remove the required from your template and instead set the Validator when you build the form:
ngOnInit() {
this.form = this._fb.group({
degrees: [[''], Validators.required]
});
}
Also notice I removed this._fb.control I'm not sure why you are using that :)
StackBlitz

Related

How can I swap option values of two HTML <select> elements?

I am trying to swap two select-option values in my currency converter. I have link icon which activates swapOptions function which swaps two values. This part works fine. The question is how to set this new values to "select" element?
This is my typescript function and I can see in console new values which should be set in select option:
startSwap:any;
endSwap: any;
swapOptions(firstOption: any, secondOption: any){
for(let i = 0; i < this.parsedJson.length; i++){
if(firstOption == this.parsedJson[i].Srednji){
this.endSwap = this.parsedJson[i].SelectOption;
}
else if(secondOption == this.parsedJson[i].Srednji){
this.startSwap = this.parsedJson[i].SelectOption;
}
}
console.log("New start option : "+this.startSwap)
console.log("New end option : "+this.endSwap)
}
This is my html. I have tried with [(ngModel)] but on change i get empty select elements.
<select name="options" #firstSelect id="slc" class="form-control" [(ngModel)]="startSwap">
<option *ngFor="let a of parsedJson;" class="form-control" (click)="firstSelectValues(a.Jedinica, a.Valuta)" (click)="intervalCurrencyStats()" [(value)]="a.Srednji">{{a.SelectOption}}</option>
</select>
<p id="p">End value: </i></p>
<select name="options2" #secondSelect id="slc" class="form-control" [(ngModel)]="endSwap">
<option *ngFor="let a of parsedJson;" class="form-control" (click)="secondSelectValues(a.Jedinica, a.Valuta)" [(value)]="a.Srednji">{{a.SelectOption}}</option>
</select>
On this picture you can see two select option elements and the blue arrow which is link to swapOption function. The empty fields are result of clicking the arrow.
Any advice is welcome. Thanks in advance!
Angular CLI: 9.1.8
Node: 12.13.0
After some time I have figured this one out.
Now using formGroup and form control
import { FormControl, FormGroup, FormsModule, FormBuilder } from '#angular/forms';
Some changes in HTML:
<form [formGroup]="crForm">
<select name="options" #firstSelect id="slc" class="form-control" formControlName="crControl">
...
</select>
<select name="options2" #secondSelect id="slc" class="form-control" formControlName="crEndControl">
...
</select>
</form>
And in typescript added private fb: FormBuilder in constructor, and formbuilder group for setting new values in select-option (also added inside onInit() with hardcoded default values):
this.crForm = this.fb.group({
crControl: [this.startSwap],
crEndControl: [this.endSwap]
})

Angular: selected directive on input not working

I have the following select in my template:
<select class="form-control" formControlName="tipo" name="tipo">
<option value="" selected disabled>(Select an option)</option>
<option value="FACT">Factura</option>
<option value="NOCRE">Nota Crédito</option>
</select>
however, despite I have put the selected directive to the first one, it does not show if the user does not click the select. It behaves like another option tag.
How can I make this option visible when the component loads without user interaction?
Since value is "" for 'Select..' option, set value "" in it's formcontrol
Working Demo
Try like this:
this.yourForm= new FormGroup({
'tipo':new FormControl(''),
});
why not Adding a model :
in your class :
tipo: string = "";
in HTML :
<select [(ngModel)]="tipo" class="form-control">
<option value="" selected disabled>(Select an option)</option>
<option value="FACT">Factura</option>
<option value="NOCRE">Nota Crédito</option>
</select>

Why can I not set a pre selected value to my select list in HTML with getElementById?

I am trying to set a pre selected option based on a previous select list (that part is not shown below). It's working with getelementById() when I use it on an <input> field but not on a <select>. Why is that?
Working example:
<label for="goalcategory">Edit assigned category</label>
<select id="selectedGoalcategory" class="form-control" required>
<option></option>
<option *ngFor="let goalcategory of allGoalcategories">{{goalcategory.description}}</option>
</select>
<input class="input" style="width:10%;" id="TestInput" type="text"/>
Typsescript behind it:
getCategoriByGoal()
{
var preSelectedGoalcategory = this.selectedGoal.goalcategory;
this.selectedGoalcategory = preSelectedGoalcategory;
(<HTMLInputElement>document.getElementById("TestInput")).value =
this.selectedGoalcategory.description;
}
The way I want it to work (HTML):
<label for="goalcategory">Edit assigned category</label>
<select id="selectedGoalcategory" class="form-control" required>
<option></option>
<option *ngFor="let goalcategory of allGoalcategories">{{goalcategory.description}}</option>
</select>
The way I want it to work (Typscript):
getCategoryByGoal()
{
var preSelectedGoalcategory = this.selectedGoal.goalcategory;
this.selectedGoalcategory = preSelectedGoalcategory;
(<HTMLInputElement>document.getElementById("selectedGoalcategory")).value =
this.selectedGoalcategory.description;
}
If you dont mind adding 3rd party components, you could add ng-select, it would make your life easier for a lot of things.
Install ng-select from npm:
npm install --save #ng-select/ng-select
After that add it to your module along with FormsModule:
import { NgSelectModule } from '#ng-select/ng-select';
import { FormsModule } from '#angular/forms';
#NgModule({
declarations: [AppComponent],
imports: [NgSelectModule, FormsModule],
bootstrap: [AppComponent]
})
export class AppModule {}
And in your HTML you can use it like this:
<ng-select [items]="allGoalcategories" bindLabel="name" bindValue="id" name="goalcategories"
[(ngModel)]="selectedGoalcategory">
</ng-select>
Now every time you change selectedGoalcategory it will reflect in your other dropdown, and you dont need to use getElementById
As #wentjun said, there is no need to rely on document.getElementById() for this scenario.
To get the value of the dropdown you would need to bind the "selectedGoalcategory" to the dropdown and follow below:
<select [(ngModel)]="selectedGoalCategory">
<option></option>
<option *ngFor="let goalcategory of goalCategories" [value]="goalcategory.id">{{ goalcategory.name }}</option>
</select>
So "preselect" a value, you just set the value of "dropDownValue" to one of the values in the dropdown.
I'm not sure why you need the input field, but if you want the input field to reflect the value of the dropdown, then you would do this:
<input class="input" style="width:10%;" id="TestInput" type="text" [(ngModel)]="selectedGoalCategory" />

static angular select option

<input [formControl]="twitterHandle" id="twitterHandle" placeholder="twitterHandle">
in there i get input via that and using following code get the input value
twitterHandle=new FormControl();
twitterHandle:this.twitterHandle.value,
simillar way i need to add static select input to form how to do that and how to edit following
<select>
<option value="option">country1</option>
<option value="option1">Sri lanka</option>
<option value="option2">Canada</option>
</select>
You just have to define another formControl :
selectControl : FormControl = new FormControl();
and you can initialize the control :
ngOnInit(){
this.selectControl.setValue('option')
}
In your template ,
<form>
<select [formControl]='selectControl' (change)='test()'>
<option [value]='"option"'>Option1</option>
<option [value]='"option1"'>Option2</option>
</select>
</form>
you can check the value changes in the test() as defined below :
test(){
console.log(this.selectControl.value);
}
You can See the example : https://angular-wytvwr.stackblitz.io
Hope this helps

conditions for select - HTML or Javascript/Jquery

I have the following code:
<select class="form-control" required>
<option *ngFor="let car of cars" type="text">{{car.Name}}</option>
</select>
my problem is that i can get just a name, so *ngFor fails.
is there a way in HTML to make a condition like. If not Javascript or Jquery
//There are more than 1 option
if(options.length>1){<option *ngFor="let car of cars" type="text">{{car.Name}}</option>}
//There is only an option
else {<option *ngIf="car" type="text">{{car.Name}}</option>}
Car
export class Car {
id: String;
name: [{
brand: String,
}
}]
}
JSON returns an Array[] when there are more than one element. If not, it returns an Object{} so I can not use *ngFor
Solved
The problem was in the back-end, and not in the front-end
You can use *ngIf directive like:
<select id="oneICO" class="form-control" required *ngIf="cars.length > 1">
<option *ngFor="let car of cars">{{car.Name}}</option>
</select>
<input type="text" *ngIf="cars.length < 2">{{car.Name}}</input>
Checking if a variable is an array in the template is sort of nasty How to check type of variable in ngIf in Angular2
It would be better to check if !(cars instanceof Array) and then turn it into an array in your javascript code.
In html you can use ngif in angular2
<div *ngIf="options.length>1">
<option *ngFor="let car of cars" type="text">{{car.Name}}</option>
</div>
or simple put the next code in html
<option *ngIf="options.length == 1 " type="text">{{car.Name}}</option>
cars is not a collection so you don't need any angular directives:
<select id="oneICO" class="form-control" required>
<option>{{cars.Name}}</option>
</select>
In which case, rename cars to car so that it signifies a single item.
[It is a little pointless, though, have a select with only a single option.]
Note that an option does not have a type attribute.
Your original code is fine. There's nothing wrong with it.
<select id="oneICO" class="form-control" required>
<option *ngFor="let car of cars" type="text">{{car.Name}}</option>
</select>
If you have single car, make an array of single element and it will work just fine.
cars = ['Honda']
If you have multiple cars, you'll have something like this.
cars = ['Honda', 'Toyota', 'Mitsubishi']