Angular and datalist - html

I need some help understanding how to use the HTML datalist with Angular. I have an object here. I would like the dropdown to display the make and model of the cars. But when you select a car, the selectedCar variable should be the entire car object. But the input should still only show the make and model.
cars = [{
make: 'Ford',
model: 'GTX',
color: 'green'
}, {
make: 'Ferarri',
model: 'Enzo',
color: 'red'
}, {
make: 'VW',
model: 'Amarok',
color: 'white'
}]
...
<input list="id-car" [(ngModel)]="selectedCar">
<datalist id="id-car">
<option *ngFor="let car of cars" [value]="car">{{car.make}} - {{car.model}}</option>
</datalist>
Here is a place to play with this: https://stackblitz.com/edit/angular-cwmwke

Using datalist with not get you what you wish in this case.. here is the code that partially works. After selecting any element the dropdown will not show as it was showing before.
try using select with option. This link can help you more DataList in Angular
html file
<input list="id-car" [(ngModel)]="selectedCar"
value="{{selectedCarObj.model}} - {{selectedCarObj.make}}"
(ngModelChange)="onChange()">
<datalist id="id-car">
<option *ngFor="let car of cars" [value]="car.make">{{car.make}} - {{car.model}}</option>
</datalist>
{{selectedCarObj.model}} - {{selectedCarObj.make}}
typescript file
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
cars = [{
make: 'Ford',
model: 'GTX',
color: 'green'
}, {
make: 'Ferarri',
model: 'Enzo',
color: 'red'
}, {
make: 'VW',
model: 'Amarok',
color: 'white'
}];
selectedCar = "";
selectedCarObj = {};
onChange = () => {
this.selectedCarObj = this.cars.find((c)=> c .make==this.selectedCar);
console.log(this.selectedCarObj)
}
}

Related

Angular DropDown - Unable to display value on View

In my component I have 2 Strings that I need to display on Angular Form as Dropdown, I am struggling to get the values on HTML page
Demo - https://stackblitz.com/edit/angular-dc4s7d?file=src%2Fapp%2Fapp.component.ts
Here is my ts code
export class EmployeeComponent implements OnInit {
constructor(public employeeService: EmployeeService) {}
public listItem: string[];
ngOnInit() {
this.listItem = ["A", "B"]; ----->>>>> Dropdown values
}
Html code
<div class="m-3 input-group; padding:10px; color:red; border: 3px solid ">
<span class="input-group-text">Type</span>
<select type="text" name="type" #type="ngModel"
[(ngModel)]="employeeService.selectedEmployee.type "placeholder="Type">
<option *ngFor="let dl of listItem" [value]="dl">{{dl}}</option>
</select>
</div>
Something may be wrong with your code but I can provide you a sample code to bind data with dropdown list. Please check and let me know.
HTML
<select name="city" (change)="onChange($event.target.value)">
<option *ngFor="let country of countries" [value]="country.id">{{country.name}}</option>
</select>
TS:
countries = [{
id: 1, name: 'France', cities: ['Paris', 'Marseille', 'Nice']
},
{
id: 2, name: 'Germany', cities: ['Hamburg', 'Berlin', 'Munich']
},
{
id: 3, name: 'Italy', cities: ['Roma', 'Milan', 'Napoli']
},
];
onChange(deviceValue) {
//do something
}
Note: Please Check the link of Stackblitz for more information LINK
NEW UPDATE
I think employeeService.selectedEmployee is not available on that link. That's the reason why your code was not working and You have to make a little change in listitem. Finally, code will look like =>
TS:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
selectedtype: any;
listItems= [{ name: 'A'},{ name: 'B'}];
ngOnInit() {
}
onChange(deviceValue) {
}
}
HTML:
<select name="dt" (change)="onChange($event.target.value)"
[(ngModel)]="selectedtype" placeholder="Type"
#type="ngModel" type="text">
<option *ngFor="let data of listItems" [value]="data.name">{{data.name}}</option>
</select>
NOTE: Provide link contain 4 errors.
Try Using :
You need to initialize your selectedEmployee in you service file
#Injectable({
providedIn: "root"
})
export class EmployeeService {
public selectedEmployee: Employee = {
_id: '',
name: '',
date: null,
designation: '',
salary: null,
type: null
};
constructor() {}
}
Check in your stackblitz demo path.
I think this will help you...

How to pass the object value dynamically as parameter into new FormControl() in angular 8

I have a dropdown whose data is coming from loop.Here I need to get the selected value and selected text on page load and on click a span.I am using reactive form here.To make default selection I am using new FormControl(1) ,Every thing is working correct I am getting the result in console.But when I am removing first object of array from my json and reload the page its creating error,since I hardcoded to 1 in FormControl,if I change to FormControl(2) its working fine.But I need to pass it dynamically so that it can work with any number of object. Here is the code below and demo example I created https://stackblitz.com/edit/angular-lwrvvz?file=src%2Fapp%2Fapp.component.ts
app.component.ts
import { Component } from '#angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
registerForm: FormGroup;
statusdata: any;
constructor(private formBuilder: FormBuilder)
{
this.registerForm = this.formBuilder.group({
title: new FormControl(1)
});
}
ngOnInit() {
this.statusdata = [{"groupid":1,"groupname":"project1"},{"groupid":2,"groupname":"project2"},{"groupid":3,"groupname":"project3"}];
console.log('selected Value', this.registerForm.get('title').value);
console.log('selected name', this.statusdata.filter(v => v.groupid == this.registerForm.get('title').value)[0].groupname);
}
getSelectedVal(){
console.log('selected Value', this.registerForm.get('title').value);
console.log('selected name', this.statusdata.filter(v => v.groupid == this.registerForm.get('title').value)[0].groupname);
}
}
app.component.html
-----------------
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happenss :)
</p>
<div>
<form [formGroup]="registerForm">
<select formControlName="title" class="form-control">
<option *ngFor="let grpdata of statusdata" value="{{grpdata.groupid}}">{{grpdata.groupname}}</option>
</select>
</form>
</div>
<p>home works!</p>
<div><span (click)="getSelectedVal()">Click here</span></div>
You can update the form to using patchValue method to select the first group in statusdata array. This way you don't have to hard-code anything.
Example: https://stackblitz.com/edit/angular-ggnhzq
(I've added a null condition for retrieving groupname in case there are 0 groups)

How to get selected value of dropdown in angular 6 on load(not onchange)

I have a select dropdown ,I am getting option's data and value from an array through loop. Here I need to get the value of selected drop down when page loads without onchange(in this case Recent). Here is code below.
app.component.html
<select>
<option *ngFor="let v of values" [value]="v.id">
{{v.name}}
</option>
</select>
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
title = 'projectchart';
public values = [
{ id: 3432, name: "Recent" },
{ id: 3442, name: "Most Popular" },
{ id: 3352, name: "Rating" }
];
ngOnInit(){
alert('The default selected value is');
}
}
you could make use of reactive forms
constructor(private fb: FormBuilder) { }
// create a form group using the form builder service
formName = this.fb.group({
name: ['']
})
in the template
<form [formGroup]="formName">
<select formControlName="name">
<option *ngFor="let v of values" [value]="v.id">
{{v.name}}
</option>
</select>
</>
and then get the value in the ts:
this.formName.controls['name'].value

Dynamic form using *ngFor and submitting values from it

I have a stackblitz as a guide.
I am wanting to display a list of material cards that I click an 'edit' button, to which I can edit text fields, and when I click on the 'save' icon, it of course saves by triggering an function etc.
I am struggling however to get to grips with how this all works within Angular and the Material nature of my app.
html
<form id="myForm" [formGroup]="thisIsMyForm">
<mat-card [formGroup]="x" *ngFor="let x of data; let i = index">
<mat-form-field>
<label for="{{x.name}}">Name</label>
<input formControlName="name" id="{{x.name}}" matInput value="{{x.name}}">
</mat-form-field>
<mat-form-field>
<label for="{{x.type}}">Type</label>
<input formControlName="type" id="{{x.type}}" matInput value="{{x.type}}"/>
</mat-form-field>
</mat-card>
</form>
ts
import { Component, ViewChild } from '#angular/core';
import {MatSnackBar} from '#angular/material';
import {FormArray, FormBuilder, FormGroup, Validators} from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
thisIsMyForm: FormGroup
data = [
{name:"one", type:"one"},
{name:"two", type:"two"},
{name:"three", type:"three"},
];
constructor(private formBuilder: FormBuilder) {}
onSubmit() {
// Here I would like to be able to access the values of the 'forms'
}
}
You are diving into the deep end for sure, trying to build a dynamic reactive form within the scope of an *ngFor is a challenge. I will walk you through it the best I can.
You will need to create an array for controls, in your constructor create your form setting formArrayName as an empty array using this.formBuild.array([])... call this whatever you want, I just used formArrayName for demonstration purposes.
After the form is instantiated with an empty array call this.buildForm()
constructor(private formBuilder: FormBuilder) {
this.thisIsMyForm = new FormGroup({
formArrayName: this.formBuilder.array([])
})
this.buildForm();
}
In your buildForm() iterate over your data[] and push controls for each index while assigning the default value and a default state of disabled.
buildForm() {
const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;
Object.keys(this.data).forEach((i) => {
controlArray.push(
this.formBuilder.group({
name: new FormControl({ value: this.data[i].name, disabled: true }),
type: new FormControl({ value: this.data[i].type, disabled: true })
})
)
})
console.log(controlArray)
}
Please Note: console.log(controlArray.controls) results in the following output... each index is a FormGroup with two controls name and type
0: FormGroup
1: FormGroup
2: FormGroup
In your html you will need to establish a container hierarchy that mimics the thisIsMyForm you just created.
parent:thisIsMyForm
child:formArrayName
grandchild:i as formGroupName
grandchild is important because it matches the console log of controlArray.controls in previous step
<form id="myForm" [formGroup]="thisIsMyForm">
<div [formArrayName]="'formArrayName'">
<mat-card *ngFor="let x of data; let i = index">
<div [formGroupName]="i">
Create edit and save buttons based on control disabled state
<button *ngIf="formControlState(i)" (click)="toggleEdit(i)">Enable Edit</button>
<button *ngIf="!formControlState(i)" (click)="toggleEdit(i)">Save</button>
Create methods in component to receive the index as an argument and handle logic to hide buttons and toggle input fields enable and disable state.
toggleEdit(i) {
const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;
if(controlArray.controls[i].status === 'DISABLED'){
controlArray.controls[i].enable()
}else{
controlArray.controls[i].disable()
}
}
formControlState(i){
const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;
return controlArray.controls[i].disabled
}
Submit button that console.log's the form value when clicked... also disable button while any of the input formControls are in enabled state.
<button [disabled]="thisIsMyForm.get('formArrayName').enabled" (click)="onSubmit()">Submit Form</button>
onSubmit() {
// Here I would like to be able to access the values of the 'forms'
console.log(this.thisIsMyForm.value)
}
Stackblitz
https://stackblitz.com/edit/dynamic-form-ngfor-otbuzn?embed=1&file=src/app/app.component.ts
Doing it with QueryList:
your html (this is an example):
<ng-container *ngFor="let x of data; let i = index">
<div class="ctr">
<span #names class="item">{{x.name}}</span>
<span #types class="item">{{x.type}}</span>
<span class="button" (click)="showData(i)">Show data</span>
</div>
</ng-container>
<h2>Selected values: </h2>
Selected name: {{selectedName}} <br>
Selected type: {{selectedType}}
some css just for the style
.ctr{
display: flex;
flex-direction: row;
margin-bottom: 20px;
}
.item{
margin-right:40px;
}
.button{
border: 1px solid black;
padding: 2px 5px 2px 5px;
cursor: pointer;
}
the component:
import { Component, QueryList, ViewChildren } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
#ViewChildren('names') names:QueryList<any>;
#ViewChildren('types') types:QueryList<any>;
selectedName: string;
selectedType: string;
data = [
{name:"one", type:1},
{name:"two", type:2},
{name:"three", type:3},
];
showData(index){
let namesArray = this.names.toArray();
let typesArray = this.types.toArray();
this.selectedName = namesArray[index].nativeElement.innerHTML;
this.selectedType = typesArray[index].nativeElement.innerHTML;
}
}
Working stackblitz: https://stackblitz.com/edit/angular-j2n398?file=src%2Fapp%2Fapp.component.ts

HTML Variables ignores double brackets

The actually problem was that my angular is not working at all
if you want to test this do this :
import { Component, OnInit} from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
ngOnInit() {
console.log('test');
}
}
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
I'm trying to create a dropdownlist with a name and value different from each other. In Visual studio 2015 the brackets at ">{{directionOption.name}}<" are shown grey as plain text
<select [(ngModel)]="direction">
<option *ngFor="#directionOption of directionOptions" [value]="directionOption.value">{{directionOption.name}}</option>
</select>
same result
<select [(ngModel)]="direction">
<option *ngFor="let directionOption of directionOptions" [value]="directionOption.value">{{directionOption.name}}</option>
</select>
export class AppComponent implements OnInit {
direction: any = { 'Left': 'L' };
directionOptions: any = [{ name: 'Left', value: 'L' }, { name: 'Right', value: 'R' }, { name: 'None', value: 'N' }];
}
The current result inside browser F12
<option *ngfor="#directionOption of directionOptions" [value]="directionOption.value">{{directionOption.name}}</option>
Use let keyword instead of #,
<option *ngfor="let directionOption of directionOptions" [value]="directionOption.value">{{directionOption.name}}</option>
update
Angular2 doesn't process bindings added dynamically to the DOM, only when they are added statically to a components template.
original
directionOptions should look like
directionOptions: any = [{ name: 'Left' , value: 'L' }, { name: 'Right' , value: 'R' }, { name: 'None' , value: 'N' }];