VueJs bind boolean values to dropdown - javascript

I have a dropdown with two options: "True" and "False", when selected, I want the form to save the selected value as a boolean.
So if I check the form value when the user has selected "True", I want the value to be true as a boolean.
<select v-model="selected">
<option :value="null">Pick a value</option>
<option v-for="val in options">{{val}}</option>
</select>
...
data() {
return {
selected: null,
options: ["true", "false"]
}
Here is a fiddle of what I am attempting:
https://jsfiddle.net/q0nk9h32/5/
How can I output the selected values in their boolean form?
Bonus question: Instead of having the options variable, is it valid syntax / good practice, to do:
v-for="val in ["true", "false"]" ?
It seems overkill to have a variable for this (but it fails in fiddle when I try using an array directly). Thanks!

You can bind a value to each <option> using :value.
https://v2.vuejs.org/v2/guide/forms.html#Select-Options
new Vue({
el: '#app',
data() {
return {
selected: null
}
}
});
<script src="https://unpkg.com/vue"></script>
<div id="app">
<select v-model="selected">
<option :value="null">Pick a value</option>
<option v-for="val in [true, false]" :value="val">{{val}}!!!</option>
</select>
<p>
Selected is the {{ typeof selected }}: {{ selected }}
</p>
</div>
You can write the array for a v-for inline if you want. In your original example it wouldn't have worked because you included double quotes around your strings but were already using double quotes around the attribute.
You've got lots of options for rendering the text as True and False for these values...
If you just have two values, true and false, I'd be inclined to drop the v-for altogether and just write them separately.
<option :value="null">Pick a value</option>
<option :value="true">True</option>
<option :value="false">False</option>
Alternative ways of formatting the text would be to use a filter or method. So that's:
<option v-for="val in [true, false]" :value="val">{{ val | filter }}</option>
or
<option v-for="val in [true, false]" :value="val">{{ method(val) }}</option>
For a filter you'd define it in your component's filters section, for a method it'd be in your methods. Either way the function just needs to convert the boolean value to a string and then uppercase the first letter.
// Obviously you wouldn't call it 'method'...
method (value) {
const str = String(value);
return str.charAt(0).toUpperCase() + str.slice(1);
}
That said, given there are only two possible options, there are all sorts of other ways to do it. e.g.:
<option v-for="val in [true, false]" :value="val">{{ val ? 'True' : 'False' }}</option>

One option would be to create a computed property that just returns this.selected === 'true'.

Related

How to make a <select> tag in html only shows some data depending on another <select> tag using Vue.js

I'm displaying two <select> elements. The second <select> is disabled depending on the <option> selected on the first <select>. The problem is when I select an <option> on the first <select>, I want the data shown on the second <select> to be changed. For example, if I select District 1 on the first <select>, I want to see john and mary as options in the second <select>, but if I select District 2, I want josef and charles. Consider that I'm doing this on Laravel and using Vue.
I have done the first part using Vue, disabling the second <select> depending on what has been chosen on the first <select> (only third option on the first <select> will enable the second <select>):
https://jsfiddle.net/vowexafm/122/
Template:
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<select #change="treat">
<option value="District1">District 1</option><!--disable 2nd select-->
<option value="District2">District 2</option><!--disable 2nd select-->
<option value="District3">District 3</option><!--enable 2nd select-->
</select>
<br><br>
<select :disabled="isDisabled">
<option>cds 1</option>
<option>cds 2</option>
<option>cds 3</option>
</select>
</div>
Script:
new Vue({
el:'#app',
data: {
isDisabled: true,
},
methods: {
treat: function(e) {
if (e.target.options.selectedIndex == 0 ||
e.target.options.selectedIndex == 1) {
return this.disable();
}
if (e.target.options.selectedIndex != 0 &&
e.target.options.selectedIndex != 1) {
return this.enable();
}
},
enable: function() {
return this.isDisabled = false; // enables second select
},
disable: function() {
return this.isDisabled = true; // disables second select
}
},
});
Now the solution I want,for example: if i'I select District 1 on the first , I want to see john and mary as options in the second , but if I select District 2, I want to see josef and charles on the second .
Populate data object from laravel to have the options for the second select in it and a value for the current selected index from the first select
data: {
secondSelect: [
['john', 'mary'],
['josef', 'charles']
],
currentIndex: 0
}
Define a computed property that returns the values for the second select depending on currentIndex
computed: {
persons () {
return this.secondSelect[parseInt(this.currentIndex)]
}
}
Generate the second select using the computed property persons and use v-model to capture currentIndex.
<div id="app">
<select #change="treat" v-model="selectedIndex">
<option value="0">District 1</option><!--diable-->
<option value="1">District 2</option><!--diable-->
<option value="2">District 3</option><!--unable-->
</select>
<br><br>
<select :disabled="isDisabled">
<option v-for="option in persons" :value="option">{{option}}</option>
</select>
</div>
now the solution I want,for example if i select 'District 1 'on the
first i want to see 'john' and 'mary' as options in the second , but
if I select 'District 2' i want to see 'josef' and 'charles' on the
second .
is that whats in your mind?
new Vue({
el:'#app',
data:{
district:'-1',
options:{
'District1':false,
'District2':false,
'District3':false
},
},
methods:{
getOptions(){
axios.get('https://jsonplaceholder.typicode.com/users',{district:this.district}).then(res=>
this.options[this.district]=res.data)
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<select v-model="district" #change="getOptions()">
<option value="-1" selected disabled hidden>choose a district</option>
<option value="District1">District 1</option>
<option value="District2">District 2</option>
<option value="District3">District 3</option>
</select>
<br><br>
<select v-if="options[district]">
<option v-for="option in options[district]">{{option.name}}</option>
</select>
</div>
edit:
after your comment, i edited this answer so now its fetching the data from some api.
to fetch the options from a db, you first have to create an api for your app, and when the request comes out of your vue client side - the server will retrieve rows from the db, do some caculations based on the parameters you sent in the request, and bring back a json data array.
(i wont cover the server side now - thats completely off-topic. but you can easily google for 'laravel json response')
in this snippet, i used some example json api, just to show you how its done on the client side:
i use v-if to cause late- rendering of the second select. it will be rendered only after i get the options, via axios (a very common npm package used to make ajax requests in modern js frameworks).
im also registering an event listener to the change event of the first select - to make my ajax request and populate my options every time the disrict changes (i used a default option to avoid unneeded requests)

Angular iterate through select options and set selected value

I have a select set with States from JSON data:
<select name="ParentState" ng-model="selectedState" ng-options="s.StateID as s.StateCode for s in cStates | orderBy:'StateCode'">
<option value="">Select State...</option>
</select>
and would like to set the selected state as the state returned for the logged in user but I'm entirely sure how to accomplish this in Angular. Here's what I've tried and it isn't working.
angular.forEach($scope.cState, function (s) {
if (s.StateCode == xParentState) {
$scope.selectedState = s.StateCode;
}
});
xParent is this state initials e.g. 'MI' for Michigan
The ngModel is set to the StateID (as seen in your ngOptions - value as text for object in array) - so set that rather than StateCode
if (s.StateCode == xParentState) {
$scope.selectedState = s.StateID;
}
Check the documentation for `ngOptions.
You're using the select as label for value in array expression here. So to set the ngModel, you will need to set the StateID.
Assuming you have an object like:
xParentState: {
StateID: 1,
StateCode: 'MI',
StateName: 'Michigan'
}
Instead of iterating over the array of states, you can then set the value directly with $scope.selectedState = xParentState.StateID or you could use ngInit for setting it in the template (e.g. when the user reloads the page):
<select ng-model="selectedState" ng-options="s.StateID as s.StateCode for s in cStates | orderBy:'StateCode'" ng-init="selectedState = xParentState.StateID">
<option value="">Select State...</option>
</select>

Check how many selects have had an options selected using jQuery

I got a bunch of selects:
<select name="paraquien" class="selectpicker form-control paraquien" id="paraquien" onchange="mostrarPreguntas();">
<option value=""><?=__('¿Para quién es el plan?')?><span class="glyphicon glyphicon-triangle-bottom"></span></option>
<option value="1"><?=__('Para mi')?> <span class="glyphicon glyphicon-triangle-bottom"></span></option>
<option value="2"><?=__('Para regalar')?><span class="glyphicon glyphicon-triangle-bottom"></span></option>
</select>
and I would like to know if all of them have been selected, and in that case trigger an event. I've tried this far:
jQuery('.paraquien option:selected')
Getting this result array:
[
<option value=​"1">​Para mi ​</option>​,
<option value=​"1">​Hombre​</option>​,
<option value=​"3">​Estudiante​</option>​,
<option value>​Su situación sentimental​</option>​,
<option value>​¿Tiene hijos?​</option>
​]
You can see every option selected has a value attribute set, what I would like to know is how to get just the options which value has been already set, in the same selector mentioned before.
Any Idea?
You can use filter() to check for select elements where the value is still ''. Try this:
var $unchosenSelects = $('.paraquien').filter(function() {
return $(this).val() == '';
});
if ($unchosenSelects.length) {
// there was at least one select within nothing chosen...
}
Similarly you could use map() to get all the values in an array, then $.inArray to check for empty strings:
var chosenValues = $('.paraquien').map(function() {
return $(this).val();
});
if ($.inArray(chosenValues, '') != -1) {
// there was at least one select within nothing chosen...
}

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.

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