use ng-options or ng-repeat in select? - angularjs

I want use select in angularjs.
I have a json that every element have 2 part: name and value. I want show name in dropdown and when user select one of theme, value is copy to ng-model.
$scope.list = [{name:"element1",value:10},{name:"element2",value:20},{name:"element3",value:30}];
For this I have 2 way to use select:
ng-options:
I use ng-options like below:
<select ng-model="model.test" ng-options="element.name for element in list"></select>
It's work correctly, but when I select each of element, I want just value of element is copy to ng-model, but a json is copy to ng-model, like below:
$scope.model.test = {name:"element1",value:1}
I can resolve this problem in angular controller, but I want find a better way that resolve this problem.
For resolove this problem, I use second way:
2.use ng-repeat in options:
<select ng-model="model.test">
<option ng-repeat="element in list" value="{{element.value}}">{{element.name}}</option>
</select>
In second way, just value is copy to ng-model, but as a string type:
$scope.model.test = "10";
I use below code, but all of them return a string value to model.
<option ng-repeat="element in list" value={{element.value}}>{{element.name}}</option>
<option ng-repeat="element in list" value="{{element.value}}|number:0">{{element.name}}</option>
<option ng-repeat="element in list" value={{element.value}}|number:0>{{element.name}}</option>
How can fix this problem?

you can resolve it with ng-options as well
ng-options="element.value as element.name for element in list"
please read this blog to understand more about ng-options.
Also another advantage of ng-options is, it binds the object as opposed to json string in case you want to attach the selected object to ng-model.

Have you tried this :
<select ng-model="model.test" ng-options="element.value element.name for element in list"></select>
btw, if you may have hundreds of records into your list, you should create your own directive, where you would manipulate your DOM with a simple javascript for loop
ng-repeat will be slow to be rendered,
ng-options adds every record into $watch.

Related

Dynamic Select List Default Selected Item - Angular JS

I have the code listed below which works fine, however when i attempt to add ng-model and related ng-change to the select, an empty option is added. I understanding why, it is because on init the selectedOption for ng-model is empty.
What I want to do is set a default value so when I can use ng-change to set options IsSelected value to true when user selects it. I'm just not sure how to go about this, I have no issues doing this when I'm working with a static generated select list, but for some reason I can't figure it out for this dynamic generated list.
Any input is appreciated!
<div ng-repeat="optionType in productDetailModel.OptionTypes">
<select name="{{optionType.OptionTypeName}}">
<option ng-repeat="option in optionType.Options"
value="{{option.OptionValue}}">{{option.OptionValue}}
</option>
</select>
</div>
Here's plunkr I mocked to give a basic idea of what I have in mind: http://plnkr.co/edit/xBDfc0XzDwsF0mBiFZOv?p=preview
The initial option is blank because the model is initially undefined.
As tymeJV said, initializing your scope inside of your .js will define a default value that will be shown as selected initially.
$scope.modelName = $scope.optionType.Options[0];
It might be helpful to use ng-options instead of ng-repeat. One reason why it might be beneficial is that ng-options does not create a child scope (unlike ng-repeat). This could help simplify linking to your model and avoid confusion.
<select name="{{optionType.OptionTypeName}}" ng-model="modelName" ng-options="option for option in optionType.Options">
</select>
This article covers the basics of ng-options as well as discusses why it would be used as opposed to ng-repeat.
Hope this helps.
Use ng-options when using a select!
<select name="{{optionType.OptionTypeName}}" ng-model="someModel" ng-options="option as option for option in optionType.Options>
</select>
And then set the ngModel to the default option you want selected:
$scope.someModel = $scope.optionType.Options[0]
There is one directive of select element is ng-init but it call once while first time rendering, but if you change the options dynamically then it will not call again. So for that you need to set the model field with value in scope just below of your new option population logic.
$scope.modelName = $scope.Options[0]; // if array
$scope.modelName = $scope.Options[key]; // if Json Object

Display unlisted value in select with ng-options

I have a <select> element populated with the acceptable values via ng-options and bound to a model with ng-model. It is possible that the model is set to a value that is not acceptable. (It used to be acceptable but no longer is.) In this case AngularJS renders the <select> as if it had an empty item selected.
Is there a way to have it render the selected value even if it is not listed in ng-options? I know I can put a default <option> inside the <select>. It's better than displaying an empty item, but it's a static string. I'd like to have the invalid value displayed.
Interesting problem. I think that you will be able to achieve this with the combination of ngInit directive to set up initial value (it can be missing from the allowed options list) and ngShow to hide it once valid option is selected.
Something like this:
<select
ng-init="preselected = selected"
ng-change="preselected = null"
ng-model="selected"
ng-options="item.id as item.name for item in items">
<option value="" ng-show="preselected">{{preselected}}</option>
</select>
Demo: http://plnkr.co/edit/lUTR0pHDPecU0OUUwjzt?p=preview

Get text from select with ng-repeat (select2 autocomplete)

I'm using Select2 library for autocomplete(directive name) with angularjs single-page. But I have a trouble with get the text of selected option:
<!--$scope.testData = [{code:1, value:'Test1'}, {code:2, value:'Test2'}];-->
<select id="test" name="test" ng-model="test" autocomplete>
<option ng-repeat="obj in testData" value="{{obj.code}}">{{obj.value}}</option>
</select>
I'm using ng-repeat instead of ng-options because select2 plugin doesn't have support for that.
At this part I got the value of obj.code and save it on $scope.test, but, additionaly I need to save in a other variable the text of obj.value selected. How can I do this? Basically this is because I need to print in another step that value (not code) but I too need save the code.
Thanks for advance.
You would have to watch the test value (or ng-change if that's supported) and when it changes loop through your testData to find the object with the same code and then update your other variable for display.
Alternatively you could use ui-select which lets you set test to be the object then you can display the value or code as you need.

How to bind a model to an option's value

In Angular 1.2.11, given a controller with:
$scope.produce = { 'apples' : [{ 'variety' : 'granny smith', 'price': 2.00}] }
And a view with
<select ng-model='fruits'>
<option value="0">More Fruits...</option>
<option ng-repeat="p.apple for p in produce" value="p">{{ p.variety }}</option>
</select>
How can I bind 'p' to the value attribute? If I try as above the model is bound as a JSON string, not as the model itself (as it would be if I were able to use ng-options).
I'm working around this now by using an ng-change function that uses the value bound to fruits as a lookup in $scope.produce, but this seems like a workaround rather than a solution.
EDIT: Sorry I wasn't more clear about this: I need to be able to hard code 1+ options into the select list, so using ng-options is not a solution.
Here are some fiddles to help illustrate my problem:
** Using ng-options **
ng-options allows for one element that it uses for creating a default option for use as a label. Two problems with this: if I try to use that <option> for its intended purpose I can't add a second option to the select. On the other hand, if I just try to add one <option> element, it gets placed at the top of the <select> list. No good.
** Using ng-repeat **
I'm unable to bind the model to the value attribute of the <option> element. Instead, the value is stringified JSON, which is not bindable.
You need to use ng-options:
<select ng-model='fruits' ng-options="thisFruit.variety in apples">
</select>
If you need to have an option selected as a default (your "More Fruits" option) then you need to add that to the data before it gets to the repeater, and also set your model $scope.fruits = 0 to make that selection selected by default.

Using $index with the AngularJS 'ng-options' directive?

Say that I bind an array to a select tag using the following:
<select ng-model="selData" ng-options="$index as d.name for d in data">
In this case, the associated option tags are assigned a sequence of index values: (0, 1, 2, ...). However, when I select something from the drop-down, the value of selData is getting bound to undefined. Should the binding actually work?
On the other hand, say that I instead do the following:
<select ng-model="selData" ng-options="d as d.name for d in data">
Here, the option tags get the same index, but the entire object is bound on change. Is it working this way by design, or this behavior simply a nice bug or side-effect of AngularJS?
Since arrays are very similar to objects in JavaScript, you can use the syntax for "object data sources". The trick is in the brackets in the ng-options part:
var choices = [
'One',
'Two',
'Three'
];
In the template:
<select
ng-model="model.choice"
ng-options="idx as choice for (idx, choice) in choices">
</select>
In the end, model.choice will have the value 0, 1, or 2. When it's 0, you will see One; 1 will display Two, etc. But in the model, you will see the index value only.
I adapted this information from "Mastering Web Application Development with AngularJS" by PACKT Publishing, and verified at the Angular reference documentation for select.
Since you can't use $index but you can try indexOf.
HTML
<div ng-app ng-controller="MyCtrl">
<select
ng-model="selectedItem"
ng-options="values.indexOf(selectedItem) as selectedItem for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
Controller
function MyCtrl($scope) {
$scope.values = ["Value1","Value2"];
$scope.selectedItem = 0;
}
Demo Fiddle
Comment:
Array.prototype.indexOf is not supported in IE7 (8)
$index is defined for ng-repeat, not select. I think this explains the undefined. (So, no, this shouldn't work.)
Angular supports binding on the entire object. The documentation could be worded better to indicate this, but it does hint at it: "ngOptions ... should be used instead of ngRepeat when you want the select model to be bound to a non-string value."
You can also use ng-value='$index' in <option> tag.
<select ng-model="selData">
<option ng-repeat="d in data track by $index" ng-value="$index">
{{d.name}}
</option>
</select>
Don't use $index inside select tags. Use $index inside the option tags if you want to use the array indexes as either values or options.
<option ng-repeat="user in users" value="{{user.username}}">{{$index+1}}</option>
If you want to use inside values just put it in the value attribute as binding expression like
<option ng-repeat="user in users" value="{{$index+1}}">{{user.username}}</option>
and my controller code be like:
var users = ['username':'bairavan', 'username':'testuser'];

Resources