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;
Related
jsfiddle
Hi.
I have a problem with my application. I have to write several selects by using ng-repeat and each of these selects must be filled with the same data.
The problem is, when the one is changed, others selects are changes to the same value - why?.
I suppose that the problem is in the ng-model - maybe I don't understand how the "hierarchy" of the ng-model works.
If the name of the ng-model is only "option" - it doesn't work!
If the name of the ng-model is "something.option" - it also doesn't
work!
If the name of the ng-model is "something.else.option" - it does work
but all selects are filled!
HTML:
<div ng-controller="MyCtrl">
<div ng-if="models" ng-repeat="m in models">
<br><label>{{m.model}} ({{m.no}})</label><br>
<select ng-model="models.m.opModel" ng-options="opt.value as opt.text for opt in options" ng-change="foo()"></select>
</div>
</div>
JS:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.models = [
{'no':'A', 'model':'alpha'},
{'no':'B', 'model':'beta'},
{'no':'C', 'model':'gamma'}
];
$scope.options = [
{'value':1, 'text':'one'},
{'value':2, 'text':'two'},
{'value':3, 'text':'three'}
];
$scope.foo = function(){
alert($scope.models.m.opModel);
}
}
What am I doing wrong?
Thanks a lot.
You've created a scope object called "m" which is the current child of the "models" list. So for each dropdown, you're going to have a different "m" scope object. This is what you need to bind to in your ng-model so that the dropdown is bound to its unique parent in the "models" list.
Change <select ng-model="models.m.opModel"> to <select ng-model="m.opModel" to fix the problem.
To access the value with the foo() function, you'll need to use this updated function:
$scope.foo = function(index){
alert($scope.models[index].opModel)
}
And update the <select> like this:
<select ng-model="m.opModel" ng-options="opt.value as opt.text for opt in options" ng-change="foo($index)"></select>
You're creating an ng-model called "opModel" in the ng-repeat which means you'll have three new opModels under $scope.models. This is an array you can access later using an index value to specify which of the $scope.models[].opModel you want to access.
Notice that I've changed the ng-change code to send the current $index which is basically an ng-repeat counter. So your foo() function will receive either a 0, 1 or 2 which lets us access the specific ngModel that we need to access.
You are binding to the single object models. Inside an ng-repeat the repeated is available "in scope". You probably want to change this code to:
<div ng-controller="MyCtrl">
<div ng-if="models" ng-repeat="m in models">
<br><label>{{m.model}} ({{m.no}})</label><br>
<select ng-model="m.opModel" ng-options="opt.value as opt.text for opt in options" ng-change="foo()"></select>
</div>
</div>
Look at the ng-model="m.opModel", that is what I've changed. You are now updating the value of the single item, and not inserting a new object into an array which is then reused by all the ng-repeat items (which is why all the values would update at the same time).
I have ui-select2 dropdown that depends on the selection of a parent. I have a array of options for the first ui-select2, then when something is selected from that dropdown, the next dropdown will appear. The available options for the 2nd dropdown will depend on what is selected in the first dropdown. The ng-repeat directive is iterating over an array of choices. Here is the html and the js code.
HTML:
<select name="application" placeholder="Select a Tenant"
ng-disabled="!sharedObj.tenantApplications ||
sharedObj.tenantApplications.length == null"
class="form-control" id="application"
ng-change="vmOrderItem.vmNameUSI=null" ui-select2
ng-model="vmOrderItem.tenantApplication" title="Select tenant application"
data-style="btn-default" required><option></option>
<option ng-repeat="tenantApplication in sharedObj.tenantApplications |
filter:tenantFilter()" value="{{tenantApplication.id}}">{{tenantApplication.name}}
</option>
</select>
JS:
/** Filters the tenant depending on what domain is selected */
$scope.tenantFilter = function(tenantApplication) {
$scope.sharedObj.tenantApplications;
tenantApplication.name;
tenantApplication.id;
return true;
/* return $scope.vmOrderItem.domain.id == tenantApplication.domainId;*/
}
The issue I get is that even if I return true, nothing ever shows up on the dropdown. I did this to test the logic. I don't know why the tenantApplication parameter is always undefined in the function. I used google chrome inspect element to insert a breakpoint and it complains that the argument is undefined. But I don't see why it wouldn't work properly when I return true. I'm a newbie to JavaScript and AngularJS so any help is greatly appreciated. I've worked through all the AngularJS examples and read their docs but I'm still just a beginner.
Think this should be:
<option ng-repeat="tenantApplication in sharedObj.tenantApplications |
filter:tenantFilter" value="{{tenantApplication.id}}">
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.
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>
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!