I've created the following example so you can see exactly what is happening: http://jsfiddle.net/8t2Ln/101/
The same thing happens if I use ng-options. I have a different reason for doing it this way, but for the simplification of the example left that part out.
As you can see it has by default two options. I'm displaying the selected value of the ng-model next to the select so you can see what it is. When you use the top piece to add a third option it sets the value to the value of that new option as is evidenced by the displayed ng-model value next to the select, but the select itself doesn't change to show the correct value selected.
Below is the sample code at the link:
var testApp = angular.module('testApp', ['ngRoute']);
testApp.controller('Ctrl', function ($scope) {
$scope.newInput = '';
$scope.inputDevice = [
{
value: '1',
label: 'input1'
},
{
value: '2',
label: 'input2'
}
];
$scope.selectedDevice = '';
$scope.addType = function () {
var newElem = {
label: $scope.newInput,
value: '3'
};
$scope.inputDevice.push(newElem);
$scope.selectedDevice = newElem.value;
};
});
And here is the html:
<div ng-app="testApp">
<div ng-controller="Ctrl">
<p>
<input type="text" ng-model="newInput" />
<br />
<button ng-click="addType()">Add Type</button>
</p>
<select ng-model="selectedDevice">
<option></option>
<option ng-repeat="i in inputDevice" value="{{ i.value }}">{{ i.label }} - {{ i.value }}</option>
</select>
{{ selectedDevice }}</div>
</div>
This is exactly why you should not use ngRepeat to render select options. You should use ngOptions instead:
<select ng-model="selectedDevice"
ng-options="i.value as (i.label + '-' + i.value) for i in inputDevice">
<option></option>
</select>
In general, avoid using ngRepeat for rendering select options. There are at least two good reasons. ngRepeat creates separate child scope per iteration, which is not needed in case of option tag. Another important caveat is that with ngRepeat you can only bind select to primitives like strings, but you won't be able to write object to ngModel with it.
Here is a demo below.
angular.module('demo', []).controller('DemoController', function($scope) {
$scope.newInput = '';
$scope.inputDevice = [
{value: '1', label: 'input1'},
{value: '2', label: 'input2'}
];
$scope.selectedDevice = '';
$scope.addType = function() {
var newElem = {
label: $scope.newInput,
value: Number($scope.inputDevice[$scope.inputDevice.length - 1].value) + 1
};
$scope.inputDevice.push(newElem);
$scope.selectedDevice = newElem.value;
$scope.newInput = '';
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
<form ng-submit="addType()">
<input type="text" ng-model="newInput" />
<button type="submit">Add Type</button>
</form>
<select ng-model="selectedDevice" ng-options="i.value as (i.label + ' - ' + i.value) for i in inputDevice">
<option>Select</option>
</select>
{{ selectedDevice }}
</div>
The problem is that, since you're not using ng-options the browser had not finished rendering at the point when you set the new selectedDevice. If you're set on on using ng-options you can use this workaround. Use $timeout to wrap your $scope.selectedDevice = newElem.value; to ensure it runs after the browser has finished rendering the changes with ng-repeat.
I also added code to increment the next value on successive adds because hardcoding it to '3' meant that the third option would continually be selected even when more are added.
var testApp = angular.module('testApp', ['ngRoute']);
testApp.controller('Ctrl', function($scope, $timeout) {
$scope.newInput = '';
$scope.inputDevice = [{
value: '1',
label: 'input1'
}, {
value: '2',
label: 'input2'
}];
$scope.selectedDevice = '';
$scope.addType = function() {
var last = Number($scope.inputDevice[$scope.inputDevice.length - 1].value) + 1;
var newElem = {
label: $scope.newInput,
value: last.toString()
};
$scope.inputDevice.push(newElem);
$timeout(function() {
$scope.selectedDevice = newElem.value;
}, 0);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular-route.js"></script>
<div ng-app="testApp">
<div ng-controller="Ctrl">
<p>
<input type="text" ng-model="newInput" />
<br />
<button ng-click="addType()">Add Type</button>
</p>
<select ng-model="selectedDevice">
<option></option>
<option ng-repeat="i in inputDevice" value="{{ i.value }}" ng-selelected="{{ selectedDevice == i.value }}">{{ i.label }} - {{ i.value }}</option>
</select>
{{ selectedDevice }}
</div>
</div>
I had a similar problem and the reason was that my key was a number, but when trying to set another value I was sending a string. The workaround in this case is to force to set the model value to the same type as the key.
eg:
<select ng-model="model" ng-options="option.{{ key }} as option.{{ label }} for option in options">
<option value="">{{ emptyLabel }}</option>
</select>
if (scope.options.length > 0) {
scope.keyType = typeof(scope.options[0][scope.key]);
}
...
if (scope.keyType == 'number') {
scope.model = parseInt(newVal, 10);
} else {
scope.model = newVal;
}
I had the same issue of select not updating when ng-model is updated. I was retrieving the value for ng-model from a function which extracted the object from the array based on a key,value pair.
In doing this, the returned object had the hashkey property $$hashKey: "object:115"
The problem occurred when I created a copy of the object using angular.copy which stripped off this 'hashkey' property and hence would not get selected.
After I reorganized the code, to get ng-model value after angular.copy, the issue was resolved
ConstructorReviewers: function (oItem) {
this.PERSON_ID = oItem.PERSON_ID;
this.CHAIR_PERSON = oItem.CHAIR_PERSON;
/* // Commented this part and added it to EditItem function
this.oDepartment = CommonFactory.FindItemInArray(vm.oCommittee.arrDepartments, 'NAME', this.DEPARTMENT, 'item');
*/
this.EditItem = function () {
vm.EditItemOriginal = this;
angular.copy(this, vm.EditItem); // After this update the ng-model into vm.EditItem.oTitle object
vm.EditItem.oTitle = CommonFactory.FindItemInArray(vm.oCommittee.arrTitles, 'TITLE', vm.EditItem.TITLE, 'item');
vm.Popup.ShowPopup(true, 'new_edit', Constants.Mentoring.Popup.Edit);
}
}
I had the same problem. What solved it for me is converting the number to a string. Example:
$scope.selectedDevice = "" + newElem.value;
Related
I want to get the value attribute of the options of the select...
here is my html
<select ng-model = "selectedElement">
<option vlaue = "1">john</option>
<option vlaue = "2">harry</option>
<option vlaue = "3">peter</option>
</select>
when I run the code
console.log($scope.selectedElement);
I got the result "john" in console
but what I expected is to get the value attribute. for eg "1" in console.
is there any way to do that.
You are using vlaue in the option which is incorrect. Use value that will set the value of each option and gives you that value on $scope.selectedElement
var app = angular.module('myApp', []);
app.controller('MainCtrl', ['$scope', function($scope) {
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainCtrl">
<select ng-model="selectedElement">
<option value="1">john</option>
<option value="2">harry</option>
<option value="3">peter</option>
</select>
selected value is {{selectedElement}}
</div>
You should try this code as well.
Define your select box data as an array.
$scope.Fruits = [{
Id: 1,
Name: 'Apple'
}, {
Id: 2,
Name: 'Mango'
}, {
Id: 3,
Name: 'Orange'
}];
Then define a function in your controller page.
$scope.GetValue = function (fruit) {
var fruitId = $scope.ddlFruits;
var fruitName = $.grep($scope.Fruits, function (fruit) {
return fruit.Id == fruitId;
})[0].Name;
$window.alert("Selected Value: " + fruitId + "\nSelected Text: " + fruitName);
}
And last add the select tag in your html.
<select ng-model="ddlFruits" ng-options="fruit.Id as fruit.Name for fruit in Fruits track by fruit.Id"
ng-change="GetValue()">
</select>
Try with this code.Hope this will fix your issue.
<select ng-model="cart.fruit" ng-options="state as state.name for state in shelf"></select>
<br/>
<tt>Cost & Fruit selected: {{cart.fruit}}</tt>
Try above code.
How to update new value choosing from select box on click save button.
I am using ng-click function like this in my JS function for update button:
$scope.updateDealDetail = function updateDealDetail (){
$scope.showEditView = !$scope.showEditView;
$scope.dealDetail.decisionMakerDetail.email = $scope.selectedid;
}
My function for edit button:
$scope.editUserDetail = function editUserDetail(){
$scope.showEditView = !$scope.showEditView;
$scope.showSubmitView = !$scope.showSubmitView;
deal.getIdData($scope.accountDetail. accountUsers[0].role,$scope.accountDetail.id).then(function successCb(data){
$scope.editIdOptionsData=data;
$scope.selectedid = $scope.editIdOptionsData[0].email;
});
};
and my HTML for bitton click is like this :
<select ng-model="selectedid" class="form-control">
<option ng-selected="selectedid" ng-repeat="eiod in editIdOptionsData" value="{{eiod.email}}">{{eiod.email}}
<button ng-click="updateDealDetail(eoid.email)" ng-disabled="dealDataSaveButtonDisabled">Update</button>
I am trying to this through ng-repeat because of by using ng-options my data through API is now showing in the box. But My data which is on first index is only getting set. What to do to set the a default value for the selection box and by selection any value, onclick need to update that value.
Don't use ngRepeat to render options, this is your problem. Correct code would be:
<select class="form-control"
ng-model="selectedid"
ng-options="eiod.email as eiod.email for eiod in editIdOptionsData">
</select>
Best practice to use ng-options, ng-model and ng-change on the <select> element
Online demo - https://plnkr.co/edit/Gaa8sMgerRv6chio4iYa?p=preview
html
<select
ng-model="selectedItem"
ng-change="onSelectedItemChanged()"
ng-options="item as item.email for item in items"></select>
js
app.controller('MainCtrl', function($scope) {
$scope.items = [{
email: 'asd1#asd.com'
}, {
email: 'asd2#asd.com'
}];
$scope.selectedItem = $scope.items[0];
$scope.onSelectedItemChanged = function() {
alert('you changed it to ' + $scope.selectedItem.email);
}
});
In my Angularjs project, I have problem while using ng-model inside ng-repeat. When i select the value in select box, the selectbox automatically gets selected with previous selected value. I think this is due to the same ng-model inside ng-repeat. How can we fix this issue?
HTML:
<div ng-repeat="x in data">
<select class="selectbox_menulist" ng-change="endpoint.showEndPointStatsData()" ng-model="graphSelect.value">
<option ng-repeat="opt in mapOptions" value="{{opt.value}}">{{opt.type}}</option>
</select>
</div>
JS:
$scope.mapOptions = [
{ value: "bytes",type:"Bytes/sec" },
{ value: "packets",type:"Packets/sec"},
{ value: "megabytes",type:"Megabytes/sec"}
];
showEndPointStatsData: function() {
console.log('Function called ====');
console.log($scope.graphSelect.value);
}
Use array to store value of mutli ng-model in ng-repeat:
<div ng-repeat="x in data track by $index">
<select class="selectbox_menulist" ng-change="endpoint.showEndPointStatsData($index)" ng-model="graphSelect[$index]">
<option ng-repeat="opt in mapOptions" value="{{opt.value}}">{{opt.type}}</option>
</select>
</div>
$scope.mapOptions = [{ value: "bytes",type:"Bytes/sec" }, { value: "packets",type:"Packets/sec"},{ value: "megabytes",type:"Megabytes/sec"}];
$scope.graphSelect = new Array($scope.data.length);
showEndPointStatsData: function(index) {
console.log('Function called ====');
console.log($scope.graphSelect[index]);
ng-model inside ng-repeat
jsfiddle
The above link has good description on how to use it with examples
How can I set the selected value of a dropdown when I edit an item ?
<div class="form-group">
<label for="category" class="col-sm-2 control-label">Category</label>
<div class="col-sm-10">
<select ng-model="quiz.category" ng-options="category as category.name for category in categories" required>
<option></option>
</select>
</div>
</div>
And when I click on edit
$scope.editQuiz = function(quiz)
{
$scope.quiz = {};
$scope.quiz.name = quiz.name // this works fine
$scope.quiz.category = quiz.category[0]; // ?????
console.log($scope.quiz.category);
//$scope.quiz = quiz;
}
Method to get categories:
$scope.getCategories = function() {
$http.get('http://localhost/myappi/API/index.php/Api/categories').
success(function(data) {
$scope.categories = data;
})
.error(function(err) {
console.log('error',err);
})
};
Ok if you really want to keep quiz.category as an array.
At first when you get the quiz assign quiz.category to an new object.
e.g:
$scope.tmp = { category: quiz.category[0] };
We have to do that since quiz.category is an array but the value of the ng-options is an object.
now we can bind that var to the options like this:
<select ng-model="tmp.category" ng-options="category as category.name for category in categories" required>
<option></option>
</select>
and finally in your function you replace the old value with the new:
$scope.quiz.category[0] = tmp.category;
Hope it makes sense
Changing the select's ngModel is definitely the way to go. You can check out this solution, since I believe it deals with the same problem.
$scope.options = [{ name: "a", id: 1 }, { name: "b", id: 2 }];
$scope.selectedOption = $scope.options[1];
<select data-ng-options="o.name for o in options" data-ng-model="selectedOption"></select>
Can you send us your data structure sample?
Use "track by" inside the ng-options
category as category.name for category in categories track by category.id
working example
I am generating some <option> elements using the ng-repeat directory. Using ng-repeat instead of ng-options is intentional.
However, it generates an empty option in addition to the actual array. Here's the code:
<select name="type" class="form-control" ng-model="selected_type" ng-change="select_change()" >
<option ng-repeat="type in types" value="{{type.value}}">{{type.name}}</option>
</select>
$scope.types = [
{value: '1', name: 'Sale'},
{value: '2', name: 'Other'}
];
$scope.selected_type = $scope.types[0].value;
And a fiddle: http://jsfiddle.net/HB7LU/521/
Here's a working fiddle, using ng-options
http://jsfiddle.net/HB7LU/527/
<select ng-model="selected_type" ng-change="select_change()" ng-options="c.name for c in types">
Then on script.js:
$scope.selected_type = $scope.types[0];
With that said, since you're just partly using angularjs you can just map the data in an array before you actually post in say in PHP.
try ng-options instead of making options tag yourself:
<div ng-controller="MyCtrl">
<select ng-model="selected_type" ng-change="select_change()" ng-options="type.value as type.name for type in types">
</select>
</div>
http://jsfiddle.net/aBPdv/
var myApp = angular.module('myApp', []);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.types = [
{value: '1', name: 'Sale'},
{value: '2', name: 'Other'}
];
$scope.selected_type = $scope.types[0].value;
$scope.select_change = function(x){
alert($scope.selected_type);
}
}
Just use the ng-model attributes on your option tag not on your select tag (use it where the ng-repeat is defined) like that :
<select ng-change="select_change()">
<option ng-model="selected_type" ng-repeat="type in types" value="{{type.value}}">{{type.name}}</option>
</select>
Then change your
$scope.selected_type = $scope.types[0].value;
to
$scope.selected_type = $scope.types;
But your ng-change will not work because no ng-model attribute is set so no ngModelController is assign to this element.
So if you want to know when the value of the select change you have to do a directive on the select element.
For all these reasons ng-options is always and i say always the right direction for a select input usage.