Strange binding/validation behaviour when binding select list to booleans - angularjs

Can anybody explain me the following strange binding/validation behaviour when binding a select list to boolean values?
Selecting "Yes" (true) works as expected. Selecting "No" (false) obviously does not:
JSFIDDLE:
http://jsfiddle.net/mhu23/ATRQG/14/
$scope.trueFalseOptions = [{
value: true,
label: 'Yes'
}, {
value: false,
label: 'No'
}];
<select name="parameter" required ng-model="myModel" ng-options="x.value as x.label for x in trueFalseOptions"></select>
Am I doing something wrong? I would like to be able to select "Yes" or "No" from a dropdown list. The values of the option items should be true or false (boolean, not string).
Thanks for your help!

It looks like the required directive does not consider a value of false to be valid and sets your model value to undefined:
Github source link:
var validator = function(value) {
if (attr.required && (isEmpty(value) || value === false)) {
ctrl.$setValidity('required', false);
return;
} else {
ctrl.$setValidity('required', true);
return value;
}
};
Here are some options:
Use ngRequired instead of required. This lets you choose a custom required expression like: ng-required="!(myModel == true || myModel == false)". Here is a fiddle with an example.
You can create your own modified required directive that will allow false
Bind to something else (1 and 0 or "true" and "false" like you mentioned)
Also note you may want to add an empty option value so the first item doesn't say "Yes" after you select it:
<select name="parameter" ng-model="myModel" ng-options="x.value as x.label for x in trueFalseOptions">
<option value=""></option>
</select>

Related

Using angularjs how can I get checked and unchecked values

Here I am binding values to ng-click as
<input type="checkbox" ng-model="a.CheckAssign"ng-click="myFunctionnew(a.ENQUIRY_CODE,a.CheckAssign)" />
enquiryArr=[]
$scope.myFunctionnew = function(enqcode,checkassign)
{
enquiryArr.push(enqcode + '&' + checkassign)
var uniqueNames = [];
$.each(enquiryArr, function (i, el) {
if ($.inArray(el, uniqueNames) === -1) {
uniqueNames.push(el);
console.log(uniqueNames)
}
else
{
console.log(uniqueNames);
}
}
Here when I check and uncheck the checkbox the value is storing multiple
Please help me how can I store Enquiry code and T/F values.
If I understand your issue correctly, you're running into duplicate entries in your enquiryArr. You're running into this because you're trying to manually keep track of the array in an odd fashion. While there are ways to correct the way you're storing it, it's even easier to have angular track what is checked and what is not.
Using the following DataSet:
$scope.enquiries = [
{ENQUIRY_CODE: 'ENQUIRY_1', ENQUIRY_NAME: 'First Enquiry', selected: false},
{ENQUIRY_CODE: 'ENQUIRY_2', ENQUIRY_NAME: 'Second Enquiry', selected: false},
{ENQUIRY_CODE: 'ENQUIRY_3', ENQUIRY_NAME: 'Third Enquiry', selected: false},
{ENQUIRY_CODE: 'ENQUIRY_4', ENQUIRY_NAME: 'Fourth Enquiry', selected: false}
];
And binding the selected field to your checkboxes ng-model
<div ng-repeat="e in enquiries">
<input type="checkbox" ng-model="e.selected" />
{{e.ENQUIRY_NAME}}
</div>
You can determine which one is checked simply by looking at the $scope.enquiries array and looking for selected: true (or false if you want to know the ones not checked).
In javascript you can use a simple Array Filter to get the selected values as such:
$scope.enquiries.filter(e => e.selected);
Or if you want to get them in your template, you can also use the filter pipe as such:
{{(enquiries | filter:{selected:true})}}
Here is an interactive plunkr that you can view this.
Misc Note: If you do want to run something when the checkbox is clicked, you can still use an ng-click and run your custom code, however, I would recommend using ng-change as there are other ways to change the selected value of a checkbox other than clicking.
I have test your code and its working fine. your problem is not so much clear so you can check following test code.
<div ng-controller="MyController">
<div ng-repeat="dt in data">
<input type="checkbox" ng-model="CheckAssign" ng-click="myFunctionnew(dt.name,dt.volume)" />
</div>
</div>
Javascript
$scope.myFunctionnew = function(enqcode,checkassign)
{
enquiryArr.push(enqcode + '&' + checkassign)
var uniqueNames = [];
for(i=0; i <enquiryArr.length; i++) {
if ($.inArray(enquiryArr[i], uniqueNames) == -1) {
uniqueNames.push(enquiryArr[i]);
console.log(uniqueNames)
}
else
{
console.log(uniqueNames);
}
}
}
JSFiddle

Migrating from angularjs select to selectize empty value

Currently I use angularjs select directive, I have a choice to reset to None value
<select ng-model="myModel" ng-options="selectOptions">
<option value="">None</option>
</select>
When I select the None option myModel is null
{{ myModel === null }} // true
I want to have the same behaviour with angularjs selectize so I am adding an option with "" value.
onInitialize: function(selectize) {
selectize.addOption({id: '', name: 'None'});
}
So when I choose none with selectize my model is an empty string and not null
{{ myModel === null }} // false
How can I change this to null ?
Is it possible to do it without writing a new directive ?
You can assign to id value null, 0 (zero) or let it undefined like this:
onInitialize: function(selectize) {
selectize.addOption({id: null, name: 'None'});
// selectize.addOption({id: 0, name: 'None'});
// selectize.addOption({name: 'None'});
}
and check it like this:
{{ !myModel }}
As an alternate solution you could just check against the '' (empty value) like this:
{{ myModel === '' }}
I have found a way by extending the plugin on
scope.$watch('ngModel', setSelectizeValue);
var setSelectizeValue = function() {
if(scope.ngModel === '') {
scope.ngModel=null;
}
Still looking for a way without extending the plugin.

How do I change the titles of the select options, but keep the values the same?

So I have an simple array values = [0, 1] and it will be supplied to
<select ng-model="myValue" ng-options="v for v in values "></select>
After this, i will have a dropdown list having two options: 0 and 1.
But what I want are:
In the web page, I don't want to show 0 or 1, but false and true.
Once a user select an option (either false or true), the real model myValue should be 0 or 1, not false or true.
How can I do this?
Flat array initialisation won't let you do this with standard ng-options as the label is the first part of the ng-options initialisation.
ng-options="label for v in values"
To do this properly, your options would be better formatted like so:
$scope.values = [
{ label : 'true', value: 1 },
{ label : 'false', value: 0 }
];
This would allow you to define the option label from the object in the for loop
<select ng-model="myValue" ng-options="v as v.label for v in values"></select>
If you want/have to stick with your current setup you could do something along the lines of:
var initialValues = [0,1];
$scope.values = [];
// Assuming ES5
initialValues.forEach(function(value, index)
{
$scope.values.push({
label : (!!value).toString(),
value : value
});
});
And modify the HTML to be as above.
According to the documentation for ngOptions, you can use an expression of the form select as label for value in array, in which label can be any correct AngularJS expression. You can use, for instance:
<select
ng-model="myValue"
ng-options="value as (value ? 'true' : 'false') for value in values"
></select>
Fiddle
This can be acceptable when you have just a few number of possible values, but it becomes quickly unreadable if your array grows larger:
<select
ng-model="myValue"
ng-options="value as (value === 1 ? 'true' : value === 0 ? 'false' : value === -1 ? 'undefined') for value in values"
></select>
In such a case, I strongly advise you to use an object, as suggested by David Barker.

AngularJS, Dropdpown set given boolean value as predefined text

I have predefined scope values:
$scope.synchronizationStates =
[
true,
false
];
And i have defined select:
<select class="form-control" data-ng-model="projectDetail.synced" data-ng-options="synced for synchronizationState in projectDetail.synchronized">
</select>
I would like to have for state false display preselected value "NOT_SYNCED" and for true "SYNCED" And also change state value if value is changed by user.
How can I do it please using AngularJs?
Thanks for any advice.
In controller use :
$scope.synchronizationStates = [
{text:'not synced',value:false},
{text:'synced',value:true},
]
and in html
<select ng-model="selected" ng-options="value.value as value.text for value in synchronizationStates"></select>
working plunker here a link!
I think its better for you to use something like this
ng-options="e as e for e in synchronizationStates "></select>
and maybe make each element in the array an object with string for the name and true or false for the value

Setting default value in select drop-down using Angularjs

I have an object as below. I have to display this as a drop-down:
var list = [{id:4,name:"abc"},{id:600,name:"def"},{id:200,name:"xyz"}]
In my controller I have a variable that carries a value. This value decided which of the above three items in the array will be selected by default in the drop-down:
$scope.object.setDefault = 600;
When I create a drop-down form item as below:
<select ng-model="object.setDefault" ng-options="r.name for r in list">
I face two problems:
the list is generated as
<option value="0">abc</option>
<option value="1">def</option>
<option value="2">xyz</option>
instead of
<option value="4">abc</option>
<option value="600">def</option>
<option value="200">xyz</option>
No option gets selected by default even though i have ng-model="object.setDefault"
Problem 1:
The generated HTML you're getting is normal. Apparently it's a feature of Angular to be able to use any kind of object as value for a select. Angular does the mapping between the HTML option-value and the value in the ng-model.
Also see Umur's comment in this question: How do I set the value property in AngularJS' ng-options?
Problem 2:
Make sure you're using the following ng-options:
<select ng-model="object.item" ng-options="item.id as item.name for item in list" />
And put this in your controller to select a default value:
object.item = 4
When you use ng-options to populate a select list, it uses the entire object as the selected value, not just the single value you see in the select list. So in your case, you'd need to set
$scope.object.setDefault = {
id:600,
name:"def"
};
or
$scope.object.setDefault = $scope.selectItems[1];
I also recommend just outputting the value of $scope.object.setDefault in your template to see what I'm talking about getting selected.
<pre>{{object.setDefault}}</pre>
In View
<select ng-model="boxmodel"><option ng-repeat="lst in list" value="{{lst.id}}">{{lst.name}}</option></select>
JS:
In side controller
$scope.boxModel = 600;
You can do it with following code(track by),
<select ng-model="modelName" ng-options="data.name for data in list track by data.id" ></select>
This is an old question and you might have got the answer already.
My plnkr explains on my approach to accomplish selecting a default dropdown value. Basically, I have a service which would return the dropdown values [hard coded to test]. I was not able to select the value by default and almost spend a day and finally figured out that I should have set $scope.proofGroupId = "47"; instead of $scope.proofGroupId = 47; in the script.js file. It was my bad and I did not notice that I was setting an integer 47 instead of the string "47". I retained the plnkr as it is just in case if some one would like to see. Hopefully, this would help some one.
<select ng-init="somethingHere = options[0]" ng-model="somethingHere" ng-options="option.name for option in options"></select>
This would get you desired result Dude :) Cheers
Some of the scenarios, object.item would not be loaded or will be undefined.
Use ng-init
<select ng-init="object.item=2" ng-model="object.item"
ng-options="item.id as item.name for item in list"
$scope.item = {
"id": "3",
"name": "ALL",
};
$scope.CategoryLst = [
{ id: '1', name: 'MD' },
{ id: '2', name: 'CRNA' },
{ id: '3', name: 'ALL' }];
<select ng-model="item.id" ng-selected="3" ng-options="i.id as i.name for i in CategoryLst"></select>
we should use name value pair binding values into dropdown.see the
code for more details
function myCtrl($scope) {
$scope.statusTaskList = [
{ name: 'Open', value: '1' },
{ name: 'In Progress', value: '2' },
{ name: 'Complete', value: '3' },
{ name: 'Deleted', value: '4' },
];
$scope.atcStatusTasks = $scope.statusTaskList[0]; // 0 -> Open
}
<select ng-model="atcStatusTasks" ng-options="s.name for s in statusTaskList"></select>
I could help you out with the html:
<option value="">abc</option>
instead of
<option value="4">abc</option>
to set abc as the default value.

Resources