How to get .json objects by id in Angular 2? - html

I'm trying to get objects by id from a JSON file after selecting an item from my drop-down list. So far I have managed to retrieve all the objects from JSON but not by ID.
Typescript
showInfo() {
var selected = this.diadikasies.filter(x=> x.content);
console.log (selected);
}
HTML
<div *ngIf="diadikasies && diadikasies.length > 0" class="form-group">
<label for="diadikasies">
<i class="fas fa-clipboard-list" aria-hidden="true"></i> Please Select: </label>
<select #proc (change)="showInfo()">
<option [ngValue]="undefined" disabled selected>Επιλέξτε Διαδικασία</option>
<option *ngFor="let diad of diadikasies" [value]="diad.id">{{ diad.title.rendered }}</option>
</select>
</div>
Thanks in advance.

You can do with find() method like below
TS file
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
description;
opts = [{
id: 1,
name: 'Test 1',
description: 'This is Test 1 description'
}, {
id: 2,
name: 'Test 2',
description: 'This is Test 2 description'
}];
showInfo(value) {
let selectedOpt = this.opts.find(opt => opt.id == value);
this.description = selectedOpt.description;
}
}
In the template file
<div *ngIf="opts && opts.length > 0" class="form-group">
<label for="opts">
<i class="fas fa-clipboard-list" aria-hidden="true"></i> Please Select: </label>
<select #proc (change)="showInfo(proc.value)">
<option [ngValue]="undefined" disabled selected>Επιλέξτε Διαδικασία</option>
<option *ngFor="let diad of opts" [value]="diad.id">{{ diad.name }}</option>
</select>
</div>
<div>{{ description }}</div>
You can find the working example from here Stackblitz

You can use ngModel and ngModelChange together to get the selected value
<select #proc [(ngModel)]="selectedObj" (ngModelChange)="showInfo()">
and inside showInfo method,
var selected = this.diadikasies.filter(x=> x.id == this.selectedObj.id);

Related

How to loop the formcontrolname dynamically along with validation

I want to validate the multiple looping of dynamic formControlName="xxx" in select field
My html code
<ul *ngFor="let detaillist of stressli.stresstabdetails;">
<li>
<div class="form-container">
<select [(ngModel)]="detaillist.stressname" class="form-control" formControlName="spotstressname {{q + 1 }}">
<option [ngValue]="undefined" selected>Select an option</option>
<option *ngFor="let item of stressdata;" [ngValue]="item">{{item}}</option>
</select>
</div>
</li>
</ul>
TS file validation:
this.CaseDetailsForm = this.formBuilder.group({
spotstressname1:['', Validators.required],
spotstressname2:['', Validators.required],
});
In .ts file I hardcoded the spotstressname1, spotstressname2, etc.
Instead of hardcoded value I need dynamically as Output. How can I get that?
First of all... DON'T use ngModel with reactive forms, you need to decide whether you want to use ngModel or reactive forms, not both!
Here in this sample we go full reactive. So how to create your formcontrols dynamically... I would do:
constructor(private fb: FormBuilder) {
this.CaseDetailsForm = this.fb.group({});
}
ngOnInit() {
// add dynamic form controls named 'spotstressname' and index
this.stressli.stresstabdetails.map((x, i) => {
this.CaseDetailsForm.addControl('spotstressname'+i, this.fb.control(x.stressname))
})
}
Then in the template we can use the keyvalue pipe to iterate the form controls of the form in the template:
<div *ngFor="let ctrl of CaseDetailsForm.controls | keyvalue">
<select [formControlName]="ctrl.key">
<option value="">Select an option</option>
<option *ngFor="let item of stressdata;" [value]="item">{{item}}</option>
</select>
</div>
STACKBLITZ DEMO
this.data = [
{
controlName: 'Username',
controlType: 'text',
valueType: 'text',
placeholder: 'Enter username',
validators: {
required: true,
minlength: 5
}
},
{
controlName: 'Deposit From',
controlType: 'date',
valueType: 'date',
placeholder: 'Deposit From',
modelVal:"depositFrom",
validators: {
required: true
}
}];
this.data.forEach(formControl => {
formGroup[formControl.controlName] = new FormControl('');
});

How to add a search filter to a select option in angular

I'm trying to add to add a search filter in my select option list because there are many options and I think that without a search, it will not be easy for the user to find the option that he wants to select.
I hope you will understand me because I'm not good at English.
Here's my code (it's just a part of my table)
<ng-container *ngFor="let menaceProcessus of menaceProcessusTab">
<tr>
<td colspan="4" bgcolor="#f1f1f1"><b>{{menaceProcessus?.processus?.nom}}</b></td>
</tr>
<ng-container *ngFor="let actif of menaceProcessus?.actifs">
<tr>
<td [rowSpan]="actif?.menaces?.length+1">{{actif?.actif?.nom}}</td>
</tr>
<ng-container *ngFor="let mnVuln of actif?.menaces">
<tr>
<td>{{mnVuln?.vulnerabilite?.nom}}</td>
<td>
<select class="form-control"
(change)="mnVuln?.menaceActif?.menace.id = $event.target.value;
updateMenaceProcessus()">
<option></option>
<option *ngFor="let menace of menaces"
[value]="menace.id"
[selected]="menace.id === mnVuln?.menaceActif?.menace.id">
{{menace.nom}}</option>
</select>
</td>
<td>
<input class="form-control"
type="text" [value]="mnVuln?.menaceActif?.probabilite">
</td>
</tr>
</ng-container>
</ng-container>
</ng-container>
If you want to filter in select option, you can use datalist control of HTML. If you use it, there is no need to do extra coding for filtering. It has built-in functionality for filtering.
HTML :
<input list="menace" name="menace">
<datalist id="menace">
<option *ngFor="let menace of menaces">{{menace.nom}} </option>
</datalist>
I think you can use ng-select: https://www.npmjs.com/package/#ng-select/ng-select
for Yor Requirement
If you want to filter your array menaces by typing on the first letter, then it is possible to filter your array like this:
HTML:
<select class="form-control"
(change)="mnVuln?.menaceActif?.menace.id = $event.target.value;
updateMenaceProcessus();
filterMenaces($event)">
<option></option>
<option *ngFor="let menace of menaces"
[value]="menace.id"
[selected]="menace.id === mnVuln?.menaceActif?.menace.id">
{{menace.nom}}</option>
</select>
TypeScript:
origMenaces = [];
methodAPIToGetMenaces() {
this.yourService()
.subscribe(s=> {
this.menaces = s;
this.origMenaces = s;
});
}
filterMenaces(str: string) {
if (typeof str === 'string') {
this.menaces = this.origMenaces.filter(a => a.toLowerCase()
.startsWith(str.toLowerCase()));
}
}
UPDATE 1:
If you want to filter by input value:
HTML:
<input type="text"
(ngModelChange)="filterItem($event)"
[(ngModel)]="filterText">
<br>
<select
#selectList
[(ngModel)]="myDropDown"
(ngModelChange)="onChangeofOptions($event)">
<option value="empty"></option>
<option *ngFor="let item of items">
{{item}}
</option>
</select>
<p>items {{ items | json }}</p>
TypeScript:
import { Component, ViewChild, ElementRef, AfterViewInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular 4';
myDropDown : string;
items = ['one', 'two', 'three'];
origItems = ['one', 'two', 'three'];
#ViewChild('selectList', { static: false }) selectList: ElementRef;
onChangeofOptions(newGov) {
console.log(newGov);
}
filterItem(event){
if(!event){
this.items = this.origItems;
} // when nothing has typed*/
if (typeof event === 'string') {
console.log(event);
this.items = this.origItems.filter(a => a.toLowerCase()
.startsWith(event.toLowerCase()));
}
console.log(this.items.length);
this.selectList.nativeElement.size = this.items.length + 1 ;
}
}
Please, see work example at stackblitz
I couldn't find any easy way to do this for the select, but the autocomplete
component seems to do something very close to what is desired. The only issue with it is, that it does not require the value to be one of the options. That's why I created the following directive:
// mat-autocomplete-force-select.directive.ts
import { Directive, Input } from '#angular/core';
import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator } from '#angular/forms';
import { MatAutocomplete } from '#angular/material/autocomplete';
#Directive({
selector: '[matAutocomplete][appMatAutocompleteForceSelect]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: MatAutocompleteForceSelectDirective,
multi: true,
}
]
})
export class MatAutocompleteForceSelectDirective implements Validator {
#Input('matAutocomplete')
matAutocomplete!: MatAutocomplete;
validate(control: AbstractControl): ValidationErrors | null {
if (this.matAutocomplete.options && !this.isOptionOfAutocomplete(control.value)) {
return { 'notAnAutocompleteValue' : true }
}
return null;
}
private isOptionOfAutocomplete(value: string) {
return this.matAutocomplete.options.find(option => option.value === value) !== undefined;
}
}
After that, you can add the directive to the input of the autocomplete, and it will have an error of notAnAutocompleteValue if it's not that.
<input matInput type="text" appMatAutocompleteForceSelect [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" >
<!-- ... -->
</mat-autocomplete>
For anyone unfamiliar with the autocomplete component, https://material.angular.io/components/autocomplete/overview will be helpful.
Cheers :)
<input list="menace" name="menace">
<datalist id="menace">
<option *ngFor="let menace of menaces">{{menace.nom}} </option>
</datalist>
This works fine and in the case of a form just add a form control name and the value can be picked. Answered by #ParthDhankecha

Angular ngIf formGroup

I have a form on Angular that allows to display an input according to the value selected in a drop-down list.
Here is an example of my code:
(If two is selected an input appears)
https://stackblitz.com/edit/angular-fqkfyx
If I leave the [formGroup] = "usForm" the input display does not work. On the other hand if I delete [formGroup] = "usForm" of the tag form my code works as I want. So the problem is related to [formGroup] = "usForm"
My html:
<div class="offset-md-2">
<form [formGroup]="usForm">
<div class="div-champs">
<p id="champs">Type
<span id="required">*</span>
</p>
<div class="select-style ">
<select [(ngModel)]="selectedOption" name="type">
<option style="display:none">
<option [value]="o.name" *ngFor="let o of options">
{{o.name}}
</option>
</select>
</div>
</div>
<p id="champs" *ngIf="selectedOption == 'two'">Appears
<input type="appears" class="form-control" name="appears">
</p>
</form>
</div>
My component.ts:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder } from '#angular/forms';
#Component({
selector: 'app-create-us',
templateUrl: './create-us.component.html',
styleUrls: ['./create-us.component.css']
})
export class CreateUsComponent implements OnInit {
public usForm: FormGroup;
public selectedOption: string;
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.createForm();
}
createForm() {
this.usForm = this.fb.group({
'type': [null, ],
'appears': [null, ],
});
}
options = [
{ name: 'first', value: 1 },
{ name: 'two', value: 2 }
];
}
I simplified my problem as much as in reality it is in a large form with a dozen input
I need your help, thanks in advance
Regards,
Valentin
You should be using formControlName instead of [(ngModel)].
And then in comparison, you should be comparing to usForm.value.type instead of the selectedValue.
Give this a try:
<div class="offset-md-2">
<form [formGroup]="usForm">
<div class="div-champs">
<p id="champs">Type
<span id="required">*</span>
</p>
<div class="select-style ">
<select formControlName="type" name="type">
<option style="display:none">
<option [value]="o.name" *ngFor="let o of options">
{{o.name}}
</option>
</select>
</div>
</div>
<p id="champs" *ngIf="usForm.value.type == 'two'">Appears
<input type="appears" class="form-control" name="appears">
</p>
</form>
</div>
Here's a Sample StackBlitz for your ref.
Your template is loaded before form group is created. Add ngIf to wail while form group will be created:
<div class="offset-md-2" *ngIf="usForm">
<form [formGroup]="usForm">

Binding select element to object in Angular

I'd like to bind a select element to a list of objects -- which is easy enough:
#Component({
selector: 'myApp',
template:
`<h1>My Application</h1>
<select [(ngModel)]="selectedValue">
<option *ngFor="#c of countries" value="c.id">{{c.name}}</option>
</select>`
})
export class AppComponent{
countries = [
{id: 1, name: "United States"},
{id: 2, name: "Australia"}
{id: 3, name: "Canada"},
{id: 4, name: "Brazil"},
{id: 5, name: "England"}
];
selectedValue = null;
}
In this case, it appears that selectedValue would be a number -- the id of the selected item.
However, I'd actually like to bind to the country object itself so that selectedValue is the object rather than just the id. I tried changing the value of the option like so:
<option *ngFor="#c of countries" value="c">{{c.name}}</option>
but this does not seem to work. It seems to place an object in my selectedValue -- but not the object that I'm expecting. You can see this in my Plunker example.
I also tried binding to the change event so that I could set the object myself based on the selected id; however, it appears that the change event fires before the bound ngModel is updated -- meaning I don't have access to the newly selected value at that point.
Is there a clean way to bind a select element to an object with Angular 2?
<h1>My Application</h1>
<select [(ngModel)]="selectedValue">
<option *ngFor="let c of countries" [ngValue]="c">{{c.name}}</option>
</select>
StackBlitz example
NOTE: you can use [ngValue]="c" instead of [ngValue]="c.id" where c is the complete country object.
[value]="..." only supports string values
[ngValue]="..." supports any type
update
If the value is an object, the preselected instance needs to be identical with one of the values.
See also the recently added custom comparison https://github.com/angular/angular/issues/13268
available since 4.0.0-beta.7
<select [compareWith]="compareFn" ...
Take care of if you want to access this within compareFn.
compareFn = this._compareFn.bind(this);
// or
// compareFn = (a, b) => this._compareFn(a, b);
_compareFn(a, b) {
// Handle compare logic (eg check if unique ids are the same)
return a.id === b.id;
}
This could help:
<select [(ngModel)]="selectedValue">
<option *ngFor="#c of countries" [value]="c.id">{{c.name}}</option>
</select>
You can do this too without the need to use [(ngModel)] in your <select> tag
Declare a variable in your ts file
toStr = JSON.stringify;
and in you template do this
<option *ngFor="let v of values;" [value]="toStr(v)">
{{v}}
</option>
and then use
let value=JSON.parse(event.target.value)
to parse the string back into a valid JavaScript object
It worked for me:
Template HTML:
I added (ngModelChange)="selectChange($event)" to my select.
<div>
<label for="myListOptions">My List Options</label>
<select (ngModelChange)="selectChange($event)" [(ngModel)]=model.myListOptions.id >
<option *ngFor="let oneOption of listOptions" [ngValue]="oneOption.id">{{oneOption.name}}</option>
</select>
</div>
On component.ts:
listOptions = [
{ id: 0, name: "Perfect" },
{ id: 1, name: "Low" },
{ id: 2, name: "Minor" },
{ id: 3, name: "High" },
];
An you need add to component.ts this function:
selectChange( $event) {
//In my case $event come with a id value
this.model.myListOptions = this.listOptions[$event];
}
Note:
I try with [select]="oneOption.id==model.myListOptions.id" and not work.
============= Another ways can be: =========
Template HTML:
I added [compareWith]="compareByOptionId to my select.
<div>
<label for="myListOptions">My List Options</label>
<select [(ngModel)]=model.myListOptions [compareWith]="compareByOptionId">
<option *ngFor="let oneOption of listOptions" [ngValue]="oneOption">{{oneOption.name}}</option>
</select>
</div>
On component.ts:
listOptions = [
{ id: 0, name: "Perfect" },
{ id: 1, name: "Low" },
{ id: 2, name: "Minor" },
{ id: 3, name: "High" },
];
An you need add to component.ts this function:
/* Return true or false if it is the selected */
compareByOptionId(idFist, idSecond) {
return idFist && idSecond && idFist.id == idSecond.id;
}
Just in case someone is looking to do the same using Reactive Forms:
<form [formGroup]="form">
<select formControlName="country">
<option *ngFor="let country of countries" [ngValue]="country">{{country.name}}</option>
</select>
<p>Selected Country: {{country?.name}}</p>
</form>
Check the working example here
In app.component.html:
<select type="number" [(ngModel)]="selectedLevel">
<option *ngFor="let level of levels" [ngValue]="level">{{level.name}}</option>
</select>
And app.component.ts:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
levelNum:number;
levels:Array<Object> = [
{num: 0, name: "AA"},
{num: 1, name: "BB"}
];
toNumber(){
this.levelNum = +this.levelNum;
console.log(this.levelNum);
}
selectedLevel = this.levels[0];
selectedLevelCustomCompare = {num: 1, name: "BB"}
compareFn(a, b) {
console.log(a, b, a && b && a.num == b.num);
return a && b && a.num == b.num;
}
}
For me its working like this, you can console event.target.value.
<select (change) = "ChangeValue($event)" (ngModel)="opt">
<option *ngFor=" let opt of titleArr" [value]="opt"></option>
</select>
The key is to use a two way binding in the select via [(ngModel)] and use [ngValue] in each option.
You can even have a default null option and it works with Angular 12.
<select name="typeFather" [(ngModel)]="selectedType">
<option [ngValue]="null">Select a type</option>
<option *ngFor="let type of types" [ngValue]="type">{{type.title}}</option>
</select>
That approach is always going to work, however if you have a dynamic list, make sure you load it before the model.
You Can Select the Id using a Function
<option *ngFor="#c of countries" (change)="onchange(c.id)">{{c.name}}</option>
Create another getter for selected item
<form [formGroup]="countryForm">
<select formControlName="country">
<option *ngFor="let c of countries" [value]="c.id">{{c.name}}</option>
</select>
<p>Selected Country: {{selectedCountry?.name}}</p>
</form>
In ts :
get selectedCountry(){
let countryId = this.countryForm.controls.country.value;
let selected = this.countries.find(c=> c.id == countryId);
return selected;
}
Also, if nothing else from given solutions doesn't work, check if you imported "FormsModule" inside of "AppModule", that was a key for me.
You can get selected value also with help of click() by passing the selected value through the function
<md-select placeholder="Select Categorie"
name="Select Categorie" >
<md-option *ngFor="let list of categ" [value]="list.value" (click)="sub_cat(list.category_id)" >
{{ list.category }}
</md-option>
</md-select>
use this way also..
<h1>My Application</h1>
<select [(ngModel)]="selectedValue">
<option *ngFor="let c of countries" value="{{c.id}}">{{c.name}}</option>
</select>
Attention Angular 2+ users:
for some reason, [value] does not work on elements. use [ngModel] instead.
<select [ngModel]="selectedCountry">
<option *ngFor="let country of countries" [value]="country">{{country.name}}</option>
</select>
Tested on Angular 11. I need an extra object 'typeSelected'. Pay attention I'm not using [(ngValue)] as other answers do:
<mat-select formControlName="type" [(value)]="typeSelected"
[compareWith]="typeComparation">
<mat-option *ngFor="let myType of allSurveysTypes" [value]="myType">
{{myType.title}}
</mat-option>
</mat-select>
//Declaration.
typeSelected: SurveyType;
...
//Assigning variable 'type' of object 'survey' to 'typeSelected'.
this.typeSelected = survey?.type;
...
//Function to compare SurveyType objects.
typeComparation = ( option, value ) => {
if (option && value) {
return option.id === value.id;
}
}
This code is very simple:
<select class="form-control" id="marasemaat" [(ngModel)]="fullNamePresentor"
[formControl]="stateControl" (change)="onSelect($event.target.value)">
<option *ngFor="let char of programInfo1;let i = index;"
onclick="currentSlide(9,false)"
value={{char.id}}>{{char.title + " "}} ----> {{char.name + " "+ char.family }} ---- > {{(char.time.split('T', 2)[1]).split(':',2)}}</option>
</select>

Get current value when change select option - Angular2

I'm writing an angular2 component and am facing this problem.
Description: I want to push an option value in select selector to its handler when the (change) event is triggered.
Such as the below template:
<select (change)="onItemChange(<!--something to push-->)">
<option *ngFor="#value of values" value="{{value.key}}">{{value.value}}</option>
</select>
Component Class:
export Class Demo{
private values = [
{
key:"key1",
value:"value1"
},
{
key:"key2",
value:"value2"
}
]
constructor(){}
onItemChange(anyThing:any){
console.log(anyThing); //Here I want the changed value
}
}
How can I get the value(without using jquery) ?
There is a way to get the value from different options. check this plunker
component.html
<select class="form-control" #t (change)="callType(t.value)">
<option *ngFor="#type of types" [value]="type">{{type}}</option>
</select>
component.ts
this.types = [ 'type1', 'type2', 'type3' ];
callType(value) {
console.log(value);
this.order.type = value;
}
In angular 4, this worked for me
template.html
<select (change)="filterChanged($event.target.value)">
<option *ngFor="let type of filterTypes" [value]="type.value">{{type.display}}
</option>
</select>
component.ts
export class FilterComponent implements OnInit {
selectedFilter:string;
public filterTypes = [
{ value: 'percentage', display: 'percentage' },
{ value: 'amount', display: 'amount' }
];
constructor() {
this.selectedFilter = 'percentage';
}
filterChanged(selectedValue:string){
console.log('value is ', selectedValue);
}
ngOnInit() {
}
}
Checkout this working Plunker
<select (change)="onItemChange($event.target.value)">
<option *ngFor="#value of values" [value]="value.key">{{value.value}}</option>
</select>
For me, passing ($event.target.value) as suggested by #microniks did not work. What worked was ($event.value) instead. I am using Angular 4.2.x and Angular Material 2
<select (change)="onItemChange($event.value)">
<option *ngFor="#value of values" [value]="value.key">
{{value.value}}
</option>
</select>
HTML
<h3>Choose Your Favorite Cricket Player</h3>
<select #cricket (change)="update($event)">
<option value="default">----</option>
<option *ngFor="let player of players" [value]="player">
{{player}}
</option>
</select>
<p>You selected {{selected}}</p>
Javascript
import { Component } from '#angular/core';
#Component({
selector: 'app-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.css']
})
export class DropdownComponent {
players = [
"Sachin Tendulkar",
"Ricky Ponting",
"Virat Kohli",
"Kumar Sangakkara",
"Jacques Kallis",
"Hashim Amla ",
"Mahela Jayawardene ",
"Brian Lara",
"Rahul Dravid",
"AB de Villiers"
]
selected = "----"
update(e){
this.selected = e.target.value
}
}
app.componen.html
<app-dropdown></app-dropdown>
You can Use ngValue. ngValue passes sting and object both.
Pass as Object:
<select (change)="onItemChange($event.value)">
<option *ngFor="#obj of arr" [ngValue]="obj.value">
{{obj.value}}
</option>
</select>
Pass as String:
<select (change)="onItemChange($event.value)">
<option *ngFor="#obj of arr" [ngValue]="obj">
{{obj.value}}
</option>
</select>
Template:
<select class="randomClass" id="randomId" (change) =
"filterSelected($event.target.value)">
<option *ngFor = 'let type of filterTypes' [value]='type.value'>{{type.display}}
</option>
</select>
Component:
public filterTypes = [{
value : 'New', display : 'Open'
},
{
value : 'Closed', display : 'Closed'
}]
filterSelected(selectedValue:string){
console.log('selected value= '+selectedValue)
}