Angularjs Select doesn't seem to update ng-model when option chosen - angularjs

I have two SELECTs on a page. They both load the possible options correctly and the ng-model appears to set properly as the initial value is set based on values in the model when loaded. I want to be able to make sure that the user does not choose a value for both of the SELECTs so I added a function for the ng-click. Inside the function I check if one was initially set that the other model does not now have a value. The problem I am facing is that when I get into the function, the models don't appear to be reflecting what the user has chosen.
I looked at a lot of questions on here and found solutions that indicated that the ng-options probably needed some changes. I have tried what I have seen, but nothing seems to be helping.
Here are the two HTML SELECTs
<select ng-model="example3model" class="form-control input-md" ng-click="checkTags(3)" ng-options="industry as industry.text group by industry.group for industry in industryData track by industry.id" >
<option value="">-- Select Industry --</option>
</select>
<select ng-model="example4model" class="form-control input-md" ng-click="checkTags(4)" ng-options="product as product.text group by product.group for product in productData track by product.id" >
<option value="">-- Select Product --</option>
</select>
Both arrays (industryData and productData) look similar (different actual values) and look like this:
industrydata is an array of about 28 objects like these 3...
{group: "Energy and Natural Resources", id: "5", text: "Chemicals"}
{group: "Consumer Industries", id: "6", text: "Consumer Products"}
{group: "Public Services", id: "7", text: "Defense Security"}
If I look at the model of one of the selects if initially set with values it looks like: (this is for an 'example4model'
Object
group : "Finance"
id : "34"
text : "Governance, Risk, and Compliance"
My function snippet looks like this:
$scope.checkTags = function(curModel) {
if (curModel == 3) {
if ($scope.example4model != null && $scope.example4model.text != '' && $scope.example3model != null) {
$rootScope.showMsg("Remove Product before adding an Industry.");
$scope.example3model = null;
}
} else {
if ($scope.example3model != null && $scope.example3model.text != '' && $scope.example4model != null) {
$rootScope.showMsg("Remove Industry before adding a Product.");
$scope.example4model = null;
}
}
};
If example4model is set initially, and I try to choose a value from the example3model select, I would think when I come into the function, I should see some value in example3model, but it is null. If I change the option chosen for example4model, when I come into the function, it shows the initial value and not the newly selected one.
It seems that somehow the model is not being updated to show the chosen options but I can't figure out why. Based on responses to other questions, I added the 'as' clause and the 'track by' clauses but that didn't help either.
Any help would be appreciated.

So I drew up a sample of your provided snippets in Plunker (bottom of post)...
Have you tried initializing your models with null?
What may be causing the issue on your end (if I understand the issue correctly) is that your models will be undefined before being set using the <select>. And in your checkTags() method, you are checking for "not null".
I suggest declaring your models in your controller like so:
$scope.example3model = null;
$scope.example4model = null;
This should allow your checkTags() if statements to catch the model values before being set. Alternatively, you can change your if statements to check for whether the model is "undefined" instead.
Other Recommendations
I also might recommend changing ng-click to ng-change -- ng-click will fire your checkTags() function whenever the <select> is clicked whereas ng-change just fires it when an option is selected.
In your checkTags() if statements, you can null check with a simple if($scope.example3model) -- check my snippet for those (line 43).
Don't forget to use !== when you are checking a value and looking for a truthy / falsy (bool) evaluation.
Plunker
https://embed.plnkr.co/mUgsqY/
Wrap checkTags() in a $timeout:
// In your HTML
<select ng-model="example3model" ng-click="initiateCheckTags(3)">
<option value="">-- Select Industry --</option>
</select>
// In your Controller
$scope.initiateCheckTags = function(curModel) {
$timeout(function() {
$scope.checkTags(curModel);
}, 100);
}

Related

getting selected value for select list in angular from a $firebaseArray()

I have a simple select list that is based on a $firebaseArray(). I dont have a problem getting the values into the drop. Just the selected value.
<select class="form-control" ng-model="vm.selectedRole"
ng-options="role.name for role in vm.allRoles">
</select>
The $firebaseArray looks like this
In my controller the function that initializes the form with the select is
Get.getParentUrl('roles').$loaded()
.then(function (data) {
vm.allRoles = Get.getParentUrl('roles');
vm.selectedRole = entity.role.name;
})
And this populates the select but it does not set the selected value for it on vm.selectedRole. Note that entity is the value that is being passed , so if i write a
console.log(entity.role.name);
The returned value is the selected value that is being passed. So if the user selects a user with a role "Supervisor" and i write a console.log(vm.selectedRole) inside the .then(function(data){ the value returned is "Supervisor"
However the html displays a "?"
I got it working by adding the vm.selectedRole like so
vm.selectedRole = { name: entity.role.name };
Which works i guess. Syntax seems a bit crappy though
https://docs.angularjs.org/api/ng/directive/ngOptions

Angularjs Binding Dropdown using ng-options

I have looked at the angular documentation https://docs.angularjs.org/api/ng/directive/ngOptions but still can't figure this one out.
I have a list of sexes that get bound to a select like this:
$scope.sexes = jQuery.grep(formData, function(a) {
return (a.category == "Sex");
});
the JSON for the sex list looks like this:
2: Object
alternateCode: null
category: "Sex"
code1: "F"
codeID: 60002
description: "Female"
lastModifiedBy: ""
lastModifiedDate: "1900-01-01T00:00:00"
subCategory: null
The member object that should make the select choice has a property on it sex:M. The problem is when I try to bind the select it will populate the list correctly but will not select the option I need:
<select name="sex" id="sex" class="form-control"
ng-model="editableMember.sex"
ng-options="s.sex as s.description for s in sexes track by s.code1 "></select>
Any help would be greatly appreciated
Perhaps you missed this part of the documentation:
Do not use select as and track by in the same expression. They are not designed to work together.
The ng-model value will be the result of either the select or track by expression. The following code for ng-options should work:
ng-options="s.code1 as s.description for s in sexes"

Angularjs how to set the default value for select

I have the following object:
defaults = {
0 : {
id : 10,
value : "string 1"
},
1 : {
id : 22,
value : "string 2"
}
}
I want to iterate over this object and display it as a select box.
<select ng-model="selectedValue" ng-options="obj.id as obj.value for obj in defaults">
<option value="">---Select option-----</option>
</select>
What I'm trying to achieve is to select 'string 2' by default. But it does not work.
The problem I have is the fact the selectedValue is a string:
$scope.selectedValue = "string 2";
From what I learned from the documentation the selectedValue must be the same object. But unfortunately, it is not possible. In my case selectedValue must be a string.
In other words I need to operate with the name of the option only, I don't care about id.
I tried to use ng-repeat. It even works but displays an empty option and I don't think using ng-repeat is a good way to do it.
Any advice will be appreciated greatly.
If you want the selectedValue variable to contain the value, and not the ID, then you should not use obj.id as obj.value, but obj.value as obj.value.
Selected value should be id;
$scope.selectedValue = 22;
See Demo
EDIT:
change template
<select ng-model="selectedValue" >
<option value="">---Select option-----</option>
<option ng-selected="selectedValue == obj.value" value="{{obj.value}}" ng-repeat="obj in defaults">{{obj.value}}</option>
</select>
see Updated Demo
I think you misinterpreted the documentation.
Selected value should refer to a value of the same object, not be an object itself.
Thus, you can set the default value as :
$scope.selectedValue = $scope.defaults[1].value;
That way, the default value will be set - it does not matter if the value is a string or a number.
If you are using ng-repeat with options you need to use on-last-repeat on your options tag. For example
select name="repeatSelect" id="repeatSelect" ng-model="usertypes.SelectedId"
option ng-repeat="option in usertypes.AvailableOptions" value="{{option.Id}}" ng-selected="option.Id === usertypes.SelectedId" on-last-repeat>{{option.Name}}
select

issues with select field's empty option

We are facing multiple issues with select field's empty option.
My rendering code is as follows:
<select ng-switch-when="select" id="{{field.name}}" ng-model=data[field.name] >
<option ng-repeat="option in field.options" value="{{option.value}}">{{option.description}}
</select>
Here our UI is dynamically generated and options also populates dynamically using REST APIs. The Select field is bound to a data object that also populated using REST calls that might have blank value initially.
Issue
It automatically adds a empty option where it is not required and disappear after selecting any non-empty option.
Also it is showing following error for few select fields
TypeError: Cannot call method 'prop' of undefined
at selectDirective.link.ngModelCtrl.$render (lib/angular/angular.js:20165:47)
at Object.ngModelWatch (lib/angular/angular.js:16734:14)
at Scope.$get.Scope.$digest (lib/angular/angular.js:11800:40)
at Scope.$get.Scope.$apply (lib/angular/angular.js:12061:24)
at done (lib/angular/angular.js:7843:45)
at completeRequest (lib/angular/angular.js:8026:7)
at XMLHttpRequest.xhr.onreadystatechange (lib/angular/angular.js:7982:11)
I have doubt that is use following code in angular
function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
ngModelCtrl.$render = function() {
var viewValue = ngModelCtrl.$viewValue;
if (selectCtrl.hasOption(viewValue)) {
if (unknownOption.parent()) unknownOption.remove();
selectElement.val(viewValue);
if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
} else {
if (isUndefined(viewValue) && emptyOption) {
selectElement.val('');
} else {
selectCtrl.renderUnknownOption(viewValue);
}
}
...
and it break at this line
if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
because the empty option is provided by REST API at later stage and not available till initial rendering.
Please provide some suggestion for implementation and some alternate approach.
P.S : I can not use ng-option with select as it emit indexed values and I need actual values for some DOM manipulation.
I would first read over how to do data-ng-options (http://docs.angularjs.org/api/ng.directive:select) because your select will cause you a bit of issues. Here's how you could move your code around:
<span data-ng-switch-when="select">
<select id="{{field.name }}" data-ng-model="data[field.name]" data-ng-options="option.value as option.description for option in field.options></select>
</span>
Secondly, the reason that the blank option is selected is because data[field.name] is not set to a value that's present in option.value. You need to set it in your controller so the blank option goes away. You can see a similar question here: Why does AngularJS include an empty option in select?

Angular select adding empty element despite carefulness

I have this html:
<select ng-model="group.newCriterionType">
<option ng-repeat="type in group.availableTypes" value="{{type}}" ng-selected="$first">{{type}}</option>
</select>
And this model code (using jresig's Class mini-library)
var FilterGroup = Class.extend({
className: 'FilterGroup',
widgetType: 'group',
init: function(name) {
this.name = name;
this.availableTypes = FilterTypes;
this.newCriterionType = this.availableTypes[0];
this.updateAvailableTypes();
},
});
However, I still get an empty element in my select. According to all the answers I've seen on SO so far, this is apparently the behaviour of when your model value contains an incorrect value. However:
I added in some console.log statements to check the value
This code is definitely being called because availableTypes is being set
It's pulling it from the array it's looping from. How can this be an incorrect value?
It persists even if i pull the ng-selected out
It persists if I use ng-options instead of looping through them (though that then means i can't set the value to the be the same as the text without turning it into an object)
Any clues much appreciated.
James

Resources