AngularJS not binding to numeric value in select list - javascript

I have an existing select tag with existing option tags, one marked "selected", for example:
<div class="form-group">
<label class="control-label">Test</label>
<select ng-model="vm.testNumber">
<option>Choose...</option>
<option value="1">one</option>
<option value="2">two</option>
<option value="3" selected>three</option>
</select>
<p class="help-block">{{vm.testNumber}}</p>
</div>
Angular is binding to the model correctly and spits out "3" in the help block when the page loads, but option 3 is not selected. It binds and shows 3 as selected if I use text for the value attributes on each option, but not when it's a numerical value. Instead it inserts an option at the top of the select list:
<option value="? number:3 ?"></option>
What am I doing wrong?

From Angular DOC
Note that the value of a select directive used without ngOptions is always a string. When the model needs to be bound to a non-string value, you must either explicitly convert it or use ngOptions to specify the set of options. This is because an option element can only be bound to string values at present.
If you change your code as like as below code snippet, you don't need to do any explicit string conversions.
<select ng-model="vm.testNumber" ng-options="item.value as item.label for item in [{label: 'one', value: 1}, {label: 'two', value: 2}]">
<option value="">Choose...</option>
</select>

Turns out you need to add a directive to make this work correctly. #codeninja.sj's answer ends up replacing 'one' with 1, 'two' with 2, etc. In the documention, the last example has this directive, convert-to-number
angular.module('app').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;
});
}
};
});
None of the other examples in the documentation worked for me.
Update #codeninja.sj's updated answer does work, however, figure this directive will cut down on magic strings in my code.

Related

Bind options value to ng-model in angularjs

I'm working on a project, and I need to bind the options value to object key's in such a manner that, on selecting an option, it gives 1, else other variables remain 0.
My HTML Code:-
<select required class="custom-select">
<option disabled>Select an option</option>
<option ng-model="PredictCtrl.detail.building_type_AP">Apartment</option>
<option ng-model="PredictCtrl.detail.building_type_GC">Independent House / Villa</option>
<option ng-model="PredictCtrl.detail.building_type_IF">Independent Floor / Builder's Floor</option>
<option ng-model="PredictCtrl.detail.building_type_IH">Gated Community Villa</option>
</select>
Variable to bind -
PredictCtrl.detail = {
building_type_AP: 0,
building_type_GC: 0,
building_type_IF: 0,
building_type_IH: 0
}
Generally, binding is done with select tag, which gives the value of the selected option, but I want in such a way that, when I click on Apartment option, it's bind variable PredictCtrl.detail.building_type_AP becomes 1, rest remains 0. Similarly, it does with other options.
I want to send the data as the same format through API.
So, please Help me out.
Sorry If I was not very clear with explaining or for any typo.
Thank you in advance.
You should take a look at the NgOptions directive which is the "angularjs" way of working with the select-tag.
It sould be able to fulfill your requirement as you will get the selected option in the SelectedOption object.
Here's an example
angular.module("app",[]).controller("myCtrl",function($scope){
$scope.details =
[
{name:"Apartment", value:1},
{name:"Independent House / Villa", value:2},
{name:"Independent Floor / Builder's Floor", value:3},
{name:"Gated Community Villa", value:4}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<select required class="custom-select" ng-options="item as item.name for item in details" ng-model="selectedOption">
</select>
<p>SelectedOption: {{selectedOption}}</p>
</div>
None of the answers at my time of writing actually present a functioning solution, so here's one.
Don't scatter ng-model directives across different option elements, it's unnecessary.
You can achieve what you want by using ng-options to enumerate all your choices, a single ng-model to keep track of the selected option, and ng-change to apply the values as you described (i.e. 1 on the selected key, 0 for everything else).
I've assumed you've got a requirement to keep the structure of detail as is. If it can be changed, then I'd recommend associating each labels with each it's respective building_type_ to keep things together.
See below.
angular
.module('app', [])
.controller('PredictCtrl', function () {
this.selectedDetail = null;
this.detail = {
building_type_AP: 0,
building_type_GC: 0,
building_type_IF: 0,
building_type_IH: 0,
};
this.labels = {
building_type_AP: 'Apartment',
building_type_GC: 'Independent House / Villa',
building_type_IF: 'Independent Floor / Builder\'s Floor',
building_type_IH: 'Gated Community Villa',
};
this.changeDetail = function () {
for (var key in this.detail) {
this.detail[key] = +(this.selectedDetail === key);
}
};
});
<script src="https://unpkg.com/angular#1.7.4/angular.min.js"></script>
<div ng-app="app" ng-controller="PredictCtrl as PredictCtrl">
<select
ng-model="PredictCtrl.selectedDetail"
ng-options="key as PredictCtrl.labels[key] for (key, value) in PredictCtrl.detail"
ng-change="PredictCtrl.changeDetail()"></select>
<pre>{{ PredictCtrl.detail | json }}</pre>
</div>
try like this:
in your controller:
$scope.details = [
{
name: "building_type_AP",
value: "Apartment",
state: false
},{
name: "building_type_GC",
value: "Independent House / Villa",
state: false
}/*add more here*/
];
$scope.setActive = function(detail){
detail.state = !detail.state;
}
in html template:
<select required class="custom-select">
<option disabled>Select an option</option>
<option ng-repeat="detail in details" ng-click="setActive(detail)">{{detail.value}}</option>
</select>
in the end just go through $scope.details and parse false to 0 and true to 1 OR just do this inside setActive function

AngularJS case-insensitive binding to a dynamic select dropdown without changing the ng-bind value to lower or upper case

I am trying to perform a case-insensitive bind of an ng-model to a dynamic select drop-down using AngularJS.
by going through various other relavent answers from stack over flow, i have come up with something like below on the view , here caseinsensitive-options is an directive which i have come up with referencing the following solution
AngularJS case-insensitive binding to a static select drop-down
HTML:
<select id="dcName" caseinsensitive-options="" ng-model="DC.name" class="form-control">
<option value="">--- Please Select ---</option>
<option ng-repeat="dataCenter in inventoryDataCenters" value="{{dataCenter}}">{{dataCenter}}</option>
</select>
js directive code :
app.directive('caseinsensitiveOptions', function() {
return {
restrict: 'A',
require: ['ngModel', 'select'],
link: function(scope, el, attrs, ctrls) {
var ngModel = ctrls[0];
ngModel.$formatters.push(function(value) {
var option = [].filter.call(el.children(), function(option) {
return option.value.toUpperCase() === value.toUpperCase()
})[0];
return option ? option.value : value
});
}
}
});
The expected result is
when i pass something like this for
$scope.inventoryDataCenters = ["TEST1","test2",teST3]; and ng-model for DC.name has value TesT1.
The drop down should show TEST1 by doing case insensitive binding. That doesnt happen now. The above solution works perfect when we have static drop down.
things to be considered is that the select is inside a div which ng-repeat as shown below
ng-repeat="DC in workflowData.project_data.service_info.variables.service_data['data-center']"
and ng-model for select DC.name is derived from the above array DC.
check this URL for binding based on case insensitive value
https://jsfiddle.net/dwd2du17/6/
<div ng-app="module" ng-controller="controller as ctrl">
<select id="animal" ng-model="ctrl.animal">
<option value="">--- Select ---</option>
<option value="CaT">Cat</option>
<option value="DOg">Dog</option>
</select>
{{ctrl.animal}}
</div>
var appForm = angular.module('module', [])
.controller('controller', function($scope) {
});

AngularJS null value for select

I couldn't find an elegant way for setting null values with a <select> using AngularJS.
HTML :
<select ng-model="obj.selected">
<option value=null>Unknown</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
{{obj}}
JS :
$scope.obj ={"selected":null};
When the page is loaded, the first option is selected, which is good, and the output is {"selected":null}. When that first option is reselected after having switch to another one, the output becomes {"selected":"null"} (with the quotes), which is not what I would expect.
Running example :
http://plnkr.co/edit/WuJrBBGuHGqbKq6yL4La
I know that the markup <option value=null> is not correct. I also tried with <option value=""> but it corresponds to an empty String and not to null : the first option is therefore not selected and another option which disappears after the first selection is selected by default.
Any idea ?
This should work for you:
Controller:
function MyCntrl($scope) {
$scope.obj ={"selected":null};
$scope.objects = [{id: 1, value: "Yes"}, {id: 0, value: "No"}]
}
Template:
<div ng-controller="MyCntrl">
<select ng-model="obj.selected"
ng-options="value.id as value.value for value in objects">
<option value="">Unknown</option>
</select>
<br/>
{{obj}}
</div>
Working plnkr
You should use ng-options with select.
You can use the ngOptions directive on the select. According to the documentation:
Optionally, a single hard-coded <option> element, with the value set to an empty string, can be nested into the <select> element. This element will then represent the null or "not selected" option. See example below for demonstration.
<select ng-model="obj.selected" ng-options="key as label for (key, label) in ['No', 'Yes']">
<option value="">Unknown</option>
</select>
It's obviously a better idea to define the options list directly in the controller.
Try using ng-options instead of manually creating tags, as in this example, lightly-edited from the Angular docs:
http://plnkr.co/edit/DVXwlFR6MfcfYPNHScO5?p=preview
The operative parts here are lines 17, defining a 'colors' object, and the ng-options attributes iterating over those colors to create options.
If you REALLY want to use null, see below. You need to use ng-options and let Angular handle the mapping:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Color selector</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.8/angular.min.js"></script>
</head>
<body ng-app="">
<script>
function MyCntrl($scope) {
$scope.obj ={"selected":null};
$scope.objStates = [{key:"Unknown", value:null}, {key:"Yes", value:1}, {key:"No", value:0}]
$scope.$watch('obj.selected', function(newVal){
console.log(newVal);
})
}
</script>
<div ng-controller="MyCntrl">
<select ng-model="obj.selected" ng-options="state.value as state.key for state in objStates">
</select>
<br/>
{{obj}}
</div>
</body>
</html>
I ran into the same Problem but could not solve it via 'ng-options'. My solution is:
module.directive('modelToNull', [function () {
return {
scope: {
check: "&modelToNull"
},
require: 'ngModel',
link: function ($scope, element, attrs, ngModelController) {
ngModelController.$parsers.push(function (value) {
return value == null || $scope.check({value: value}) ? null : value;
});
}
};
}]);
You can use it like this:
<select ng-model="obj.selected" model-to-null="value == 'null'">
<option value="null">Unknown</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
Can you try to use parseInt on the value? For example, both "1" and "0" will equal their respective integer values. If you run the empty string through parseInt you can easily get NaN.
> parseInt("") = NaN
> parseInt("0") === 0
> parseInt("1") === 1
Without the possibility of using ng-options I present another fix.
I've been battling this a couple of months now, using solutions presented on this question and I don't know how nobody posted this:
<option value="null"></option>
This should work on Angular 1.6 and above for sure when you are using ng-repeat for options instead of ng-options.
It's not ideal but since we are used to work on legacy code this simple fix could save your day.
the only way you can achieve that is by using a onchange event and restoring the object as initialized any other attempt to set the selected to null will remove the property from the object.
$scope.setValue=function(val){
if($scope.obj.selected=="null")
$scope.obj ={"selected":null};
}
<select ng-change="setValue()" ng-model="obj.selected">
<option value=null ng-click="obj.selected=null">Unknown</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
this is a bad idea, you should always have values in your model instead of playing around with null and undefined
This is much easier on Angular2/Angular where you can just use
<option [value]="null">Unknown</option>
This value is no longer a string, but a real null value.

How to bind a (basic) Kendo DropDownList made from a select element, with data in option elements, to a javascript object using Kendo MVVM?

I can't seem to work out, or see examples any where in the doco or on the web for how to do this.
I have a simple select element that I have marked up to be a Kendo DropDownList.
HTML:
<div id="View">
<select
id="DropDownList"
data-role="dropdownlist"
data-value-primitive="true"
data-bind="value: OptionID">
<option value="1">Option One</option>
<option value="2">Option Two</option>
<option value="3">Option Three</option>
</select>
</div>
JavaScript:
$(document).ready(function() {
var oDataSource = {
OptionID: -1
};
// MVVM Bind View to Record
kendo.bind($('#View'), oDataSource);
// Log OptionID set in oDataSource by DropDownListing Binding
$('#DropDownList').data('kendoDropDownList').bind('select', function (e) {
console.log('Selected Option: ' + oDataSource.OptionID);
});
});
The console.log of the oDataSource.OptionID shows -1 every time.
I have created a fiddle here that demonstrates the code above: http://jsfiddle.net/codeowl/CDrFS/3/
What am I doing wrong?
Regards,
Scott
Two questions:
You should define oDataSource as an ObservableObject otherwise your variable is not bound to DropDownList.
You need to use change handler instead since select is triggered when the option is selected but the input is not changed yet.
So your code should be:
var oDataSource = kendo.observable({
OptionID: -1
});
// MVVM Bind View to Record
kendo.bind($('#View'), oDataSource);
// Log OptionID set in oDataSource by DropDownListing Binding
$('#DropDownList').data('kendoDropDownList').bind('change', function (e) {
console.log('Selected Option: ' + oDataSource.OptionID);
});
See you JSFiddle modified here : http://jsfiddle.net/OnaBai/CDrFS/4/

Angular, boolean value in a select box

I want to set a boolean value to true or false using a select here is my code:
<select class="span9" ng-model="proposal.formalStoryboard">
<option value="false">Not Included</option>
<option value="true">Included</option>
</select>
The value (proposal.formalStoryboard) is set properly to true or false but the change are not reflected on the select box when the value is already assigned.
I tried ng-value="true" and ng-value="false" instead of just value but it's not working as well.
EDIT: Commentors have pointed out that my original solution did not work as claimed. I have updated the answer to reflect the correct answer given by others below (I cannot delete an accepted answer).
For Angular 1.0.6, consider this HTML:
<div ng-app="">
<div ng-controller="MyCntrl">
<select ng-model="mybool"
ng-options="o.v as o.n for o in [{ n: 'Not included', v: false }, { n: 'Included', v: true }]">
</select>
<p>
Currently selected: <b>{{ mybool }}</b> opposite: {{ !mybool }}
</p>
</div>
</div>
And this JavaScript:
function MyCntrl($scope) {
$scope.mybool = true;
}
Here is a working DEMO for Angular 1.0.6 and here is a working DEMO for Angular 1.3.14, which is slightly different.
Just do like this:
<select ng-model="someModel" ng-options="boolToStr(item) for item in [true, false]">
</select>
and define:
$scope.boolToStr = function(arg) {return arg ? 'Included' : 'Not included'};
Why not just use this?
<select class="form-control" ng-options="(item?'Included':'Not Included') for item in [true, false]"></select>
If you are using angularjs version >= 1.2.0 you will have access to the directive ng-value
You can use the ng-value on an option element. Your htmls would work like this.
<select ng-model="proposal.formalStoryboard">
<option ng-value="true">Included</option>
<option ng-value="false">Not Included</option>
</select>
It also works on radio and checkboxes.
I would recommend using a directive for this. As usual, I try to stay away from timeouts and other async operations in preference of a more authoritative and direct control.
directives.directive('boolean', function() {
return {
priority: '50',
require: 'ngModel',
link: function(_, __, ___, ngModel) {
ngModel.$parsers.push(function(value) {
return value == 'true' || value == true;
});
ngModel.$formatters.push(function(value) {
return value && value != 'false' ? 'true' : 'false';
});
}
};
});
The priority is set specifically so that it is done prior to any other directives (that usually don't have a priority set, and defaults to 0)
For example, I use this directive (for a true/false selection) with my selectpicker directive that wraps my select elements in the selectpicker bootstrap plugin.
Edit:
The caveat here, which I forgot to mention, is that your html values need to be string values. What the directive does is translates between the view and the model, keeping the model value in boolean and your view in string format:
%select.selectpicker{ ng: { model: 'modelForm.listed' }, selectpicker: '{ }', boolean: true }
%option{ value: 'true' } Listed
%option{ value: 'false' } Unlisted
This will work too. Just force the value to be boolean by putting an angular expression in for the value.
<select class="span9" ng-model="proposal.formalStoryboard">
<option value="{{false}}"
ng-selected="proposal.formalStoryboard === false">
Not Included
</option>
<option value="{{true}}"
ng-selected="proposal.formalStoryboard === true">
Included
</option>
</select>
I created sample for you, please check this out.
Is it what you want to use model to drive the ui binding?
<div ng-app ng-controller="Ctrl">
<select class="span9" ng-model="proposal.formalStoryboard">
<option value="false">Not Included</option>
<option value="true">Included</option>
</select>
<button ng-click="changeValue();">Click</button>
<div>
function Ctrl($scope) {
$scope.proposal = {};
$scope.proposal.formalStoryboard = true;
$scope.changeValue = function () {
$scope.proposal.formalStoryboard = !$scope.proposal.formalStoryboard;
console.log($scope.proposal.formalStoryboard);
}
}
I had very little success with this frustrating issue. My solution, while not too elegant since it's an additional line of code, solved it every time. This may not work in every application.
$scope.myObject.myBooleanProperty = $scope.myObject.myBooleanProperty.toString();
Turning it into a "real" string before trying to rebind it to the model displayed on the page allowed it to correctly select the value.
Angular does a strict comparsion between the Value bind to ng-model and the Values in the given Options. The Values given in the initial Question are the Strings "false" and "true".
If the Value of ng-model is of Type bool and defined like {"Value":false}, Angulars strict === comparsion between string and bool does never match so the select-box is empty.
The real Problem is- if you select a Value, the Type changed from bool to string ({"Value":false} --> {"Value":"false"})can cause errors if posted back.
The best Solution for both issues for me was the one of Thiago Passos in this Post.
(https://stackoverflow.com/a/31636437/6319374)
<script type='text/javascript'>
function MyCntrl($scope) {<!--from ww w . j a v a 2s. c om-->
$scope.mybool = true;
}
</script>
</head>
<body>
<div ng-app="">
<div ng-controller="MyCntrl">
<select ng-model="mybool">
<option value="false">Not Included</option>
<option value="true">Included</option>
</select>
<p>
Currently selected: {{ mybool }}
</p>
</div>
</div>
</body>
</html>

Categories

Resources