How to achieve a valid null-option with select ng-options - javascript

There are a couple of questions and answers around this topic here, but I cannot find a solution which is working the way it should be for my case.
Just imagine I have an object like this
$scope.person = {name: 'Peter', category1: null, category2: null};
In a different variable I receive a list of categories via a $resource call with a result like this:
$scope.categories = [{id:1, name:'Supplier'}, {id:2, name:'Customer'}];
Now it's easy to build a select with ng-options to choose from categories to set the selected category.id as person.category1 or person.category2.
But how can I do that when category1 is mandatory while category2 can still be a valid null value?
So basically what I am looking for now are two selects with the following options:
//Select1
- Select Category1 (disabled)
- Customer (value: 1)
- Supplier (value: 2)
//Select2
- Select Category2 (disabled)
- No Category (value: null)
- Customer (value: 1)
- Supplier (value: 2)
EDIT
I added a Plunkr based on #Mistalis answer, which shows what I want to achieve: Each select should have a disabled placeholder option and one should support a "valid null option".

You can add an option (null) to your select with the following:
<select ng-model="categ.selected" ng-options="c.name for c in categories">
<option value="">No category</option>
</select>
Demo on Plunker
categ.selected can be default set to null in your controller if needed:
$scope.categ = {"selected": null};
Update from comment:
It seems you can't hard-code 2 options in a ng-options, so I suggest you to push the "No category" option in categories in your controller:
$scope.categories.push({id:null, name:'No category', noCat:'true'});
Note the noCat: 'true' that will be used to be not displayed on the first select.
Now your HTML becomes:
<select ng-model="person.category1"
ng-options="c.id as c.name for c in categories | filter: {noCat: '!true'}">
<option value="" disabled>Select Category 1</option>
</select>
<select ng-model="person.category2" ng-options="c.id as c.name for c in categories">
<option value="" disabled>Select Category 2</option>
</select>
New Plunker

If you need to validate form with angular's form controller, you can't use empty value, it won't be considered as valid. You have to use (int)0 instead.
<select ng-model="person.category1" ng-options="category.id as category.name for category in categories | filter: {id: '!' + 0}" required>
<option value="">Select Category 1</option>
</select>
<select placeholder="Select Category 2" ng-model="person.category2" ng-options="category.id as category.name for category in categories" required>
<option value="">Select Category 2</option>
</select>
If you want to make Select Category options to be unavailable to select at all (like a placholder), then add disabled attribute to <option>
Here is jsfiddle with your example.

Related

How to show and hide the content based on dropdown selection items in angular

My requirement is to show the content based on selection of dropdown list.
component.ts
OptionList: LookupActionCode[]=[];
public setList(actionType: any):void{
this.anotherOptionList = [];
if(actionType == dataConstant.calendar){
this.List.push(
{
Name: dataConstant.content
},
{
Name: dataConstant.showcontent
},
{
Name: dataConstant.hidecontent
},
)}
switch(actionType){
case dataConstant.memberdata:
this.OptionList = this.memberCodes;
break;
case dataConstant.referral:
this.OptionList= this.optionalCodes;
break;
case dataConstant.Calendar:
this.OptionList = this.List;
break;
}
.component.html
//first dropdown
<label for="OptionList" class="cpp-required"> <b>Action</b></label>
<select id=action class="form-control" required (change) ="setList($event.target.value)">
<option value="" disabled [selected]="true"></option>
<option [value] = "dataConstant.referral">{{dataConstant.referral}}</option>
<option [value] = "dataConstant.memberdata">{{dataConstant.memberdata}}</option>
<option [value] = "dataConstant.calendar">{{dataConstant.content}}</option>
</select>
//second dropdown
<label> <b>Action</b></label>
<select id=action class="form-control" required>
<option value="" disabled [selected]="true"></option>
<option *ngFor="let option of optionList" [value] ="option">{{option.Name}} </option>
</select>
<div *ngIf="logic>
//some content to show and hide the data
</div>
So my requirement is from the first dropdown if i select the dataConstant.content then In secondit will show the realted dropdown lists those are dataConstant.content,dataConstant.showcontent and dataConstant.showcontent (implemented)
So If select the dataConstant.showcontent value then I need to show the data in div
Can anyone help me on this
If you first add a property to your component in ts to hold the selected value:
theProperty: string | undefined;
and on your select list in html add:
<select [(ngModel)]="theProperty" ect...
This will set up two way binding between your property and the select list. (Note reactive forms are good option here but have chose this for simplicity).
You can then add:
*ngIf="theProperty === thingToMatchTo"
But maybe pick a more sensible property name than what I've used.
NOTE - Make sure you add FormsModule to your imports in the Module that this component is declared. It's what makes the ngModel directive available to you.

Blank option with empty string created in select using AngularJS

I've created an angularJS select box which will filter the results in a table based on the selected value in the select box.
Now, the select box is created using an object 'user['location']' which has locations as keys.
Also, I'm grabbing the default user location '${city}' as soon as the page is loaded, passing it on to my select box, and filter the results accordingly in the table.
If the user's current location doesn't match any of the options in my select box, then no filter should be applied!
For e.g., if the user location is 'London', since there's nothing like in 'London' in my object, it should select the first option - 'Select City'.
But currently it is creating an empty string like <option value= "? string:London ?"></option> above that and is selecting it!
How, do fix it?
Here's my code:
HTML:
<select class="form-control" ng-model="user.loc" ng-init="user.loc = '${city}'">
<option value="" ng-selected="!checkKey(user.loc)">Select City</option>
<option value="{{key}}" ng-selected="key == user.loc" ng-repeat="(key, value) in user['location']">{{key}}</option>
</select>
JS:
$scope.user['location'] = {Sydney: 5, Hong Kong : 7, NYC : 3, Toronto: 1};
$scope.checkKey = function(loc) {
if(loc in $scope.user['location']){
return true;
} else {
return false;
}
};
I think I understand what you are trying to do here. But instead of checking the values using checkKey, you can do it once when your controller is loaded.
Also, you can leverage ngOptions to render available options in the select box.
angular.module('myapp', [])
.controller('myctrl', function($scope) {
$scope.user = {};
$scope.user['location'] = {
'Sydney': 5,
'Hong Kong': 7,
'NYC': 3,
'Toronto': 1
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="myctrl">
<select class="form-control" ng-model="user.loc" ng-init="user.loc = user.location['London']" ng-options="value as key for (key, value) in user.location">
<option value="">Select City</option>
</select>
</div>
You can change ng-init with your own value, as you were doing, and it should work fine with it.
Ok, I tried this and it worked!
<select class="form-control" ng-model="user.loc">
<option value="" ng-selected="!checkKey(user.loc)">Select City</option>
<option value="{{key}}" ng-selected="key == '${city}'" ng-repeat="(key, value) in user['location']">{{key}}</option>
</select>

Select dropdownlist value from session

I have a dropdown list in my html file.
I want the location (in the dropdown) to be automatically selected if it is present in the session object if session.
I hope you understand my question. I am new to mvc. Thanks
#if (Session["Location"] == null)
{
<select class="form-control" id="DeliveryLocation" name="DeliveryLocation">
<option value="" selected disabled hidden>Choose Your Location</option>
<option value="Aundh">Aundh</option>
<option value="Baner">Baner</option>
<option value="Balewadi">Balewadi</option>
<option value="Pimpri">Pimpri</option>
<option value="Nilakh">Nilakh</option>
<option value="Wakad">Wakad</option>
</select>
}
else
{
// i want code here to select value from dropdown as it is in location session
<pre> <select class="form-control" id="DeliveryLocation" name="DeliveryLocation">
<option value="" selected disabled hidden>Choose Your Location</option>
<option value="Aundh">Aundh</option>
<option value="Baner">Baner</option>
<option value="Balewadi">Balewadi</option>
<option value="Pimpri">Pimpri</option>
<option value="Nilakh">Nilakh</option>
<option value="Wakad">Wakad</option>
</select>
}
You should use SelectList and MVC's HTML Helpers to build your dropdown. It looks daunting if you're new to MVC, but it simplifies a lot of stuff for you.
In your current action method that loads this page:
ViewBag.DeliveryLocation = new SelectList(new[]
{
new { Text = "Aundh", Value = "Aundh" },
new { Text = "Balewadi", Value = "Balewadi" },
new { Text = "Pimpri", Value = "Pimpri" }
}, "Value", "Text", Session["Location"]);
There are a bunch of overloads for the SelectList class. So the above code creates a SelectList with the collection where Value property will be bound to option's value attribute and Text will be displayed as the option's text. The next parameter is selectedValue. In your case, you'd want to set to whatever is there in the Session["Location"].
You can also create a list of SelectListItem and put it in a ViewBag.
And then in your view,
#Html.DropDownList("DeliveryLocation")
That's it. So what happens here is, Razor generates a <select> element with name="DeliveryLocation". Then it looks for a DeliveryLocation property in the ViewBag. WE have set this in our controller and the options will be set accordingly.
Let's say, you have set ViewBag.DeliveryLocationList in your controller with the SelectList. Then you'd have to tell razor where to look for a SelectList. And since ViewBag is a dynamic object, you'd have to cast it.
#Html.DropDownList("DeliveryLocation", (IEnumerable<SelectListItem>)ViewBag.DeliveryLocationList, "Choose Your Location", new { #id= "DeliveryLocation" })
Here you have hardcoded the locations. In real applications, the option values like Locations will usually be fetched from the database. Then you don't have to make big changes if you use HTML helpers.
This link from Microsft docs has some great examples for beginners
100% work in your situation.
<select class="form-control" id="DeliveryLocation" name="DeliveryLocation">
<option #(Session["location"] == null ? "selected disabled hidden": "")>Choose location</option>
<option #((string)Session["location"] == "USA" ? "selected" : "")>USA</option>
<option #((string)Session["location"] == "Praga" ? "selected" : "")>Praga</option>
<option #((string)Session["location"] == "Paris" ? "selected" : "")>Paris</option>
<option #((string)Session["location"] == "China" ? "selected" : "")>China</option>
<option #((string)Session["location"]== "GB" ? "selected":"")>GB</option>
</select>

AngularJS Data Driven dropdown with ng-repeat

I have been trying to create data driven cascading dropdown menu with Angularjs for my chart.
Here is what I got so far PLUNKER
Year:
<select id="YearSelector">
<option ng-repeat="year in filterOptions.stores">{{year.year}}</option>
</select>
Quarter:
<select id="QuarterSelector">
<option ng-repeat="quarter in filterOptions.stores">{{quarter.quarter}}</option>
</select>
Channel:
<select id="channel">
<option ng-repeat="channel in filterOptions.stores">{{channel.channel}}</option>
</select>
I understand in my select ng-repeat loop thru data and display each one of data to my selection menu. But I only want to one time for each data.
OUTPUT of dropdown menu should only have:
Year dropdown only: 2011, 2012
Quarter dropdown only : 1 , 2
Channel: Hypermarkets, Supermarkets
Add angular.filter in your module as:
angular.module('app',['angular.filter'])
and use it in your html page as follows:
<select>
<option ng-repeat="(key,value) in filterOptions.stores | groupBy: 'year'">
{{key}}
</option>
</select>
I've done the year selector in this jsbin example, hope it helps.
Dependency include:
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>
Just create a filter which filter all the duplicate values
app.filter('unique', function() {
return function(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
});
then in your html pass the parameter based on which do you want to filter
<select id="YearSelector">
<option ng-repeat="year in filterOptions.stores | unique: 'year'">{{year.year}}</option>
</select>
Quarter:
<select id="QuarterSelector">
<option ng-repeat="quarter in filterOptions.stores | unique: 'quarter'">{{quarter.quarter}}</option>
</select>
Channel:
<select id="channel">
<option ng-repeat="channel in filterOptions.stores | unique: 'channel'">{{channel.channel}}</option>
</select>
AngularJs Remove duplicate elements in ng-repeat

How to set a default value in ng-options [duplicate]

I have searched Google and can't find anything on this.
I have this code.
<select ng-model="somethingHere"
ng-options="option.value as option.name for option in options"
></select>
With some data like this
options = [{
name: 'Something Cool',
value: 'something-cool-value'
}, {
name: 'Something Else',
value: 'something-else-value'
}];
And the output is something like this.
<select ng-model="somethingHere"
ng-options="option.value as option.name for option in options"
class="ng-pristine ng-valid">
<option value="?" selected="selected"></option>
<option value="0">Something Cool</option>
<option value="1">Something Else</option>
</select>
How is it possible to set the first option in the data as the default value so you would get a result like this.
<select ng-model="somethingHere" ....>
<option value="0" selected="selected">Something Cool</option>
<option value="1">Something Else</option>
</select>
You can simply use ng-init like this
<select ng-init="somethingHere = options[0]"
ng-model="somethingHere"
ng-options="option.name for option in options">
</select>
If you want to make sure your $scope.somethingHere value doesn't get overwritten when your view initializes, you'll want to coalesce (somethingHere = somethingHere || options[0].value) the value in your ng-init like so:
<select ng-model="somethingHere"
ng-init="somethingHere = somethingHere || options[0].value"
ng-options="option.value as option.name for option in options">
</select>
Try this:
HTML
<select
ng-model="selectedOption"
ng-options="option.name for option in options">
</select>
Javascript
function Ctrl($scope) {
$scope.options = [
{
name: 'Something Cool',
value: 'something-cool-value'
},
{
name: 'Something Else',
value: 'something-else-value'
}
];
$scope.selectedOption = $scope.options[0];
}
Plunker here.
If you really want to set the value that will be bound to the model, then change the ng-options attribute to
ng-options="option.value as option.name for option in options"
and the Javascript to
...
$scope.selectedOption = $scope.options[0].value;
Another Plunker here considering the above.
Only one answer by Srivathsa Harish Venkataramana mentioned track by which is indeed a solution for this!
Here is an example along with Plunker (link below) of how to use track by in select ng-options:
<select ng-model="selectedCity"
ng-options="city as city.name for city in cities track by city.id">
<option value="">-- Select City --</option>
</select>
If selectedCity is defined on angular scope, and it has id property with the same value as any id of any city on the cities list, it'll be auto selected on load.
Here is Plunker for this:
http://plnkr.co/edit/1EVs7R20pCffewrG0EmI?p=preview
See source documentation for more details:
https://code.angularjs.org/1.3.15/docs/api/ng/directive/select
I think, after the inclusion of 'track by', you can use it in ng-options to get what you wanted, like the following
<select ng-model="somethingHere" ng-options="option.name for option in options track by option.value" ></select>
This way of doing it is better because when you want to replace the list of strings with list of objects you will just change this to
<select ng-model="somethingHere" ng-options="object.name for option in options track by object.id" ></select>
where somethingHere is an object with the properties name and id, of course. Please note, 'as' is not used in this way of expressing the ng-options, because it will only set the value and you will not be able to change it when you are using track by
The accepted answer use ng-init, but document says to avoid ng-init if possible.
The only appropriate use of ngInit is for aliasing special properties
of ngRepeat, as seen in the demo below. Besides this case, you should
use controllers rather than ngInit to initialize values on a scope.
You also can use ng-repeat instead of ng-options for your options. With ng-repeat, you can use ng-selected with ng-repeat special properties. i.e. $index, $odd, $even to make this work without any coding.
$first is one of the ng-repeat special properties.
<select ng-model="foo">
<option ng-selected="$first" ng-repeat="(id,value) in myOptions" value="{{id}}">
{{value}}
</option>
</select>
---------------------- EDIT ----------------
Although this works, I would prefer #mik-t's answer when you know what value to select, https://stackoverflow.com/a/29564802/454252, which uses track-by and ng-options without using ng-init or ng-repeat.
This answer should only be used when you must select the first item without knowing what value to choose. e.g., I am using this for auto completion which requires to choose the FIRST item all the time.
My solution to this was use html to hardcode my default option. Like so:
In HAML:
%select{'ng-model' => 'province', 'ng-options' => "province as province for province in summary.provinces", 'chosen' => "chosen-select", 'data-placeholder' => "BC & ON"}
%option{:value => "", :selected => "selected"}
BC & ON
In HTML:
<select ng-model="province" ng-options="province as province for province in summary.provinces" chosen="chosen-select" data-placeholder="BC & ON">
<option value="" selected="selected">BC & ON</option>
</select>
I want my default option to return all values from my api, that's why I have a blank value. Also excuse my haml. I know this isn't directly an answer to the OP's question, but people find this on Google. Hope this helps someone else.
Use below code to populate selected option from your model.
<select id="roomForListing" ng-model="selectedRoom.roomName" >
<option ng-repeat="room in roomList" title="{{room.roomName}}" ng-selected="{{room.roomName == selectedRoom.roomName}}" value="{{room.roomName}}">{{room.roomName}}</option>
</select>
Depending on how many options you have, you could put your values in an array and auto-populate your options like this
<select ng-model="somethingHere.values" ng-options="values for values in [5,4,3,2,1]">
<option value="">Pick a Number</option>
</select>
In my case, I was need to insert a initial value only to tell to user to select an option, so, I do like the code below:
<select ...
<option value="" ng-selected="selected">Select one option</option>
</select>
When I tryed an option with the value != of an empty string (null) the option was substituted by angular, but, when put an option like that (with null value), the select apear with this option.
Sorry by my bad english and I hope that I help in something with this.
Using select with ngOptions and setting a default value:
See the ngOptions documentation for more ngOptions usage examples.
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: '2', name: 'Option B'} //This sets the default value of the select in the ui
};
}]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-rc.0/angular.min.js"></script>
<body ng-app="defaultValueSelect">
<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>
<hr>
<tt>option = {{data.selectedOption}}</tt><br/>
</div>
plnkr.co
Official documentation about HTML SELECT element with angular data-binding.
Binding select to a non-string value via ngModel parsing / formatting:
(function(angular) {
'use strict';
angular.module('nonStringSelect', [])
.run(function($rootScope) {
$rootScope.model = { id: 2 };
})
.directive('convertToNumber', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) {
return parseInt(val, 10);
});
ngModel.$formatters.push(function(val) {
return '' + val;
});
}
};
});
})(window.angular);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-rc.1/angular.min.js"></script>
<body ng-app="nonStringSelect">
<select ng-model="model.id" convert-to-number>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
{{ model }}
</body>
plnkr.co
Other example:
angular.module('defaultValueSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.availableOptions = [
{ name: 'Apple', value: 'apple' },
{ name: 'Banana', value: 'banana' },
{ name: 'Kiwi', value: 'kiwi' }
];
$scope.data = {selectedOption : $scope.availableOptions[1].value};
}]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-rc.0/angular.min.js"></script>
<body ng-app="defaultValueSelect">
<div ng-controller="ExampleController">
<form name="myForm">
<select ng-model="data.selectedOption" required ng-options="option.value as option.name for option in availableOptions"></select>
</form>
</div>
</body>
jsfiddle
This worked for me.
<select ng-model="somethingHere" ng-init="somethingHere='Cool'">
<option value="Cool">Something Cool</option>
<option value="Else">Something Else</option>
</select>
In response to Ben Lesh's answer, there should be this line
ng-init="somethingHere = somethingHere || options[0]"
instead of
ng-init="somethingHere = somethingHere || options[0].value"
That is,
<select ng-model="somethingHere"
ng-init="somethingHere = somethingHere || options[0]"
ng-options="option.name for option in options track by option.value">
</select>
In my case since the default varies from case to case in the form.
I add a custom attribute in the select tag.
<select setSeletected="{{data.value}}">
<option value="value1"> value1....
<option value="value2"> value2....
......
in the directives I created a script that checks the value and when angular fills it in sets the option with that value to selected.
.directive('setSelected', function(){
restrict: 'A',
link: (scope, element, attrs){
function setSel=(){
//test if the value is defined if not try again if so run the command
if (typeof attrs.setSelected=='undefined'){
window.setTimeout( function(){setSel()},300)
}else{
element.find('[value="'+attrs.setSelected+'"]').prop('selected',true);
}
}
}
setSel()
})
just translated this from coffescript on the fly at least the jist of it is correct if not the hole thing.
It's not the simplest way but get it done when the value varies
Simply use ng-selected="true" as follows:
<select ng-model="myModel">
<option value="a" ng-selected="true">A</option>
<option value="b">B</option>
</select>
This working for me
ng-selected="true"
I would set the model in the controller. Then the select will default to that value. Ex:
html:
<select ng-options="..." ng-model="selectedItem">
Angular controller (using resource):
myResource.items(function(items){
$scope.items=items;
if(items.length>0){
$scope.selectedItem= items[0];
//if you want the first. Could be from config whatever
}
});
If you are using ng-options to render you drop down than option having same value as of ng-modal is default selected.
Consider the example:
<select ng-options="list.key as list.name for list in lists track by list.id" ng-model="selectedItem">
So option having same value of list.key and selectedItem, is default selected.
I needed the default “Please Select” to be unselectable. I also needed to be able to conditionally set a default selected option.
I achieved this the following simplistic way:
JS code:
// Flip these 2 to test selected default or no default with default “Please Select” text
//$scope.defaultOption = 0;
$scope.defaultOption = { key: '3', value: 'Option 3' };
$scope.options = [
{ key: '1', value: 'Option 1' },
{ key: '2', value: 'Option 2' },
{ key: '3', value: 'Option 3' },
{ key: '4', value: 'Option 4' }
];
getOptions();
function getOptions(){
if ($scope.defaultOption != 0)
{ $scope.options.selectedOption = $scope.defaultOption; }
}
HTML:
<select name="OptionSelect" id="OptionSelect" ng-model="options.selectedOption" ng-options="item.value for item in options track by item.key">
<option value="" disabled selected style="display: none;"> -- Please Select -- </option>
</select>
<h1>You selected: {{options.selectedOption.key}}</h1>
I hope this helps someone else that has similar requirements.
The "Please Select" was accomplished through Joffrey Outtier's answer here.
If you have some thing instead of just init the date part, you can use ng-init() by declare it in your controller, and use it in the top of your HTML.
This function will work like a constructor for your controller, and you can initiate your variables there.
angular.module('myApp', [])
.controller('myController', ['$scope', ($scope) => {
$scope.allOptions = [
{ name: 'Apple', value: 'apple' },
{ name: 'Banana', value: 'banana' }
];
$scope.myInit = () => {
$scope.userSelected = 'apple'
// Other initiations can goes here..
}
}]);
<body ng-app="myApp">
<div ng-controller="myController" ng-init="init()">
<select ng-model="userSelected" ng-options="option.value as option.name for option in allOptions"></select>
</div>
</body>
<!--
Using following solution you can set initial
default value at controller as well as after change option selected value shown as default.
-->
<script type="text/javascript">
function myCtrl($scope)
{
//...
$scope.myModel=Initial Default Value; //set default value as required
//..
}
</script>
<select ng-model="myModel"
ng-init="myModel= myModel"
ng-options="option.value as option.name for option in options">
</select>
try this in your angular controller...
$somethingHere = {name: 'Something Cool'};
You can set a value, but you are using a complex type and the angular will search key/value to set in your view.
And, if does not work, try this :
ng-options="option.value as option.name for option in options track by option.name"
I think the easiest way is
ng-selected="$first"

Categories