I have two select and I show value if they exist:
page.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
customer: any = {
city: '',
state: '',
};
ngOnInit() {
// I recover this info from BE
this.customer.state = 'England';
this.customer.city = 'London';
}
}
page.html
<div class="col configurator-form-input col-12 col-md-6">
<label class="text">State *</label>
<div
class="input-group input-error"
[ngClass]="
customer.state ? 'input-group input error' : 'input-group input-error'
"
>
<select
id="state"
class="form-control"
[(ngModel)]="customer.state"
[ngModelOptions]="{ standalone: true }"
(change)="onChangeProvinceForState($event.target.value)"
appTab
tabIndex="14"
>
<option disabled value="">Select State</option>
<option
*ngFor="let state of stateList"
ngDefaultControl
[value]="state.name"
>
{{ state.name }}
</option>
</select>
</div>
</div>
<div class="col configurator-form-input">
<label class="text">City *</label>
{{ this.customer.city }}
<div
class="input-group input-error"
[ngClass]="customer.city ? 'input-group' : 'input-group input-error'"
>
<!-- <span class="fake-option" *ngIf="existingCustomer">{{customer.city}}</span> -->
<select
id="city"
name="city"
class="form-control"
[(ngModel)]="customer.city"
[ngModelOptions]="{ standalone: true }"
appTab
tabIndex="15"
>
<option value="">Select City</option>
<option *ngFor="let city of citiesList" ngDefaultControl [value]="city">
{{ city }}
</option>
</select>
</div>
</div>
https://stackblitz.com/edit/angular-wyendp?file=src/app/app.component.html
I recover the city and state from an api call, but I don't understand how to show in the select directly
EDIT:
onChangeStateForCity(e) {
console.log("e ", e)
let countiesObservable = this.citiesService.getAllState();
countiesObservable.pipe(untilDestroyed(this)).subscribe((data: any) => {
this.citiesList = data[e];
});
}
You are missing the declaration of properties stateList and citiesList. I have modified your SB, to generate some static dropdown down options. You can easily assign these variables to the response you get from your API.
Stackblitz demo
app.component.ts (defined the variables):
stateList = [
'England',
'France'
]
citiesList = [
'London',
'Paris'
]
app.component.html (bind them in template):
<option *ngFor="let state of stateList" ngDefaultControl [value]="state">
<option *ngFor="let city of citiesList" ngDefaultControl [value]="city">
Just add array of stateList and citiesList.
stateList = [{ name: 'England' }];
citiesList = ['London'];
Related
I have 2 dropdown menus, the second one changes values depending on the selection of the first dropdown.
All I want to do is set the first value of the second dropdown to be selected by default no matter what the option in the first dropdown is.
At the moment, the default selection of the second dropdown is always empty.
I tried fetching the values from types and loading them via v-for on the option tag and setting :selected="index===0" but it didn't work either.
Demo: https://codesandbox.io/s/relaxed-flower-2hjox1?file=/src/App.vue
The Template
<div class="col-md-6">
<label for="type" class="form-label">Type</label>
<select id="type" class="form-select" v-model="form.type">
<option value="en-US" selected>English (US)</option>
<option value="en-GB">English (British)</option>
</select>
</div>
<div class="col-md-6">
<label for="selected" class="form-label">Option 2</label>
<div v-if="form.type === 'en-GB'">
<select id="selected" name="selected" class="form-select" v-model="form.selected">
<option value="Arsenal">Arsenal</option>
<option value="Chelsea">Chelsea</option>
<option value="Liverpool">Liverpool</option>
</select>
</div>
<div v-else-if="form.type === 'en-US'">
<select id="selected" name="selected" class="form-select" v-model="form.selected">
<option value="Lakers">Lakers</option>
<option value="Bulls">Bulls</option>
<option value="Mavericks">Mavericks</option>
</select>
</div>
</div>
Javascript
export default {
name: "App",
data() {
return {
form: {
type: 'en-GB',
selected: ''
},
types: {
american: ['Lakers', 'Bulls', 'Mavericks'],
british: ['Arsenal', 'Liverpool', 'Chelsea']
}
}
},
};
const app = Vue.createApp({
data() {
return {
form: {
type: "en-GB",
selected: "",
},
types: {
american: ["Lakers", "Bulls", "Mavericks"],
british: ["Arsenal", "Liverpool", "Chelsea"],
},
};
},
watch: {
'form.type': {
handler() {
this.form.selected = this.form.type === "en-GB" ? this.types.british[0] : this.types.american[0]
},
immediate: true
}
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div class="col-md-6">
<label for="type" class="form-label">Type</label>
<select id="type" class="form-select" v-model="form.type">
<option value="en-US" selected>English (US)</option>
<option value="en-GB">English (British)</option>
</select>
</div>
<div class="col-md-6">
<label for="selected" class="form-label">Option 2</label>
<div v-if="form.type === 'en-GB'">
<select
id="selected"
name="selected"
class="form-select"
v-model="form.selected"
>
<option value="Arsenal">Arsenal</option>
<option value="Chelsea">Chelsea</option>
<option value="Liverpool">Liverpool</option>
</select>
</div>
<div v-else-if="form.type === 'en-US'">
<select
id="selected"
name="selected"
class="form-select"
v-model="form.selected"
>
<option value="Lakers">Lakers</option>
<option value="Bulls">Bulls</option>
<option value="Mavericks">Mavericks</option>
</select>
</div>
</div>
</div>
You can create watcher and set default values for second select:
watch: {
'form.type': {
handler() {
this.form.selected = this.form.type === "en-GB" ? this.types.british[0] : this.types.american[0]
},
immediate: true
}
}
All I want to do is set the first value of the second dropdown to be
selected by default no matter what the option in the first dropdown
is.
Add a watcher, which watches form.type, then pick the first item from types
Note, I've changed american key to the key your using for type, then you can loop over the options, if you don't have that in place you'll need mapping object anyway typeMap: {'en-US': 'american', 'en-GB': 'british' } ... types[typeMap[form.type]]
new Vue({
el: '#app',
data() {
return {
form: {
type: 'en-GB',
selected: ''
},
types: {
'en-US': ['Lakers', 'Bulls', 'Mavericks'],
'en-GB': ['Arsenal', 'Liverpool', 'Chelsea']
}
}
},
watch: {
'form.type' () {
this.form.selected = this.types[this.form.type][0]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="app">
<div class="col-md-6">
<label for="type" class="form-label">Type</label>
<select id="type" class="form-select" v-model="form.type">
<option value="en-US" selected>English (US)</option>
<option value="en-GB">English (British)</option>
</select>
</div>
<div class="col-md-6">
<label for="selected" class="form-label">Option 2</label>
<select id="selected" name="selected" class="form-select" v-model="form.selected">
<option v-for="name in types[form.type]">{{ name }}</option>
</select>
</div>
</div>
I need to show different components depending on the selected option. I don’t know how to write the code for showing component one or two. Are there any examples available?
<template>
<div class="col-md-3 md-form mr-2">
<i class="fa fa-envelope prefix grey-text"></i>
<label class="font-weight-light mb-2">Component</label>
<select v-model="comp" class="form-control">
<option value="">Select your component to show</option>
<option value="">Show component 1</option>
<option value="SentenceSelected">Show component 2</option>
</select>
</div>
</template>
import SuspensionSelected from '../precautonary/mix/SuspensionSelected'
import SentenceSelected from '../precautonary/mix/SentenceSelected'
export default {
name: "PrecautionCreate",
components: {
SuspensionSelected,
SentenceSelected
},
data: () => ({
selectedyear: '',
selectedcause:'',
comp: ''
})
};
enter image description here
You can use a dynamic component:
<component :is="comp"></component>
Demo:
SuspensionSelected = {
template: `<div>Suspension Component</div>`
}
SentenceSelected = {
template: `<div>Sentence Component</div>`
}
new Vue({
el: "#app",
name: "PrecautionCreate",
components: {
SuspensionSelected,
SentenceSelected
},
data: () => ({
selectedyear: '',
selectedcause:'',
comp: ''
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<i class="fa fa-envelope prefix grey-text"></i>
<label class="font-weight-light mb-2">Component</label>
<select v-model="comp" class="form-control">
<option value="">Select your component to show</option>
<option value="SuspensionSelected">Suspension</option>
<option value="SentenceSelected">Sentence</option>
</select>
<component :is="comp"></component>
</div>
In my project I am using Angular 8.
Created method to bind user to project according to their id, tested with postman back end functionality works properly.
My service for bindUser method:
bindUserToProject(userId: number, projectId: number) {
const seperator = "/";
const body = { userId, seperator, projectId };
return this.http.post(this.baseUrl + '/bind/', body)
}
Component:
export class AddProjectForUserComponent implements OnInit {
users: any = {};
projects: any = {};
constructor(private router: Router, private projectService: ProjectService, private vmService:
VmService, private userService: UserService) { }
ngOnInit() {
this.users = this.getUsersForProject()
this.projects = this.getProjects()
}
getUsersForProject() {
this.projectService.getUsersForProject().subscribe(u => this.users = u);
}
getProjects() {
this.vmService.getProjectsForVm().subscribe(p => this.projects = p)
}
goBackToUserProjects() {
this.router.navigate(["/user-projects"])
}
bindUserToProject(userId: number, projectId: number) {
this.userService.bindUserToProject(userId, projectId);
}
HTML:
<div class="bindProject">
<form #bindProject="ngForm" (ngSubmit)="bindUserToProject()">
<h2 class="text-center text-primary">Bind User to Projects</h2>
<div class="input-group mt-1">
<div class="input-group-prepend">
<div class="input-group-text">
<i class="fas fa-dot-circle text-info"></i> Users
</div>
</div>
<select name="userId" [(ngModel)]="users.userId" class="form-control" required>
<option disabled>-Please choose User-</option>
<option *ngFor="let item of users" [ngValue]="item.userId">
{{ item.userName }}
</option>
</select>
</div>
<div class="input-group mt-1">
<div class="input-group-prepend">
<div class="input-group-text">
<i class="fas fa-dot-circle text-info"></i> Projects
</div>
</div>
<select name="projectId" [(ngModel)]="projects.projectId" class="form-control" required>
<option disabled>-Please choose Projects-</option>
<option *ngFor="let item of projects" [ngValue]="item.projectId">
{{ item.projectName }}
</option>
</select>
</div>
<div class="form-group mt-1">
<button [disabled]="!bindProject.valid" class="btn btn-success btn-sm mr-5" type="submit"><i
class="fas fa-plus"></i> Add</button>
<button (click)="goBackToUserProjects()" class="btn btn-sm btn-outline-success"><i
class="fas fa-tasks"></i> Go back to user projects</button>
</div>
</form>
</div>
Question is how can I get selected id from both dropdown and pass it to my bindToProject() method.
You should bind the select values with some variables say selectedProject and selectedUser.
app.component.ts :
selectedUser : number;
selectedProject : number;
bindUserToProject() {
this.userService.bindUserToProject(this.selectedUser, this.selectedProject);
}
app.component.html :
<select name="userId" [(ngModel)]="selectedUser">
<option disabled>-Please choose User-</option>
<option *ngFor="let item of users" [ngValue]="item.userId">
{{ item.userName }}
</option>
</select>
<select name="projectId" [(ngModel)]="selectedProject">
<option disabled>-Please choose Projects-</option>
<option *ngFor="let item of projects" [ngValue]="item.projectId">
{{ item.projectName }}
</option>
</select>
Demo : https://stackblitz.com/edit/angular-3udq1g
Define a variable in your component called something like selectedUserId, change [(ngModel)]="users.userId" to [(ngModel)]="selectedUserId". Then in bindUserToProject() you can access that value directly from the component.
You can do the same for the projects dropdown.
try like this
<form #bindProject="ngForm" (ngSubmit)="bindUserToProject(bindProject.value)">
<select name="userId" class="form-control" ngModel required>
<option disabled>-Please choose User-</option>
<option *ngFor="let item of users" [ngValue]="item.userId">
{{ item.userName }}
</option>
</select>
<select name="projectId" class="form-control" ngModel required>
<option disabled>-Please choose Projects-</option>
<option *ngFor="let item of projects" [ngValue]="item.projectId">
{{ item.projectName }}
</option>
</select>
<button type="submit">
Add
</button>
</form>
component
bindUserToProject({userId, projectId}) {
this.userService.bindUserToProject(userId, projectId);
}
bindUserToProject will get the hole form value but this {userId, projectId} is ES2015 feature called destruction
demo 🚀
In case someone has same issue my service also was wrong which threw exception json Parser.
I changed this one to and it worked fine:
bindUserToProject(userId: number, projectId: number) {
return this.http.post(this.baseUrl + '/bind/' + userId + "/" + projectId, {})
}
These are the following step of solution-:
Initialize two variable for userId and projectId.
Apply these variable in ngModel like [(ngModel)]="UserId" and [(ngModel)]="projectId"
use (ngSubmit)="bindUserToProject()"
In component file use initialized variables in bindUserToProject() function.
Select dropdown and click Submit.
Now, you have a selected value in your variable.
I am using angular 6 and i am unable to display the selected option as default in select box,
HTML consists,
<select class="form-control selectBox" name="username" #username="ngModel" required ngModel>
<option disabled selected>Select User Name</option>
<option *ngFor="let user of userList" [value]="user.uid">{{user.name }}</option>
</select>
Ts:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
userList: any = [
{
"name" : "Test User"
},
{
"name" : "Hello World"
},
{
"name" : "User Three"
}
]
}
It is showing empty value as default inside the select box.
How can i show the selected option as default inside the select box which from the line?
<option disabled selected>Select User Name</option>
Stackblitz:https://stackblitz.com/edit/angular-wfjmlm
You need to set a value in select box like this:
<option disabled selected value="">Select User Name</option>
Will make it work.
add [value]=""
<option disabled [value]="" selected>Select User Name</option>
and if you want to hide disable option then add hidden attribute
<option hidden disabled [value]="" selected>Select User Name</option>
the solution can be found in as follows
following was html
<select class="form-control selectBox" name="username" [(ngModel)]="selected" required>
<option disabled selected>Select User Name</option>
<option *ngFor="let user of userList" >{{user.name }}</option>
</select>
<hr> {{selected}}
following was the controller
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
userList: any = [
{
"name": "Test User"
},
{
"name": "Hello World"
},
{
"name": "User Three"
}
];
selected = 'Select User Name';
}
stackblitz
ReactiveForms
I pretty much suggest using ReactiveForms. In this way you will have a cleaner code as well as more powerful options.
first import ReactiveForms to your app.module:
import {FormsModule, ReactiveFormsModule} from '#angular/forms';
...
imports: [
...
ReactiveFormsModule
...
]
Then in your controller:
myForm: FormGroup;
constructor(private fb: FormBuilder){
this.myForm = this.fb.group({
username: null
})
}
And in your template:
<form [formGroup]="myForm">
<select formControlName="username" placeholder="Select Username">
<option disabled selected>Select User Name</option>
<option *ngFor="let user of userList" [value]="user.uid">{{user.name }}</option>
</select>
Use angular material instead of select and option.
Like this for example:
<mat-form-field>
<mat-select placeholder="Select User Name">
<mat-option *ngFor="let user of userList" [value]="user.uid">
{{food.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
More details here: https://material.angular.io/components/select/overview
When you create a select with ngFor loop for options, default value from ngModel is not selected
HTML :
<form style="margin : 20%;">
<div class="row">
<div class="form-group">
<label for="foo">K1 :{{keyboard | json}}</label>
<select [(ngModel)]="keyboard" name="foo" class="custom-select">
<option *ngFor="let a of foo" [ngValue]="a">{{a.name}}</option>
</select>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="fooz">K2 :{{keyboard2 | json}}</label>
<select [(ngModel)]="keyboard2" name="fooz" class="custom-select">
<option [ngValue]="foo[0]">AZERTY</option>
<option [ngValue]="foo[1]">QWERTY</option>
</select>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="fooa">K2 :{{keyboardStr | json}}</label>
<select [(ngModel)]="keyboardStr" name="fooa" class="custom-select">
<option [selected]="keyboardStr == 'AZERTY'" [ngValue]="AZERTY">AZERTY</option>
<option [selected]="keyboardStr == 'QWERTY'" [ngValue]="QWERTY">QWERTY</option>
</select>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="fooa">K2-bis :{{keyboardStr | json}}</label>
<select [(ngModel)]="keyboardStr" name="fooa" class="custom-select">
<option [selected]="keyboardStr == 'AZERTY'" [value]="AZERTY">AZERTY</option>
<option [selected]="keyboardStr == 'QWERTY'" [value]="QWERTY">QWERTY</option>
</select>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="fooa">K2-ter :{{keyboardStr | json}}</label>
<select [(ngModel)]="keyboardStr" name="fooa" class="custom-select">
<option [selected]="keyboardStr == 'AZERTY'" value="AZERTY">AZERTY</option>
<option [selected]="keyboardStr == 'QWERTY'" value="QWERTY">QWERTY</option>
</select>
</div>
</div>
</form>
Component :
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
private foo: any[] = [{id: 1, name: "AZERTY"}, {id: 2, name: "QWERTY"}];
private keyboard: any = {id: 1, name: 'AZERTY'};
private keyboard2 : any = {id: 1, name: 'AZERTY'};
private keyboardStr : string = 'AZERTY';
constructor() { }
ngOnInit() {
}
}
Result :
Shouldn't AZERTY be default selecteded ?
Is there a conflict when using both ngModel and ngValue ?
Because in the case of K1 example, value cannot be used as 'a' is an object right ?
Edit :
#Roy D. Porter Ok but imagine that I have this 'unit' object :
{
"id": 1,
"type": "REMISE",
"owner": "OWN",
"to": {
"id": 1,
"alone": true,
"level": 1,
"name": "Participant",
"minSales": 0.0,
"minTeamNumber": 0,
"durationCondition": 0,
"durationAwardCondition": null
},
"limit": 0.0,
"percentage": 25.0,
"alone": true
}
This will display well the type as model is a string :
<select [(ngModel)]="unit.type" name="tye" class="custom-select">
<option *ngFor="let type of types" [ngValue]="type">{{type | camelCase}}</option>
</select>
This does not display the default value it should :
{{award.name | camelCase}}
I assume this is caused by award not being a string. From what I see, ngModel is selected when it is a string but not when it's an object.
Angular v5.0.0
When you use [ngValue] on option, use [compareWith] on select.
Give it a function that compare two objects (in type of your ngValue and ngModel objects).
You have examples in the doc here : https://angular.io/api/forms/SelectControlValueAccessor
Best regards
I've faced the same issue as you.
My usual solution is to add an option to the list, and set it's value to -1, and initialise the binded variable to -1.
So in your case:
<select [(ngModel)]="keyboard" name="foo" class="custom-select">
<option value="-1">Please select an answer</option>
<option *ngFor="let a of foo" [ngValue]="a">{{a.name}}</option>
</select>
And in your component controller, initialise the keyboard variable to -1.