Initializing select with AngularJS and ng-repeat - javascript

I'm trying to get select-box to start off with a pre-filled option using ng-repeat with AngularJS 1.1.5. Instead the select always starts out with nothing selected. It also has an empty option, which I don't want. I think that there is a side effect of nothing being selected.
I can get this working using ng-options instead of ng-repeat, but I want to use ng-repeat for this case. Although my narrowed down example doesn't show it, I also want to set the title attribute of each option, and there is no way to do that using ng-options, as far as I know.
I don't think this is related to the common AngularJs scope/prototypical inheritance issue. At least I don't see anything obvious when inspecting in Batarang. Plus, when you pick an option in the select with the UI, the model does update correctly.
Here's the HTML:
<body ng-app ng-controller="AppCtrl">
<div>
Operator is: {{filterCondition.operator}}
</div>
<select ng-model="filterCondition.operator">
<option
ng-repeat="operator in operators"
value="{{operator.value}}"
>
{{operator.displayName}}
</option>
</select>
</body>
And the JavaScript:
function AppCtrl($scope) {
$scope.filterCondition={
operator: 'eq'
}
$scope.operators = [
{value: 'eq', displayName: 'equals'},
{value: 'neq', displayName: 'not equal'}
]
}
JS Fiddle for this : http://jsfiddle.net/coverbeck/FxM3B/2/

OK. If you don't want to use the correct way ng-options, you can add ng-selected attribute with a condition check logic for the option directive to to make the pre-select work.
<select ng-model="filterCondition.operator">
<option ng-selected="{{operator.value == filterCondition.operator}}"
ng-repeat="operator in operators"
value="{{operator.value}}">
{{operator.displayName}}
</option>
</select>
Working Demo

For the select tag, angular provides the ng-options directive. It gives you the specific framework to set up options and set a default. Here is the updated fiddle using ng-options that works as expected: http://jsfiddle.net/FxM3B/4/
Updated HTML (code stays the same)
<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.value as operator.displayName for operator in operators">
</select>
</body>

The fact that angular is injecting an empty option element to the select is that the model object binded to it by default comes with an empty value in when initialized.
If you want to select a default option then you can probably can set it on the scope in the controller
$scope.filterCondition.operator = "your value here";
If you want to an empty option placeholder, this works for me
<select ng-model="filterCondition.operator" ng-options="operator.id as operator.name for operator in operators">
<option value="">Choose Operator</option>
</select>

Thanks to TheSharpieOne for pointing out the ng-selected option. If that had been posted as an answer rather than as a comment, I would have made that the correct answer.
Here's a working JSFiddle: http://jsfiddle.net/coverbeck/FxM3B/5/.
I also updated the fiddle to use the title attribute, which I had left out in my original post, since it wasn't the cause of the problem (but it is the reason I want to use ng-repeat instead of ng-options).
HTML:
<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator">
<option ng-repeat="operator in operators" title="{{operator.title}}" ng-selected="{{operator.value == filterCondition.operator}}" value="{{operator.value}}">{{operator.displayName}}</option>
</select>
</body>
JS:
function AppCtrl($scope) {
$scope.filterCondition={
operator: 'eq'
}
$scope.operators = [
{value: 'eq', displayName: 'equals', title: 'The equals operator does blah, blah'},
{value: 'neq', displayName: 'not equal', title: 'The not equals operator does yada yada'}
]
}

As suggested you need to use ng-options and unfortunately I believe you need to reference the array element for a default (unless the array is an array of strings).
http://jsfiddle.net/FxM3B/3/
The JavaScript:
function AppCtrl($scope) {
$scope.operators = [
{value: 'eq', displayName: 'equals'},
{value: 'neq', displayName: 'not equal'}
]
$scope.filterCondition={
operator: $scope.operators[0]
}
}
The HTML:
<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator.value}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.displayName for operator in operators">
</select>
</body>

If you are using md-select and ng-repeat ing md-option from angular material then you can add ng-model-options="{trackBy: '$value.id'}" to the md-select tag ash shown in this pen
Code:
<md-select ng-model="user" style="min-width: 200px;" ng-model-options="{trackBy: '$value.id'}">
<md-select-label>{{ user ? user.name : 'Assign to user' }}</md-select-label>
<md-option ng-value="user" ng-repeat="user in users">{{user.name}}</md-option>
</md-select>

Related

ng-change function is not being called and no error?

I am working with a select box in angular and it appears like the ng-change function is never being called. This is the code for the select:
<select
data-ng-options="choice.id as choice.singular for choice in model.doseUnitChoices"
data-ng-model="ucumId"
data-ng-change="updateForm()"
class="form-control input-sm">
<option value=""></option>
</select>
I have simplified the code in the controler function to do the minimum needed:
updateForm: function(){
console.log('test');
},
So far everything works like normal, the drop down shows all the available options, but when I select any option in the dropdown it immediately changes back to the last option, which may mean something, and the change function is never called and no errors appear in the console? Any ideas on how I can debug this issue and find out whats wrong?
UPDATE: interestingly I discovered while inspecting the element on the page is that actually all of the select elements are listed as selected, maybe there is an issue with the data being used as the model? Looking into it
I discovered that the issue was being caused by two problems outside the scope of the question:
ucumId didn't exist when this select was being called, which I guess caused all the select options to be set as selected somehow?
because the above error was causing all the options to be 'selected', no matter what i did in the select it never updated the values so no change was occurring?
Anyway making sure 'ucumId' existed fixed the issue I was having,
I just tried to duplicate it and with the minimum amount of code, it works fine.
<html>
<body ng-app="app" ng-controller="myController">
<select
data-ng-options="choice as choice.label for choice in model.doseUnitChoices"
data-ng-model="ucumId"
data-ng-change="updateForm()"
class="form-control input-sm">
<option value=""></option>
</select>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js "></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js "></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js "></script>
<script>
angular.module("app",[]).controller("myController", myController)
function myController($scope) {
$scope.ucumId = "";
$scope.updateForm = function(){
console.log('test');
};
$scope.model = {}
$scope.model.doseUnitChoices = [
{id: 1, label: "one" },
{id:2, label: "two" }
]
}
</script>
</body>
</html>
I suspect that either there's a small typo somewhere, updateForm is redefined somewhere or your controller is getting redefined somewhere. I'd suggest pairing down the actual code and removing things piece by piece until you get to a point where it's working or something like that.

AngularJS input select with integer value in ng-model stop working

I have a app written in C# .NET using WebApi and AngularJS.
At some points in my aplication I fill up a select tag with options using ENUMS, because since the values ​​are not in the database I don't feel like need to create a service that return the enums because I'm using razor pages so I can use the enums directly.
Everything was working fine until I updated the angular version to 1.4.7, Than this stop working, and I can't downgrade the angular version (for some enterprise reasons).
For example, I have this code
<div class="col-md-3 col-xs-12">
<label for="qualificacaoCobreJunta" class="col-xs-12 control-label">#IsiCTB.Internationalization.Res.Controls.label_cobre_junta<span class="obrigatorio">*</span></label>
<div class="col-xs-12">
<select class="form-control" id="qualificacao-cobre-junta" name="qualificacaoCobreJunta" ng-model="qualificacao.cobrejunta"
required>
<option value="" id="cobrejunta-0">#IsiCTB.Internationalization.Res.Controls.label_prompt_selecione</option>
<option id="optCobreJuntaCom" value="#IsiCTB.Entities.Enums.ComSem.Com.ToInt()">#IsiCTB.Entities.Enums.ComSem.Com.GetValueString()</option>
<option id="optCobreJuntaSem" value="#IsiCTB.Entities.Enums.ComSem.Sem.ToInt()">#IsiCTB.Entities.Enums.ComSem.Sem.GetValueString()</option>
<option id="optCobreJuntaAmbos" value="#IsiCTB.Entities.Enums.ComSem.Ambos.ToInt()">#IsiCTB.Entities.Enums.ComSem.Ambos.GetValueString()</option>
<option id="optCobreJuntaNA" value="#IsiCTB.Entities.Enums.ComSem.NA.ToInt()">#IsiCTB.Entities.Enums.ComSem.NA.GetValueString()</option>
</select>
<div ng-show="formQualificacaoSubmitted" class="error-form-validation">
<div ng-show="gerenciaQualificacoesSoldador.qualificacaoCobreJunta.$error.required">#IsiCTB.Internationalization.Res.Controls.label_obrigatorio</div>
</div>
</div>
</div>
Code getting data from WebApi.
QualificacaoService.get({ id: idQualificacao }, function (data) {
$scope.qualificacao = data;
});
And that return a JSON object with a bunch of attributes, like that:
{
id: 1,
cobrejunta: 2,
anotherEnumField: 1,
anotherEnumField2: 5,
anotherEnumField3: 2
....
}
If I have like qualificacao.cobrejunta = "2" (string) setting in the model, the select is pointing to right option, but if I have qualificacao.cobrejunta = 2 (integer) than nothing seems to work.
There's anyway to get this working again, or the only (best) solution is crete a service that will request a API, and this API will build the array and than return that for using ng-option?
Thank you guys.
This is discussed here.
All you have to do is to change your select as below
<select class="form-control" id="qualificacao-cobre-junta" name="qualificacaoCobreJunta" ng-model="qualificacao.cobrejunta" required
ng-options="entry.value as entry.label for entry in [{value : #IsiCTB.Entities.Enums.ComSem.Com.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.Com.GetValueString()'}, {value: #IsiCTB.Entities.Enums.ComSem.Sem.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.Sem.GetValueString()'}, {value: #IsiCTB.Entities.Enums.ComSem.Ambos.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.Ambos.GetValueString()'}, {value:#IsiCTB.Entities.Enums.ComSem.NA.ToInt(), label: '#IsiCTB.Entities.Enums.ComSem.NA.GetValueString()'}]">
</select>
I think Angular behaviour has changed with the version 1.4.8. I had the same problem: I had a list of values into a combo (static values), and I assigned dynamically the value to select throught the controller. It wasn't a problem with version 1.3.8, but it's with 1.4.8 when the selected value remains blank. But I can show the value in the view, and it's correct.
The way to solve this for me was to translate that static values, to an object containing that values, and defining it al the begin of the controller (before assigning the value). It's strange to have to do it, but I didn't find another way to success.

Print child elements as ng-options of an AngularJS select

I am iterating through an array of food items and printing out a select for each one. I want to populate the options of the select from child elements of the array. I am trying to do it like this:
<div ng-controller="MyCtrl">
<div ng-repeat="food in foodlist"> {{food.name}}
<select ng-options="unit.title as unit in food.unit" ng-model="unit" ng-change="update()"></select>
{{unit.name}}
</div>
</div>
The foods look like this:
{code: 1, name: 'Yoghurt', "unit":[
{"title":"bottle",
"gram":"45",
"max":"100"
},
{"title":"cup",
"gram":"250",
"max":"12"}
]},
This prints out the title of each food fine, but prints nothing into the selects.
See JSFiddle
I guess that I am calling the child elements incorrectly. Can anyone tell me how to do this correctly?
You have an error in your ng-options. Try this:
<select ng-options="unit.title for unit in food.unit" ng-model="unit" ng-change="update()"></select>
Using 'as' in your expression will allow you to specify what is displayed as the text part of the option. You still need the 'for' part of the statement which is the variable crated for each item in the collection food.unit.
Hope this helps!
Use ng-options like: ng-options="unit.title as unit.title for unit in food.unit"
Also you can use ng-init to avoid empty combo on start:
HTML
<div ng-controller="MyCtrl">
<div ng-repeat="food in foodlist">{{food.name}}
<select
ng-options="unit.title as unit.title for unit in food.unit"
ng-model="unit"
ng-change="update()"
ng-init="unit = food.unit[0].title"
></select>{{unit.name}}</div>
</div>
Demo Fiddle
I populated my drop-down menu in this way.
<html>
<select ng-model="myModel" ng-options="direction for direction in directionOptions"></select>
<controller>
var Directions = ['UP', 'DOWN', 'LEFT', 'RIGHT'];
$scope.directionOptions= Directions;
You can specify what value you want displayed in the drop-down menu by editing the first 'direction' in the ng-options.

Two way databinding in Select2 for AngularJS doesn't work

I am having issues with using the Select2 plugin in AngularJS. I can load the items fine, and retrieve the selected item from my ng-model, but I have issues, that the dropdown isn't updated if I update the ng-model.
In my view the code looks like this:
<select ui-select2 data-placeholder="All" id="filtersSelect" ng-model="chosenFilterItem" ng-options="item.text for item in filterItems">
In my controller I have the following code, which retrieves the items and binds it to the list:
$scope.fetchFilters = function(){
$http.get($scope.filtersUrl).then(function(result){
$scope.filterItems = result.data;
$scope.chosenFilterItem = result.data[3];
if(!$scope.$$phase) {
$scope.$apply();
}
});
}
As you can see I just try to set the 3rd item on the dropdownlist, but no item is preselected. Is there another way around preselecting a dropdown item?
Angular-ui/ui-select2 github page states:
ui-select2 is incompatible with <select ng-options>. For the best
results use <option ng-repeat> instead.
So, to save yourself from headache I also recommend using options with ng-repeat as in:
$scope.filterItems = [
{id: 1, text: 'Item1'},
{id: 2, text: 'Item2'},
{id: 3, text: 'Item3'},
{id: 4, text: 'Item4'}
];
<select ui-select2 placeholder="All" ng-model="chosenItem">
<option value=""></option>
<option ng-repeat="item in filterItems" value="{{item.id}}">{{item.text}}</option>
</select>
DEMO PLUNKER
Stewie posted the rigth way to implement Select2, but he's using "static" elements.
The difference is that angular renders select2 before having the elements called via ajax, so in this case you need to add an ui-if statement in order to add the directive only after you have data.
<select ui-select2 placeholder="All" ng-model="chosenFilterItem" **ui-if="filterItems.length>0"**>
<option value=""></option>
<option ng-repeat="item in filterItems" value="{{item.id}}">{{item.text}}</option>
</select>
If it doesn't work please create a jsfiddle with ajax items loading and I'll work there!

Empty first element in dropdown list

I am quite a beginner with AngularJS and currently I am working on a web application in Django where I use AngularJS for the frontend part i can say. My problem is that the dropdown list which is populated with objects from a scope always start with a blank element (if i select one from the list, the issue is gone). This create problems because if the user doesn't select anything the POST request normally it will not work anymore. I would like to know how to have something like a preselected value or something similar. Here's part of my code:
Select tag:
<select id="sel" class="input-block-level" ng-model="list_category">
<option ng-repeat="obj in list_categories.data" value="{{obj.id}}">{{obj.name}}</option>
<option value="Other">Other</option>
</select>
$scope.list_categories:
var listcategoryPromise = ListCategory.get();
listcategoryPromise.then(function(response) {
$scope.list_categories = {
meta : response.data.meta,
data : response.data.objects
};
});
Use the directive ng-options and remove the value from the 'Other' option, like this:
<select id="sel" class="input-block-level" ng-model="list_category" ng-options="obj.id as obj.name for obj in list_categories.data">
<option value="">Other</option>
</select>
This ensures that if list_category is empty (no entry selected), the 'Other' option is selected (by default).
jsFiddle: http://jsfiddle.net/bmleite/gkJve/
Find the below working example below you should avoid ng-repeat with options
so please see below sample code with
<body ng-controller="testcontroller">
<select ng-model="item" ng-options="item.ID as item.Title for item in items">
</select>
<span>{{item}}</span>
</body>
App.controller('testcontroller', function ($scope) {
$scope.item = '000001';
$scope.items = [
{ ID: '000001', Title: 'Chicago' },
{ ID: '000002', Title: 'New York' },
{ ID: '000003', Title: 'Washington' }
];
});
You can use a specific syntax for <select> tags with Angularjs.
Inspired from the documentation page:
<select id="sel" class="input-block-level" ng-model="list_category" ng-options="obj.name for obj in list_categories.data">
<option value="Other">Other</option>
</select>
Here's some code directly from the AngularJs.org website about select lists:
<select ng-model="color" ng-options="c.name for c in colors"></select>
First, as you can see, you don't need to use the ng-repeat to build your options list. Angular is going to basically let you do a foreach loop on a collection to build your option list. Second, you have the ng-model which is on the select, but isn't the same as your collections name. This is going to be your item which is actually collected at post time .
function MyCntrl($scope) {
$scope.colors = [
{name:'black', shade:'dark'},
{name:'white', shade:'light'},
{name:'red', shade:'dark'},
{name:'blue', shade:'dark'},
{name:'yellow', shade:'light'}
];
$scope.color = $scope.colors[2]; // red
}
Okay, and here's the javascript controller code. $scope.colors is the collection and $scope.color is the model property which has been assigned to the select list in the html. As you can see from this example the model property is being given a default starting value of the third option in the array. For you, this can be set from the http.get you're using for loading up your page initally.
Now when you're doing the foreach, you're basically grabbing the 'name' value from the collection and you're saying 'show this value' in the dropdown and use this value on the post. By having that inital model property set, you should be able to avoid having an empty option field in your drop down list.
Reference: AngularJS Select
in my opinion this answer is cleaner:
$scope.form = {type : $scope.typeOptions[0].value};
http://jsfiddle.net/MTfRD/2010/
The Blank empty option on top of drop down will appear if you have set ng-model with some value which is not contained in the list options created after the ng-Repeat.
Now if you consider the original post and remove the ng-model or set some valid value in ng-model, it will work fine
or you can set selected first item as
$scope.list_category = $scope.list_categories.data[0].id;

Categories

Resources