angularjs select showing non filtered selected - angularjs

I'm ran across the following that I found to be strange. I'm not blocked by it but was curious if someone knew. When I use hasOwnProperty with a select option, it shows a value (A2F0C7) not in the dropdown as selected.. Can anyone share why this is happening? Here is the jsfiddle:
http://jsfiddle.net/stampyNY/2oeo8of9/1/
<div ng-controller="TestCtrl">
<select>
<option ng-repeat="(k,v) in items" ng-show="v.hasOwnProperty('test')" value="{{k}}">{{k}}</option>
</select>
var app = angular.module('app', []);
function TestCtrl($scope) {
$scope.items = {
'A2F0C7':{'secId':'12345', 'pos':'a20'},
'C8B3D1':{'pos':'b10'},
'WAM':{'test': 1, 'pos':'b10'}
};
}
Thank You!

In angularJS, when you add "ng-show={{expression}}", the expression will be validated (either to true or false) and add the style "display: none;" respectively.
As a result, you will have something rendered in your HTML:
<select>
<!-- ngRepeat: (k,v) in items -->
<option ng-repeat="(k,v) in items" ng-show="v.hasOwnProperty('test')" value="A2F0C7" class="ng-scope ng-binding" style="display: none;">A2F0C7</option>
<option ng-repeat="(k,v) in items" ng-show="v.hasOwnProperty('test')" value="C8B3D1" class="ng-scope ng-binding" style="display: none;">C8B3D1</option>
<option ng-repeat="(k,v) in items" ng-show="v.hasOwnProperty('test')" value="WAM" class="ng-scope ng-binding">WAM</option>
</select>
With this style added, the value won't be showed in your drop down box, but by default the first value will be selected for html select tag. That's the reason why you see this value (although it shouldn't).
To fix this,simply update your code by adding ng-selected:
<select>
<option ng-repeat="(k,v) in items" ng-show="v.hasOwnProperty('test')" ng-selected="v.hasOwnProperty('test')" value="{{k}}">{{k}}</option>
</select>

As was previously posted ng-show just controls the visibility of the DOM object which does not prevent it from beeing selected initially. It would be preferable to not create the actual DOM element for entries which shouldn't be visible.
This could be done using a custom filter:
app.filter('filterTestProperty', function() {
return function(values) {
var result = {};
for (var key in values){
var value = values[key];
if (value.hasOwnProperty('test')){
result[key] = value;
}
}
return result;
}
});
And the HTML:
<option ng-repeat="(k, v) in items | filterTestProperty" value="{{k}}">{{k}}</option>
var app = angular.module('app', []);
app.filter('filterTestProperty', function() {
return function(values) {
var result = {};
for (var key in values) {
var value = values[key];
if (value.hasOwnProperty('test')) {
result[key] = value;
}
}
return result;
}
});
app.controller('TestCtrl', function TestCtrl($scope) {
$scope.items = {
'A2F0C7': {
'secId': '12345',
'pos': 'a20'
},
'C8B3D1': {
'pos': 'b10'
},
'WAM': {
'test': 1,
'pos': 'b10'
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestCtrl">
<select>
<option ng-repeat="(k, v) in items | filterTestProperty" value="{{k}}">{{k}}</option>
</select>
</div>

Related

Angularjs ng-change and ng-repeat not properly working

In ng-change the selected value is not setting up in the ngchange function.
First time when I select a value its setting up as null, and again I try to select an another value, its setting the value of the previous selected value.
var ngInitParams = JsonConvert.SerializeObject(Model);
var firstVarId= Model.Variants.First().ProductId;
var firstVarName= Model.Variants.First().Name;
<section id="#inPageNavigationID" ng-controller="prodSpecsCtrl as main"
ng-init="main.init('#firstVarId', '#firstVarName')">
<div class="container" ng-init="main.loadSelect('#ngInitParams')">
<div>
<div class="row">
<div class="col-sm-6 fieldset">
<div class="form__item ">
<div>
<select class="-dropdown--two-columns" name="productvariants" id="sel1" data-placeholder="#selectOptionVal" ng-model="variant.ProductId"
ng-change="main.load('{{variant.ProductId}}','{{(main.JsonVariants.Variants | filter: {ProductId:variant.ProductId})[0].Name}}')">
<option value="" disabled>Select Model</option>
<option ng-repeat="variant in main.JsonVariants.Variants" value="{{variant.ProductId}}" selected="#firstVariantId" data-option-header="{{variant.CatalogCode}}">{{variant.Name}}</option>
</select>
<span class="fa fa-angle-down"></span>
</div>
</div>
</div>
</div>
</div>
<section>
this.init = function (varId, varName) {
this.load(varId, varName);
}
this.loadSelect = function (strjson) {
self.JsonVariants = JSON.parse(strjson);
}
Here is an example of an ng-change within a select.
https://plnkr.co/edit/ZhJbVfPRCLoeFwYoi3Mp?p=preview
<body ng-controller="MainCtrl">
<select ng-model="item" ng-change="changed(item)" ng-options="item.Name for item in items"></select>
<p>ID:{{selected.ID}} Name: {{selected.Name}}</p>
<p>You Selected: {{selected}}</p>
</body>
And Controller:
app.controller('MainCtrl', function($scope) {
$scope.items = [];
$scope.selected = {};
$scope.changed = function(item) {
$scope.selected = item;
}
function setupItems() {
for (var i = 0; i < 10; i++) {
var item = {ID: i, Name: "Item " + i}
$scope.items.push(item);
}
}
setupItems();
});

show no data available message when ng-options is empty in select?

I have created an select element as
<label class="item item-select no-border-bottom padding full-width custom-back">
<div class="input-label">Select Time Slot</div>
<select ng-model="addAppointment.timeSlot" name="timeSlot" class="custom-back" ng-disabled="!addAppointment.date" ng-options="timeSlot as timeSlot for timeSlot in availableTimeSlots" required>
</select>
</label>
I would like a option having message No Data in select when ng-options array is empty.
You could add an <option> with ng-if to your select. Here is a contrived example of how this would work.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.options = [];
$scope.selectedOption = undefined;
$scope.addOptions = function() {
var start = $scope.options.length;
for(var i = 1; i <= 5; i++) {
$scope.options.push('Option #' + (start + i));
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select ng-model="selectedOption" ng-options="opt as opt for opt in options">
<option value="" ng-if="options.length === 0">No Data</option>
</select>
<button type="button" ng-click="addOptions()">Add Options</button>
</div>

how to use indexof in array set in angularjs

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myctrl', function($scope) {
$scope.state = [{name:'TamilNadu', code:1}, {name:'Kerala', code:2}, {name:'Karnataka', code:3}];
$scope.onChange = function() {
var a = this.drop.state; }
});
</script>
<body>
<div ng-app="myApp" ng-controller="myctrl">
State :
<select id="stat" ng-model="drop.state" ng-change="onChange()">
<option ng-repeat = "x in state"> {{x.name}} </option>
<select>
</div>
</body>
In this code, I can be able to get the selected value from the textbox in the variable a. Now, I need to get the code value of the name selected. Is it possible using indexof(). And I need it in dynamic ie., when the 'state' is selected I need that corresponding 'code' from the array set.
<option value="{{x}}" ng-repeat = "x in state"> {{x.name}} </option>
If you add the value on your Option, you may get the complete object, and accessing the code and the Value
you can assign code as value to option
<option ng-repeat = "x in state" ng-value="x.code"> {{x.name}}
Demo
var app = angular.module('myApp', []);
app.controller('myctrl', function($scope) {
$scope.drop = {}
$scope.state = [{name:'TamilNadu', code:1}, {name:'Kerala', code:2}, {name:'Karnataka', code:3}];
$scope.onChange = function() {
var a = $scope.drop.state
console.log(a)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myctrl">
State :
<select id="stat" ng-model="drop.state" ng-change="onChange()">
<option ng-repeat = "x in state" ng-value="x.code"> {{x.name}} </option>
</select>
</div>
Even though the other answer is valid, this is the right way to go about it:
<select id="stat" ng-model="drop.state" ng-options="x.code as x.name for x in state" ng-change="onChange()">
<option value="">Select a value</option>
</select>
If the purpose of the ng-change was to get the state code, this way it's not needed. Your ng-model will be equal to the selected state code.
You can bind data to a single property., and can access both. with preferred ng-options .
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myctrl', function($scope) {
$scope.state = [{
name: 'TamilNadu',
code: 1
}, {
name: 'Kerala',
code: 2
}, {
name: 'Karnataka',
code: 3
}];
$scope.onChange = function() {
alert(this.drop.state.name);
alert(this.drop.state.code);
}
});
</script>
<body>
<div ng-app="myApp" ng-controller="myctrl">
State :
<select id="stat" ng-model="drop.state" ng-options= "x as x.name for x in state" ng-change="onChange()"> </select>
</div>
</body>

How to pass an object to the value property in option tag using angular?

I have a select tag which i have loaded the data through angular ng-repeat.
<select ng-model="user.accessRole">
<option ng-selected="{{item.name == user.accessRole.name}}"
ng-repeat="item in accessRoles" value="{{item}}">
{{item.name}}
</option>
</select>
Once I submit this the value I got for accessRole model is as below.
accessRole:"{"id":1,"name":"admin","accessRights":"administrative access"}"
I want this value to be passed without double quotes. That means,
accessRole:{"id":1,"name":"admin","accessRights":"administrative access"}
I tried out this by removing double quotes in value property.(value={{item}})
But it didn't give me the solution.
How can i do this?
It should be like to this.
var app = angular.module('anApp', []);
app.controller('ctrl', function($scope) {
$scope.user = {};
$scope.accessRoles= [{"id":1,"name":"admin","accessRights":"administrative access"}];
$scope.display = function(){
console.log($scope.user);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<div ng-app="anApp" ng-controller="ctrl">
<div class="form-group">
<select ng-options="role as role.name for role in accessRoles" ng-model="user.accessRole" ng-change="display()">
</select>
</div>
</div>
use JSON.parse() to convert string to json object
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.user = {};
$scope.accessRoles= [{"id":1,"name":"admin","accessRights":"administrative access"}]
$scope.submit = function(){
console.log($scope.user)
$scope.user.accessRole = JSON.parse( $scope.user.accessRole)
console.log($scope.user)
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select ng-model="user.accessRole">
<option ng-repeat="item in accessRoles" value="{{item}}">
{{item.name}}
</option>
</select>
<button ng-click="submit()">click</button>
</div>

ng-select gives only string, but I want an integer

This is my angular html file code. In my mongo database frequencyType added as frequencyType = "1", but I want frequencyType = NumberInt(1);
<div class="span4">
<select class="span12 combobox" ng-model="frequencyType" required>
<option value="1">Daily</option>
<option value="2">Weekly</option>
<option value="3">Monthly</option>
<option value="4">Yearly</option>
</select>
</div>
I get in my database frequencyType = "1" but I want frequencyType = NumberInt(1).
There is an easier way:
Just use value*1 as your id, that will convert the string to int without changing the value... assuming the id is an integer.
so the result is>
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="selectedItem*1 as selectedItem for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
This will work in more cases, since indexOf is not available in objects, only in arrays. This solution works for objects with integers as keys (for example if some keys are missing, or if you use db ids)
Most solutions discussed here require using the ngOptions directive instead of using static <option> elements in the HTML code, as was the case in the OP's code.
Angular 1.6.x
Edit If you use Angular 1.6.x, just use the ng-value directive and it will work as expected.
angular.module('nonStringSelect', [])
.run(function($rootScope) {
$rootScope.model = { id: 2 };
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<div ng-app="nonStringSelect">
<select ng-model="model.id">
<option ng-value="0">Zero</option>
<option ng-value="1">One</option>
<option ng-value="2">Two</option>
</select>
{{ model }}
</div>
Older versions
There is a way to make it work while still using static elements. It's shown in the AngularJS select directive documentation.
The idea is to use a directive to register a parser and a formatter on the model. The parser will do the string-to-int conversion when the item is selected, while the formatter will do the int-to-string conversion when the model changes.
Code below (taken directly from the AngularJS documentation page, credit not mine).
https://code.angularjs.org/1.4.6/docs/api/ng/directive/select#binding-select-to-a-non-string-value-via-ngmodel-parsing-formatting
angular.module('nonStringSelect', [])
.run(function($rootScope) {
$rootScope.model = { id: 2 };
})
.directive('convertToNumber', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) {
return parseInt(val, 10);
});
ngModel.$formatters.push(function(val) {
return '' + val;
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="nonStringSelect">
<select ng-model="model.id" convert-to-number>
<option value="0">Zero</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
{{ model }}
</div>
I've just had the same problem and figured out the right way to do this - no 'magic' required. :)
function MyCtrl($scope) {
$scope.values = [
{name : "Daily", id : 1},
{name : "Weekly", id : 2},
{name : "Monthly", id : 3},
{name : "Yearly", id : 4}];
$scope.selectedItem = $scope.values[0].id;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="selectedItem.id as selectedItem.name for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
I think the angular way to do this is to use the directive "convert-to-number" in the select tag.
<select class="span12 combobox" ng-model="frequencyType" required convert-to-number>
<option value="1">Daily</option>
<option value="2">Weekly</option>
<option value="3">Monthly</option>
<option value="4">Yearly</option>
</select>
You can see the documentation and a fiddle here at the end of the page : https://docs.angularjs.org/api/ng/directive/select
I suggest you to try to use indexOf.
JS
function MyCtrl($scope) {
$scope.values = ["Daily","Weekly","Monthly","Yearly"];
$scope.selectedItem = 0;
}
HTML
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="values.indexOf(selectedItem) as selectedItem for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
Demo Fiddle
So send to mongoDB $scope.selectedItem value
This is the easiest way I have found so far:
function Controller($scope) {
$scope.options = {
"First option" : 1,
"Second option" : 2,
"Last option" : 10
}
$scope.myoption = 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">
<select ng-model="myoption" ng-options="label for (label, value) in options"></select>
Option Selected: {{myoption}}
</div>
Or, if you want to use numeric indexes:
function Controller($scope) {
$scope.options = {
1 : "First option",
2 : "Second option",
10 : "Last option"
}
$scope.myoption = 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">
<select ng-model="myoption" ng-options="value*1 as label for (value, label) in options"></select>
Option Selected: {{myoption}}
</div>
For Angular 2, follow the rabit...

Resources