(Angular 5) *ngIf not working on Select/Options - html

I have a model Questionaire which has name property.
app.component.ts
import {Questionaire} from '../questionaire.model';
questionaire : Questionaire;
Based on the name property of class Questionaire in my html code I need to display different option value of the select element using *ngIf this is
what I am trying to do in app.component.html
<select
class="form-control"
name="proposal"
required
ngModel
>
<div *ngIf = "questionaire.name === 'credit'">
<option value="">Select</option>
<option value="Proposal">Proposal</option>
<option value="ndg">NDG</option>
<option value="credit">Credit Line</option>
</div>
<div *ngIf = "questionaire.name === 'asset'">
<option value="">Select</option>
<option value="Proposal">Proposal</option>
<option value="asset">Asset</option>
</div>
</select>
I am not able to achieve what I am trying to do.
I hope I am clear.

You should really move your data logic inside the typescript part of your component. Your template should only contain presentation logic
public interface Kvp {
value: string;
label: string;
}
export class AppComponent implements OnInit {
questionaire : Questionaire;
options: Kvp[];
ngOnInit(): void {
if (this.questionnaire.name === 'credit') {
this.options = [
{value: 'Proposal', label: 'Proposal'},
{value: 'ndg', label: 'NDG'}
];
// You can do the rest ;-)
}
}
}
Then, inside your template, simply iterate through "options"
<select class="form-control"
name="proposal"
required
ngModel>
<option value="">Select</option>
<option *ngFor="let item from options" value="{{item.label}}">{{item.value}}</option>
</select>
note: You really shouldn't have any business logic inside your AppComponent. This component should only contain sub-components.

Instead of using *ngIf on a div i used it on a ng-container and it worked for me.
Here is the piece of code:
<select
class="form-control"
name="proposal"
required
ngModel
>
<option value="">Select</option>
<option value="Proposal">Proposal</option>
<ng-container *ngIf = "questionaire.name === 'credit'">
<option value="ndg">NDG</option>
<option value="credit">Credit Line</option>
</ng-container>
<ng-container *ngIf = "questionaire.name === 'asset'">
<option value="asset">Asset</option>
</ng-container>
</select>
I hope it may help.

Use ng-template instead of Div like this:
<select class="form-control" name="proposal" required ngModel *ngIf="questionaire.name === 'credit' else asset ">
<option value="">Select</option>
<option value="Proposal">Proposal</option>
<option value="ndg">NDG</option>
<option value="credit">Credit Line</option>
</select>
<ng-template #asset>
<option value="">Select</option>
<option value="Proposal">Proposal</option>
<option value="asset">Asset</option>
</ng-template>

Related

How to call an angular function within another function?

I have three select options in my html page. Based on the three selecting values I need to write a value in another text box.
<select (change)="aaFilter($event.target.value)" class="form-control">
<option *ngFor="let type of aa" [value]="type.value">
{{type.display}}
</option>
</select>
<select (change)="bbFilter($event.target.value)" class="form-control">
<option *ngFor="let type of bb" [value]="type.value">
{{type.display}}
</option>
</select>
<select (change)="ccFilter($event.target.value)" class="form-control">
<option *ngFor="let type of cc" [value]="type.value">
{{type.display}}
</option>
</select>
So I have Onchange function in every select box. Now In my typescript file my
aaFilter(selectedaa:string){
console.log('value is ',selectedaa);
}
Likewise I have written three functions. But based on this values I need to set up a value in textbox.
headerName(){
//Here I need to take up the threee selected values from drop down & do some function based on that.
}
How can that be done in angular 6 & typescript?
In component:
Public selectedValues = [];
aaFilter(value, index){
this.selectedValues[index] = value;
this.updateModelInput();
}
bbFilter(value, index){
this.selectedValues[index] = value;
this.updateModelInput();
}
ccFilter(value, index){
this.selectedValues[index] = value;
this.updateModelInput();
}
updateModelInput(){
if(this.selectedValues.length === 3){
// UPDATE THE VALUE IN TEXT BOX
}
}
From Template, you can pass value 0, 1, 2 as 2nd parameter in change method.
Well, you haven't bound anything to the select options have you?
<select
[(ngModel)] ="filterA"
(change) ="headerName()"
class ="form-control">
<option *ngFor="let type of aa" [value]="type.value">
{{type.display}}
</option>
</select>
<select
[(ngModel)] ="filterB"
(change) ="headerName()"
class ="form-control">
<option *ngFor ="let type of bb" [value]="type.value">
{{type.display}}
</option>
</select>
<select
[(ngModel)] ="filterC"
(change) ="headerName()"
class ="form-control">
<option *ngFor="let type of cc" [value]="type.value">
{{type.display}}
</option>
</select>
In your component file:
headerName()
{
/* Do whatever this function is supposed to do whenever one of the
filters is changed. The variables filterA, filterB and filterC will
now always have the most recent values for you to operate on */
}

use single ngFor loop to display two distinct optgroup in select tag for angular 4

I have a dummy Array of Objects as follows:
this.historyOfWords = [
{
'property': 'property1',
'type': 'dataprop',
'value': 'value1'
},
{
'property': 'Ref1',
'type': 'objprop',
'value': 'Prop of Ref1'
}
];
I am looking to sort the above mentioned information into <optgroup> for the <select> tag
My current implementation is as follows:
<select size="10">
<optgroup label="Properties"> <!-- all type of data that is not `objprop`-->
<option *ngFor="let eachVal of historyOfWords">
<div *ngIf="eachVal.type!='objprop'"> <!-- test type here -->
{{eachVal.property}}</div>
</option>
</optgroup>
<optgroup label="References to Properties">
<option *ngFor="let eachVal of historyOfWords"> <!-- need to run the loop again-->
<div *ngIf="eachVal.type==='objprop'">{{eachVal.property}}</div>
</option>
</optgroup>
</select>
I tried the logic if else logic in angular similarly
<select size="10">
<optgroup label="Properties"> <!-- all type of data that is not `objprop`-->
<option *ngFor="let eachVal of historyOfWords">
<div *ngIf="eachVal.type=='dataprop'; else ref;"> <!-- test type here -->
{{eachVal.property}}</div>
</option>
</optgroup>
<optgroup label="References to Properties">
<ng-template #ref> <-- ELSE show this -->
<option *ngFor="let eachVal of historyOfWords"> <!-- need to run the loop again-->
<div>{{eachVal.property}}</div> <!-- need to put some logic here again -->
</option>
</optgroup>
</select>
The problem is eachVal is outside the scope of the first optgroup and hence not available so I need to loop over again.
What is an optimal way to display two distinct values under optgroup without looping more times.
Filter the data ahead of time. It's always a good idea to keep as much of the logic as possible in the component class, and not in the template.
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `
<select>
<optgroup label="Properties">
<option *ngFor="let eachVal of notObjProp">
<div> {{eachVal.property}}</div>
</option>
</optgroup>
<optgroup label="References to Properties">
<option *ngFor="let eachVal of objProp">
<div>{{eachVal.property}}</div>
</option>
</optgroup>
</select>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
data = [
{
'property': 'property1',
'type': 'dataprop',
'value': 'value1'
},
{
'property': 'Ref1',
'type': 'objprop',
'value': 'Prop of Ref1'
}
];
objProp = this.data.filter(({ type }) => type === 'objprop');
notObjProp = this.data.filter(({ type }) => type !== 'objprop');
}
Live demo
interface optgroup {
label: string,
options: {value: string, name:string}[]
}
<optgroup
*ngFor="let group of optgroup"
[label]="group.label"
>
{{ group.label }}
<option
*ngFor="let option of group.options; index as i"
class="title"
[value]="option.value"
>
{{ i + 1 }}. {{ option.name }}
</option>
</optgroup>

Bootstrap´s 4 PlaceHolder on Select Angular 4

i made a Select with dynamic values using ngModel directive and the Bootstrap Framework, it works. My problem is that i want to add a placeholder, but the ng directive seems to ruining it.
Here is what i have:
<select [(ngModel)]="usuario.pais" name="s" class="form-control">
<option value="">Select a Country</option><!--My PlaceHolder-->
<option *ngFor="let pais of paises" value="pais.codigo">{{pais.nombre}}</option>
</select>
Any suggestions?
Maybe try this:
In TS:
public usuario = {pais: ''};
public paises = [{nombre: 'la France', codigo: 'fr'}, {nombre: 'deutscheland', codigo: 'de'}];
in HTML:
<select [(ngModel)]="usuario.pais" name="s" class="form-control">
<option value="">Select a Country</option>
<option *ngFor="let pais of paises" [value]="pais.codigo">
{{pais.nombre}}
</option>
</select>

Value of select Angular issue

I have the following code:
component.html:
<select id="select" (change)="updateValue(this.value)">
<option *ngFor="let option of filteredOptions" value="{{option .Id}}"></option>
</select>
component.ts:
updateValue(value: number){
this.value= value;
}
I can get the value of the select using jQuery or vanilla JS by selecting by ID.
Question
How can I pass in the value of the select using Angular?
For two-way binding, the [(ngModel)]="value" binding is missing. Try the following:
<select id="select" [(ngModel)]="selectedvalue">
<option *ngFor="let option of filteredOptions" value="{{option .Id}}"></option>
</select>
Now you can use the "selectedvalue" in your component.
For one-way binding, use $event.value. Try the following:
<select id="select" (change)="updateValue($event.value)">
<option *ngFor="let option of filteredOptions" value="{{option .Id}}"></option>
</select>
Demo: https://plnkr.co/edit/zxiDsiMg9GFA6nRxr5ly?p=preview
I solved it
<select id="select" (change)="updateValue($event.target.value)">
<option *ngFor="let option of filteredOptions" value="{{option .Id}}" class="select-option"></option>
</select>

How to have a default "please select" option on an Angular select element with a null value for validation?

I have a select HTML element in an Angular ngFor loop:
<select formControlName="type" required>
<option *ngFor="let type of typeList" [ngValue]="type.value">{{ type.caption }}</option>
</select>
In Internet Explorer, the first item in the list is selected when the template loads, but it's value isn't set in the form control, so causes a 'required' validation error until another value is selected in the list. I want to have a 'Please select' option that has a null value to prevent this happening.
This is for Angular 2+ used with or without TypeScript
Add an option like so:
<option [ngValue]="null">Please select</option>
So your control will look like:
<select formControlName="type" required>
<option [ngValue]="null">Please select</option>
<option *ngFor="let type of typeList" [ngValue]="type.value">{{ type.caption }}</option>
</select>
This works as Angular inspects the value attribute because of the square brackets. The value becomes a true null, unlike if we used value="" (this is just an empty string and doesn't match null).
In case you're not using ngForm, another approach to implementing the selected value is to do something like [value]='selectedType' (change)='selectedType = $event.target.value' in your select tag. For example:
In your component.ts:
public selectedType: string;
In your component.html
<select [value]='selectedType' (change)='selectedType = $event.target.value'>
<option value=''>-- Select your Type --</option>
<option *ngFor="let type of typeList" [ngValue]="type.value">{{ type.caption }}</option>
</select>
component.ts
public selectedValue = 'None';
component.html:
<div ">
<label>Highlight</label>
<select [(ngModel)]="selectedTrunk" (change)="onChangeTrunk($event)">
<option value='None'>None</option>
<option *ngFor="let trunklist of DRLNameTrunkList" [selected]="trunk" [value]="trunklist.SIPTRUNKNAME">{{trunklist.SIPTRUNKNAME}}</option>
</select>
</div>
This is my code pelase modify as per your requirements