I am using angularjs ng-options and ng-model directives in my view to set the select option and get notified when dropdown option is selected or changed. I am also adding extra empty option so that user can deselect this and for that I want value in ng-model expression to be undefined. Is there any way to do that ? I tried adding value=="{{undefined}}" but that takes out the empty option totally.
Here is the plunker example where if I select the empty option then data.model should be undefined but here it is coming as null.
https://plnkr.co/edit/d9Jzs4YgqpWHbOxonwa3?p=preview
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-select-ngvalue-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="ngvalueSelect">
<div ng-controller="ExampleController">
<form name="myForm">
<label for="ngvalueselect"> ngvalue select: </label>
<select size="6" name="ngvalueselect" ng-model="data.model" multiple>
<option label='' value="{{undefined}}"/>
<option ng-repeat="option in data.availableOptions" ng-value="option.value">{{option.name}}</option>
</select>
</form>
<hr>
<pre>model = {{data.model === undefined | json}}</pre><br/>
</div>
</body>
</html>
Corresponding app.js is
(function(angular) {
'use strict';
angular.module('ngvalueSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.data = {
model: null,
availableOptions: [
{value: 'myString', name: 'string'},
{value: 1, name: 'integer'},
{value: true, name: 'boolean'},
{value: null, name: 'null'},
{value: {prop: 'value'}, name: 'object'},
{value: ['a'], name: 'array'}
]
};
}]);
})(window.angular);
Thanks
There are two issues with your code:
Your dropdown allows multiple select thanks to the multiple attribute. This means that your model stores array of selections. The value you are looking for is one of the elements of the array, but in your code you are comparing undefined to the whole array.
Your additional option should use ng-value instead of value attribute. You don't need to write is as separate option, you can add it to availableOptions object (as {value: undefined, name: ''}).
Here is the updated plunker:
https://plnkr.co/edit/RXUlW6P7DX2wPZOazwe8?p=preview
Related
In my Angularjs application, i am having code as follows,
HTML:
<div ng-app="test" ng-controller="test">
<div>
<input type="checkbox" ng-model="showvalidrates"> Display only Valid Rates
<br><br>
<select ng-model="selectRate"
ng-options="option.id as option.name for option in data">
</select>
</div>
</div>
JS:
angular.module('test', [])
.controller('test', ['$scope', function ($scope) {
$scope.data = [
{name: 'Rate 1', id: 1, valid: true},
{name: 'Rate 2', id: 2, valid: false},
{name: 'Rate 3', id: 3, valid: true}
];
$scope.selectRate = $scope.data[1].id;
$scope.showvalidrates = true;
}]);
Here i am making ng-options to display the rates, and i am having a checkbox which will be in checked state by default.
In this scenario, i am in the need to filter the ng-options to display only the valid rates for which i am having a property called valid: true or valid: false.
Here if the checkbox is checked which means showvalidrates is true, then only the object with valid: true needs to be displayed in options.. But if the value is selected already, In the working example given below {name: 'Rate 2', id: 2, valid: false} is selected but it has valid: false in this case the selected value needs to be displayed (means Rate 2 only needs to be in selected state). unless user touches the select box, but if he clicks the select box then only valid rates needs to be displayed and he can select any of the valid rates.
And if he uncheck the showvalidrates (false) then all the rates needs to be displayed in ng-options ..
JsFiddle: http://jsfiddle.net/opygzs4a/
As per example given,
showvalidrates = true
Options:
Rate 1
Rate 2 (Selected)
Rate 3
Onclick on the select box only Rate 1 and Rate 3 needs to displayed and user can select any of these two.
Unless any of these two were chosen the Rate 2 alone needs to be in selected state and selectRate should have the value as 2 only.
The valid property was the newly implemented in code to filter the data, so in order to affect the earlier selectRate value in the application, this scenario needs to be implemented.(Even if valid is false let it be selected unless user changes)..
I am very new in AngularJs and this scenario, so please help me how to handle this situation..
If there is any alternative approach for it it would be also welcomed but requirement is the same as like mentioned above.
To achieve expected result , use below option of using filter with checkbox condition
ng-options="option.id as option.name for option in data|filter: !init && showvalidrates?{valid:true}:{}" ng-init="init = true">
On check, showvalidrates is true and based on that set filter as { valid: true } to display options with flag valid -true
On uncheck, showvalidrates is false and based on that set filter as {}
Add ng-init flag to control initial default value
Codepen - https://codepen.io/nagasai/pen/GbrOMm?editors=1010
working code sample
angular.module('test', [])
.controller('test', ['$scope', function ($scope) {
$scope.data = [
{name: 'Rate 1', id: 1, valid: true},
{name: 'Rate 2', id: 2, valid: false},
{name: 'Rate 3', id: 3, valid: true}
];
$scope.selectRate = $scope.data[1].id;
$scope.showvalidrates = true;
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="test" ng-controller="test">
<div>
<input type="checkbox" ng-model="showvalidrates" ng-change="init = false"> Display only Valid Rates
<br><br>
<select ng-model="selectRate"
ng-options="option.id as option.name for option in data|filter: !init && showvalidrates?{valid:true}:{}" ng-init="init = true" ng-click="init = false">
</select>
</div>
</div>
This is my html code:
<select id="selectFileType" ng-model="instance.fileType" required>
<option ng-repeat="(key, value) in fileTypes" id="key" value="{{key}}">{{key}} ({{value}})</option>
</select>
I am using a map of items to fill the list with information - now I want to pre-select a specific element based on the key but all the solutions I found didn`t work.
E.g. I tried to use the id field to use something like:
document.getElementById("A").selected = true;
Does someone have an idea what I should do?
Thanks and have a nice day
Use the ng-selected directive to set your pre-selected option.
angular.module('myApp', [])
.controller('ctrl', function($scope) {
$scope.vm = {
priceTypes: [{
id: 3,
name: 'pound'
},
{
id: 5,
name: 'Yen'
},
{
id: 6,
name: 'dollar'
}
]
};
//select model value
$scope.localModel = {
priceType: $scope.vm.priceTypes[1]
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ctrl">
<select ng-model="localModel.priceType">
<option
ng-repeat="item in vm.priceTypes as item"
ng-selected="localModel.priceType.id == item.id"
value="{{item}}"
>{{item.name}}</option>
</select>
<div>
priceType: {{ localModel.priceType }}
</div>
</div>
As you can see in the code, I have a list cars Car A,B, and C with corresponding ids in availableCars list. I’m getting already chosen car from a service. It is not an object just the car name. User has option to choose different car but on change, I have to send car id to other service. Is there any simplest way to achieve my goal?
(function(angular) {
'use strict';
angular.module('ngrepeatSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.carName = (function getCarNameFromService(){
return 'Car B';
})();
$scope.availableCars = [
{id: '1A', name: 'Car A'},
{id: '2B', name: 'Car B'},
{id: '3C', name: 'Car C'}
]
}]);
})(window.angular);
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-ngrepeat-select-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="ngrepeatSelect">
<div ng-controller="ExampleController">
<form name="myForm">
<label for="repeatSelect"> Repeat select: </label>
<select name="repeatSelect" id="repeatSelect" ng-model="carName">
<option ng-repeat="option in availableCars" value="{{option.name}}">{{option.name}}</option>
</select>
</form>
<hr>
<tt>selected car name = {{carName}}</tt><br/>
<tt>selected car id = ???</tt><br/>
</div>
</body>
</html>
Rather than using an ng-repeat on the "option" element inside of a select, you can use "ng-options". ng-options
I created a plnkr to illustrate your example. Some of the key pieces of code are as follows:
JS
var carName = "Car B"; //name provided to this controller
$scope.availableCars = [
{id: '1A', name: 'Car A'},
{id: '2B', name: 'Car B'},
{id: '3C', name: 'Car C'}
]
$scope.selectedCar = $scope.availableCars.filter(function(car){
return car.name === carName;
})[0];
$scope.selectedId = $scope.selectedCar.id;
$scope.updateCar = function(id){
$scope.selectedId = id;
}
and
HTML
<form name="myForm">
<label for="repeatSelect"> Repeat select: </label>
<select ng-options="car as car.name for car in availableCars" ng-model="selectedCar" ng-change="updateCar(selectedCar.id)"></select>
</form>
Notice the "ng-change" and the "ng-options" in the html.
User has option to choose different car but on change, I have to send car id to other service
You could use ng-change for that:
<select ng-change="sendInfo(...)" ...>
...
</select>
Actually, I would advise to bind to the model the car id instead of the car name. Or a car object, providing you switch to ng-options. That way you could send the selected id.
JS:
angular
.module('app', [])
function MainCtrl() {
var ctrl = this;
ctrl.selectionList = [
{ id: 1, name: 'apple'},
{ id: 2, name: 'banana'},
{ id: 3, name: 'grapes'},
{ id: 4, name: 'carrot'}
];
ctrl.selectedThing = ctrl.selectionList[0].name;
}
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
HTML:
<div class="row">
<div class="col-sm-3 col-xs-12 unit">
<select
ng-model="ctrl.selectedThing"
ng-options="selections.name as selections.name for selections in ctrl.selectionList">
</select>
</div>
</div><!--end of first row-->
So this code creates four different selections.
The problem is that when I choose an option, let's say for example "apples" on one selection, all the other selections become apples too. Is there any way to solve this with ng-options or should I just write the select in HTML?
You definitely want to use ng-options, as that isn't the issue here. The problem you are seeing is most likely because the ng-model on all of your select elements is the same ctrl variable. So when you update one of them, it changes a single variable that is bound to all four dropdowns. You either need to setup up an array for your selected items, or four different instances of a selected variable.
ctrl.selectedThings = [ctrl.selectedList[0].name, '', '', ''];
Then in your view you can do this...
<select
ng-model="ctrl.selectedThings[rowIndex]"
ng-options="selections.name as selections.name for selections in ctrl.selectionList">
</select>
Not the most robust solution if you are going past 4 items, but you should be able to adapt it to be dynamic.
Your code is working fine, can you check and confirm?!
(function ()
{
var app = angular.module("app", []);
function HomeController()
{
var vm = this;
vm.selectionList = [
{ id: 1, name: 'apple'},
{ id: 2, name: 'banana'},
{ id: 3, name: 'grapes'},
{ id: 4, name: 'carrot'}
];
}
app.controller("HomeController", [HomeController]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Angular JS App</title>
</head>
<body>
<div class="container" ng-controller="HomeController as homeCtrl">
<div class="row">
<div class="col-sm-3 col-xs-12 unit">
<select
ng-model="homeCtrl.selectedThing"
ng-options="selections.name as selections.name for selections in homeCtrl.selectionList">
</select>
<pre>{{homeCtrl.selectedThing}}</pre>
</div>
</div><!--end of first row-->
</div>
</body>
</html>
If you have ng-model="ctrl.selectedThing" for all of your <select> tags, they will all change to the same selection because they're using the same scope property. Think of it like having 4 variables referencing the same data: if you change one, access any of the variables will retrieve the same result.
You need to bind all of your selects to a different property on scope, so ctrl.selectedThing1,2,...n. That's not very scalable, but that would fix your problem.
I have fetched a json object with the list of countries. And now i want to display the selected name of the country in the select option box. I've tried different ways but there always keep showing the blank value.
Note:countries is the json object having the list of countries with key value pair. It used to display the select option in the view. And tabs[0].data.country is the value of country id which is to be selected.
Some of the codes i have tried:
Code to display the selected country name:
Code to display the select option in View:
Output:
Convert you json object into an array of objects first, and then you do something like
<select name="countries" id="contries" ng-model="vm.country">
<option ng-repeat="country in vm.countries" value="{{country.id}}">{{country.name}}</option>
</select>
Just loop over them and pick what you want from the list. Full documentation here: https://docs.angularjs.org/api/ng/directive/select
Well finally, here is the snippet that solved my problem.
html
<div ng-controller="ExampleController">
<form name="myForm">
<label for="mySelect">Make a choice:</label>
<select name="mySelect" id="mySelect"
ng-options="option.name for option in data.availableOptions track by option.id" ng-model="data.selectedOption">
</select>
</form>
</div>
js
angular.module('defaultValueSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.data = {
availableOptions: [
{id: '1', name: 'Option A'},
{id: '2', name: 'Option B'},
{id: '3', name: 'Option C'}
],
selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
};
}]);
For more information you can go to this link
Also another useful tutorial here