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.
Related
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'];
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 have a form with three steps and want to
achieve an effect that when the user completes each step, the next step scrolls up into view.
How can I achieve this? I am using VUEJS 2.5.2. I have removed some HTML to keep it cleaner and clearer.
Can anyone help with a solution?
My code so far is:
<template>
<div id="app">
<form action="" method="post">
<div id="step1" v-show="quote.location === 'home'">
<select v-model="brand">
<option value="" selected disabled hidden>Select brand</option>
<option v-for="(car, index) in cars">{{ index }}</option>
</select>
<select v-model="model">
<option value="" selected disabled hidden>Select model</option>
<option v-for="option in cars[brand]" :value="option.prize">{{ option.prize }}</option>
</select>
</div><!--/step1-->
<div id="step2" v-show="brand && model != ''">
<h2><span class="text">Do you need an installer?</span></h2>
<div class="location">
<div class="selection">
<input type="radio" id="yesInstaller" name="yesInstaller" value="Yes" v-model="quote.installer">
<label for="yesInstaller">Yes</label>
</div>
<div class="selection">
<input type="radio" id="noInstaller" name="noInstaller" value="No" v-model="quote.installer">
<label for="noInstaller">No</label>
</div>
</div>
</div><!--/step2-->
<div id="step3" v-show="quote.installer != ''">
<h2><span class="text">Right on! Here’s an overview of your selection.</span></h2>
</div><!--/step2-->
</form>
</template>
<script>
export default {
name: 'Quote',
data () {
return {
totalSteps: 4,
currentStep: 1,
show: true,
brand: '',
model: '',
cars: {
'BMW': [ { size:'1', prize:'BMW i3' }, { size:'2',prize:'BMW i8' }, { size:'3',prize:'BMW 740e' } ],
'AUDI': [ { size:'1', prize:'Audi A3 E-Tron' },{ size:'2', prize:'Audi Q7 E-Tron' } ],
'Chevrolet': [ { size: '1', prize:'Chevrolet Bolt'}, {size:'1', prize:'Chevrolet Volt' } ],
'Fiat': [ { size: '1', prize:'Fiat 500e'}]
}
}
}
}
</script>
<form class="col2">
<label for="filter-online">
Filter by Online
</label>
<div class="select">
<select id="filter-online" ng-model="vm.online" class="form-control" ng-options="online for online in vm.onlines">
<option value="">All</option>
</select>
</div>
</form>
<form class="col2">
<label for="filter-productType">
Filter by Product Type
</label>
<div class="select">
<select id="filter-productType" ng-model="vm.productType" class="form-control" ng-options="productType for productType in vm.productTypes">
<option value="">All</option>
</select>
</div>
</form>
<tr ng-repeat="lim in vm.stockLimits track by lim.id">
<td>{{lim.online}}</td>
<td>{{lim.producttype}}</td>
</tr>
vm.stockLimits values below:
ONLINE PRODUCT TYPE
Men Shirt
Men Shoe
Ladies Top
Kids belt
Kids
..........
..........
Based on drop down (filter_online select & filter_productType select), need to filter data in the table.
Is it possible to write one custom filter javascript function in angular script file which can be used to filter both online & product type based on drop down selection? It would be great if you show me the ideas of doing it.
I added a custom filter on your ng-repeat in such a way that it can filter out selected values dynamically from the dropdown selection.
Here's the ng-repeat:
ng-repeat="lim in vm.stockLimits | filter:{
online:vm.online && vm.online !== '' ? vm.online : '',
productType: vm.productType && vm.productType !== '' ? vm.productType : ''
}"
Find working code snippet below!
angular.module("myApp", [])
.controller("myCtrl", function($scope) {
var vm = this;
vm.onlines = ["Men", "Kids", "Ladies"];
vm.productTypes = ["Shirt", "Shoe", "Top"];
vm.stockLimits = [{
id: 1,
online: "Men",
productType: "Shirt"
}, {
id: 2,
online: "Men",
productType: "Shoe"
}, {
id: 3,
online: "Kids",
productType: "Belt"
}, {
id: 4,
online: "Ladies",
productType: "Top"
}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl as vm">
<form class="col2">
<label for="filter-online">
Filter by Online
</label>
<div class="select">
<select id="filter-online" ng-model="vm.online" class="form-control" ng-options="online for online in vm.onlines">
<option value="">All</option>
</select>
</div>
</form>
<form class="col2">
<label for="filter-productType">
Filter by Product Type
</label>
<div class="select">
<select id="filter-productType" ng-model="vm.productType" class="form-control" ng-options="productType for productType in vm.productTypes">
<option value="">All</option>
</select>
</div>
</form>
<table style="margin-top: 30px">
<tr ng-repeat="lim in vm.stockLimits | filter:{online:vm.online && vm.online !== '' ? vm.online : '', productType: vm.productType && vm.productType !== '' ? vm.productType : ''}">
<td>{{lim.online}}</td>
<td>{{lim.productType}}</td>
</tr>
</table>
</div>
In AngularJS you can stack as many filters on an array as you would like on an array.
Try doing something like this:
HTML:
<select ng-model="vm.online" ng-options="online for online in vm.onlines" ng-change="vm.filterChanged()">
<option value="">All</option>
</select>
<select ng-model="vm.productType" ng-options="productType for productType in vm.productTypes" ng-change="vm.filterChanged()">
<option value="">All</option>
</select>
<tr ng-repeat="lim in vm.filteredStockLimits = vm.stockLimits | filterByOnline:vm.online
| filterByProductType:vm.productType track by lim.id">
JS (Controller):
var filterChanged = function() {
var filtered = $filter('filterByOnline')(vm.stockLimits, vm.online);
vm.filteredStockLimits = $filter('filterByProductType')(filtered, vm.productType);
}
In your controller you read the data into your initial vm.stockLimits array which gets filtered into vm.filteredStockLimits when either select box is changed. Note, you will have to add two custom filters (filterByOnline and filterByProductType) to filter the array by the online and product type. For that you can reference the AngularJS docs: AngularJS Custom Filters
You can use ng-show or ng-if to filter data.
no need to create a custom filter.
something like this.
<tr ng-repeat="lim in vm.stockLimits" ng-show="lim.productType==vm.productType && lim.online==vm.online">
<td>{{lim.online}}</td>
<td>{{lim.productType}}</td>
</tr>
see full workin fiddle here
http://jsfiddle.net/SNF9x/315/
Better you can use npm package of filter;
install it:- npm i ng2-search-filter
import this to module.ts
import { Ng2SearchPipeModule } from 'ng2-search-filter';
in html : *ngFor="let dealerdata of Dealer_data|filter:Status|filter:Range"
I am new to AngularJS. In my application i have two <select>. The second select has to be dependent on the value selected from first select selected.
Following is my controller data:
$scope.types=[{type:"Cars"},{type:"Bykes"}];
$scope.Cars= [{"id":1,"CarName":"Hundai"},{"id":2,"CarName":"Maruti"},{"id":3,"CarName":"Toyoto",}];
$scope.Bykes= [{"id":10,"BykeName":"Honda"},{"id":8,"BykeName":"Bajaj"},{"id":9,"BykeName":"TVS"}];
Following is My HTML:
<div class="col-lg-2 top10">
<select class="form-control select1" ng-model="selectedType" ng-init="selectedType='Cars'">
<option ng-repeat="type in types">{{type.type}}</option>
</select>
</div>
<div class="col-lg-3">
<select ng-model="vehicle" class="form-control select2" >
<option ng-repeat="car in Cars" value="{{car}}">{{car.CarName}}</option>
</select>
</div>
Actually My Cars and Bykes data comes from database.
Now as if i select cars from first select , accordingly only cars should be displayed in the second select and if i select Bykes only Bykes should be displayed in second select.
Please help me on this.Thanx in advance.
Here is what you could do, without modifying many things in your code.
you could make use of ng-if to check on the selected vehicle type and display the corresponding dropdown accordingly.
var app = angular.module("sampleApp", []);
app.controller("sampleController", ["$scope",
function($scope) {
$scope.types = [{
type: "Cars"
}, {
type: "Bykes"
}];
$scope.Cars = [{
"id": 1,
"CarName": "Hundai"
}, {
"id": 2,
"CarName": "Maruti"
}, {
"id": 3,
"CarName": "Toyoto",
}];
$scope.Bykes = [{
"id": 10,
"BykeName": "Honda"
}, {
"id": 8,
"BykeName": "Bajaj"
}, {
"id": 9,
"BykeName": "TVS"
}];
}
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="sampleApp">
<div ng-controller="sampleController as vm">
<div class="col-lg-2 top10">
<select class="form-control select1" ng-model="vm.selectedType" ng-init="vm.selectedType='Cars'">
<option ng-repeat="type in types">{{type.type}}</option>
</select>
</div>
<div class="col-lg-3" ng-if="vm.selectedType=='Cars'">
<select ng-model="vehicle" class="form-control select2">
<option ng-repeat="car in Cars" value="{{car}}">{{car.CarName}}</option>
</select>
</div>
<div class="col-lg-3" ng-if="vm.selectedType=='Bykes'">
<select ng-model="vehicle" class="form-control select2">
<option ng-repeat="byke in Bykes" value="{{byke}}">{{byke.BykeName}}</option>
</select>
</div>
<span>
</span>
</div>
</div>
Here the answer
Here
populate second select based on select of option from first select