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"
Related
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);
}
I was trying to find the AngularJS select with ng-options or Typeahead expression syntax but I couldn't find the whole thing in one place, so I gather information from here and there and this is what I came up with:
Expression syntax (This is the full syntax, most of it are optional):
(ObjectForModel) as (stringRepresentation for the UI) for (OneObjectFromList) in (ListOfObjects) | (Filter1) | (Filter2) ...
Example: Lets say we have a list of Students:
var StudentList = [{firstName: "Jhon",lastName:"Smith" id:1},{firstName: "Clint",lastName:"Eastwood" id:2} ];
Lets say that we wanna use this list in a typeAhead input but:
1. We want our popup drop down to display: "first name - last name" but when a user select an item we want the whole item from the list to be populate in the ng-model.
2. We want to filter the select to show only 5 elements
3. We want the pop up drop down list to display only what is relevant base on the user input.
So this is how it looks like:
uib-typeahead="student as (student.firstName +' - ' + student.lastName) for student in studentList | filter:$viewValue | limitTo:5"
If you guys have something more to add please do, I know I could have use it...
You can also change the template ( for example displaying a field in a particular way, and on click set the input with another one )
in the html file :
<script type="text/ng-template" id="deterFormACTemplate.html">
<a ng-bind-html="match.model.displayed | unsafe"></a>
</script>
<input typeahead-template-url="deterFormACTemplate.html"
uib-typeahead="item as item.field for item in autocomplete(...)"
typeahead-on-select="mymodel=$model.field;"
typeahead-wait-ms="500" />
in the controller
$scope.autocomplete = function ( ){
return [ {'field':'..', "displayed":"..."},{'field':'..', "displayed":"..."}, .. ];
}
I would like to filter out a object that has a property value of "None". The object CounterParty has 2 properties, CounterPartyId and CounterPartyName.
The first object in the db has CounterPartyName: "None", I do not want this to show in the select box options.
I setup a plunker but the select-box is not working and there are no errors in the console:
Plunker
<select ng-model="search.CounterParty"
ng-options="c.CounterPartyName as c.CounterPartyName for c in counterPsList | unique: 'CounterPartyName'">
{{c.CounterParty}}
</select>
Json
$scope.counterParties = [
{"$id":"1","CounterPartyId":1,"CounterPartyName":"None","Documents":null},
{"$id":"2","CounterPartyId":2,"CounterPartyName":"CounterParty A","Documents":null},
{"$id":"3","CounterPartyId":3,"CounterPartyName":"Counter Party B","Documents":null},
{"$id":"4","CounterPartyId":4,"CounterPartyName":"Counter Party C","Documents":null},
{"$id":"5","CounterPartyId":5,"CounterPartyName":"Counter Party D","Documents":null}
];
You don't need to use angular-ui's unique filter here - its purpose is something else.
If you just need to filter out based on a certain property, you could specify the filter expression like so (notice the !):
ng-options = '...in counterPsList | filter: { CounterPartyName: "!None" }'
plunker
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
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