Angular 5 - Disabling Radio Buttons - forms

I have a radio button group in Angular 5. I want to disable some options, using the [disabled] attribute. However, I am noticing only the first radio button actually gets disabled. See my plunker: http://plnkr.co/edit/JzFmvjUyvhPdTkbYT1YZ?p=preview
Even if I hard code [disabled]="true", it still doesn't disable the second radio button. I don't want to switch to using a <select>, so I am curious if there is another way to get this to work with radio buttons.

There can be 2 solutions for this :-
1. Using the disabled attribute ([attr.disabled])
One solution to this problem can be using the disabled attribute ([attr.disabled]) instead of the disabled property ([disabled]), but [attr.disabled] works slightly differently, to enable the radio button you need to pass null to [attr.disabled] and any non-null value to disable it. Consider the below example :-
<input type="radio" name="enabled" [attr.disabled]="null" />Enabled1
<input type="radio" name="enabled" [attr.disabled]="null" />Enabled2
<input type="radio" name="disabled" [attr.disabled]="false" />Disabled1
<input type="radio" name="disabled" [attr.disabled]="false" />Disabled2
In this example the set of radio buttons named "enabled" will be enabled since for them [attr.disabled] is set to null, whereas the set of radio buttons named "disabled" will be disabled despite the [attr.disabled] being set to "false" this is because false is a non-null value.
2. Using fieldset tag
Another even better solution for this problem is using the <fieldset> tag for grouping the radio buttons together and then setting the [disabled] property on that <fieldset> tag instead of individual radio buttons. Below is an example for the same :-
<fieldset [disabled]=true>
<input type="radio" name="test" />yes
<input type="radio" name="test" />no
</fieldset>

Use this : (for reactive form approach)
<input
type="radio"
id="primaryIPV6"
value="2"
[attr.disabled]="flagValue ? '' : null"
formControlName="p_ip_type"
(change)="optionalFn()">
Set flagValue programmatically from .ts class:
use -> null : false (null would be interpreted as false )
use -> true/'' : true (true or simply blank would be interpreted as true)

One way to deal with the problem is to place the disabled binding on the last radio button in the group. Here is a modified version of your code: http://plnkr.co/edit/v6S5G7Do5NAMKzZvNdcd?p=preview
<input type="radio" name="answer" value="Yes" [(ngModel)]="name" /> Yes
<input type="radio" name="answer" value="No" [(ngModel)]="name" [disabled]="isDisabled()" /> No
There is a bug and a design problem in disabling (using [disabled]) Angular template driven radio buttons.
I fixed the bug in this pull request: https://github.com/angular/angular/pull/20310
The design problem is that we put the [disabled] binding on a single radio button, but it's all the group that is affected by the data binding. Here is a modified version of your code that illustrate the problem: http://plnkr.co/edit/3yRCSPsdjXqhUuU9QEnc?p=preview

It works fine like this [attr.disabled]="isDisabledState === true"
And in the component class you can have isDisabledState: boolean = true

I ended up cheating. Instead of using the same name for both radio buttons, I gave each radio button a unique name and bound them to the same backing field. http://plnkr.co/edit/zNbODcAqZMgjXfluxhW6?p=preview
#Component({
selector: 'my-app',
template: `
<form>
Hello {{name}}!!!
<input type="radio" name="answer1" value="Yes" [(ngModel)]="name" [disabled]="isDisabled1()" /> Yes
<input type="radio" name="answer2" value="No" [(ngModel)]="name" [disabled]="isDisabled2()" /> No
</form>
`,
})
export class App {
name:string;
isDisabled1(): boolean {
return false;
},
isDisabled2(): boolean {
return false;
}
}
Since they are both bound to the same backing field, they end up being mutually exclusive, behaving the way radio buttons should. It also allows them to be independently disabled.
In my real-world scenario, I actually only did one-way binding with (click) events to set the bound value, but it's the same trick.

I was working with ionic and the following works for me.
<ion-radio class="fix-radio_button" *ngIf="!IsSuspended" color="default" [disabled]="q.QuestionOptionId==q.AnswerId" [checked]="q.QuestionOptionId==q.AnswerId"></ion-radio>

Considering DrNio answer you should use attr.disabled and set value as [value]="'Yes'". This is because assigning as "Yes" makes angular to evaluate it as an expression instead of just a value.So your input element would be :
<input type="radio" name="answer" [value]="'Yes'" [(ngModel)]="name" [attr.disabled]="isDisabled()" />

Here is your updated running code and punker..
Update Plunker
#Component({
selector: 'my-app',
template: `
<form>
Hello {{name}}!!!
<input type="checkbox" name="dus" [(ngModel)]="isDisabled">
<input type="radio" name="answer" value="Yes" [(ngModel)]="name" [disabled]="isDisabled" /> Yes
<input type="radio" name="answer" value="NO" [(ngModel)]="name" [disabled]="isDisabled" /> No
</form>
`,
})
export class App {
name = 'Yes';;
isDisabled = true;
}

If you want to disable a specific radio button of angular material which is in a loop, you can do this based on specific condition. This can be done like this, using the disabled attribute of the radio group:
In HTML:
<mat-radio-group>
<mat-radio-button value="1"
[disabled]="name === 'welcome' ? false : true"
*ngFor="let name of names;">
{{ name }}
</mat-radio-button>
</mat-radio-group>
In .ts file:
public names = [
'welcome',
'computer',
'keyboard'
]

Related

How to avoid some required fields to be checked depending by a radio button

Maybe is better to explain with an example.
I have a form with a radio button with YES/NO items.
When a user select NO the fields below the radio button are disabled, while when he click on YES, the fields are enabled.
<form id="myForm">
<h3>Test Form</h3>
<input type="radio" name="radiobutton" id="needabikesino0" onclick="enableDisableAll();" /> Yes
<input type="radio" name="radiobutton" id="needabikesino1" onclick="enableDisableAll();" /> No
<p><input type="text" id="numerobiciclette" name="mybikes" placeholder="bike numbers" disabled /></p>
<p><input type="text" id="altezza" name="myheight" placeholder="my height" disabled /></p>
<p><input type="text" id="numerocaschi" name="myhelmets" placeholder="my helmets" disabled /></p>
</form>
function enableDisableAll() {
cb1 = document.getElementById('needabikesino0').checked;
document.getElementById('numerobiciclette').disabled = !cb1;
document.getElementById('altezza').disabled = !cb1;
document.getElementById('numerocaschi').disabled = !cb1;
}
See here: http://jsfiddle.net/dforce/0u13z7md/
The PROBLEM is:
When the user choose NO on the radio button, is not possible to send the form because the fields are compulsory.
I need the form to be sent even when the user choose NO.
How can I solve this issue?
Thanks for your help!
You could try making the field readOnly?
http://www.w3schools.com/jsref/prop_text_readonly.asp

Foundation 5 & Abide: a custom validator for a set of checkboxes?

I would like to create a validator for abide for a set of checkboxes.
Let's consider a set of 5 checkboxes. The user is asked to check 3 max, and at least 1.
So, here is my work-in-progress code:
<div data-abide-validator='checkboxes' data-abide-validator-values='1,3'>
<input type="checkbox"/>
<input type="checkbox"/>
<input type="checkbox"/>
<input type="checkbox"/>
<input type="checkbox"/>
</div>
<script>
$(document).foundation({
validators: {
checkboxes: function(el, required, parent) {
var countC = el.find(':checked').length;
alert(countC);
}
}
});
</script>
At this point, I just try to count the checked inputs. But it seems I can't even trigger the validator... I think I could manage to code my validation stuff if only I could figure out how to trigger it.
Indeed I didn't find many examples of the custom validator, and the official doc did not help me much.
Your HTML markup is not really "correct" for abide. You should be attaching the data-abide-validator attribute to the inputs, not the parent div. Additionally, you need some better markup so abide's default error display can work (and some better use of foundation's grid system to lay it out). I would point you toward the Abide Validation Page on Zurb's site for some examples of form markup.
I've taken the liberty of restructuring your markup to be something that is more becoming of a foundation layout:
<form action="/echo/html/" method="POST" data-abide>
<div class="row">
<div class="small-12 columns checkbox-group" data-abide-validator-limit="1,3">
<label>Check some boxes</label>
<small class="error">You have checked an invalid number of boxes.</small>
<ul class="small-block-grid-3">
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="1" /> 1
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="2" /> 2
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="3" /> 3
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="4" /> 4
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="5" /> 5
</label>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<button type="submit">Submit</button>
</div>
</div>
</form>
As to your JS code. It's not correct either. You need to address the abide -> validators namespace of the options, not just validators. I've rewritten your JS code to not only do that, but give the desired effect you wanted:
$(document).foundation({
abide: {
validators: {
checkbox_limit: function(el, required, parent) {
var group = parent.closest( '.checkbox-group' );
var limit = group.attr('data-abide-validator-limit').split(',');
var countC = group.find(':checked').length;
if( countC >= limit[0] && countC <= limit[1] ) {
group.find('small.error').hide();
//return true so abide can clear any invalid flags on this element
return true;
} else {
group.find('small.error').css({display:'block'});
//return false and let abide do its thing to make sure the form doesn't submit
return false;
}
}
}
}
});
In order to check adjacent elements when doing custom validation, you need to have something to target. The el variable in the validation function will be the DOM element of the input/field that is being validated. The required variable will tell you if the field is flagged as being required or not (boolean). The parent variable will be set to the "parent" of the field. I say "parent" because although the label tag is technically the parent of the input element, abide is smart enough to realize that the label is part of the field's element structure and skip over it to the li element instead.
From there, you need a way to identify a common parent. So I added the checkbox-group class to whatever element I decided to make the "parent" of all the checkboxes in the group. This is not a Foundation or Abide "magic" class, but rather something of my own creation for use in the validation function.
From there, you can easily trace the few lines of the validation function to see the workflow: Find the group container object, parse the limits off the container's data-abide-validator-limits attribute, count the number of checked inputs in the container, check if the number checked is between the limits, display/hide the error message and return true/false so abide knows if the field validated or not.
I've got a working Fiddle of it if you care to check it out yourself ;) Hopefully this was informative for you, and I wish you the best of luck playing with the awesome that is Foundation!

Radio button policy

Do radio buttons have policy of setting default value? I want to create form where are radio buttons and it is required value. What is better to select one on show form or show all and put error message(if any radio button, not selected on submit)?
You can select a default radio value by using checked
<input type=radio name=r1 value="1" checked>
<input type=radio name=r1 value="2">
Here default value is set to 1, v should use checked keyword.
It is better to set default radio button option.
Suppose if u dont want to use default radio button selection You can call a js function(using onsubmit()). Like this
<form id="ID" method="post" action="servleName" onSubmit="return validateOption()">
<input type=radio name=r1 value="1" >A</input>
<input type=radio name=r1 value="2">B</input>
<input type="submit" value="Submit"><span id="error" style="display:none;"></span>
</form>
Your script goes here to validate whether option selected or not,Submission of page is possible only if onsubmit=true ie if validateOption() returns true.
<script>
function validateOption()
{
var group=document.getElementsByName("r1");
for ( var i = 0; i < group.length; i++)
{
if (group[i].checked)
return true;
}
// else you can show error message like this
document.getElementById("error").innerHTML="Please enter your choice";
return false;
}
</script>

Adding an extra relative value to an input value field

I'm currently creating a form that is very similar to the following code.
<form name="test" action="/go/test" method="post">
<input type=hidden name="hotspot_url" value="http://www.test.com/">
<input name="cky" value="<%write(cky);%>" type="hidden">
<input name="accept" value="Accept" type="hidden">
<input name="saccept" size="20" value="I Accept" onClick="hotspot.accept.value='Accept'" type="submit">
<input name="sdisconnect" size="20" value="I Decline" onClick="hotspot.accept.value='Decline'" type="submit">
</form>
However, the new form has a text input field. What I want to achieve is that the value entered in that text field is placed, upon send, after the test.com value (location marked with xxx)
<input type=hidden name="hotspot_url" value="http://www.test.com/xxx">
I've looked around - but i can't seem to find a solution.
What would be the best way to get this done?
You can use a buttons onclick event, which is not of type submit. When onclick occurs, you can first change the value of hidden field and then submit the form.
Or if you use JQuery, you can use the following jQuery code to do something before the form is submitted:
$(function() {
$('#form').submit(function() {
// DO STUFF
return true; // return false to cancel form action
});
});
You can give both inputs an id, and do something like this:
give the form an "onsumbit= doThis()"
function doThis(){
var hiddeninput= $('#hiddeninput').val();
var input = $('#input').val();
$('#hiddeninput').val(hiddeninput+input);
return true;
}
this is very simple nothing fancy.

Example of jQuery Mobile site with conditional/branching questions

I'm trying to create a JQM survey with branching questions--i.e. in a survey with questions 1-3, if you choose a particular answer on question 1, a question is dynamically added between questions 1 and 2.
UPDATE: I made an attempt ( https://dl.dropbox.com/u/17841063/site2/index-c1.html#page2 ) that works by matching the value of a radio button to the name of a hidden div--if there's a match, it unhides the div. The problem right now is that if you change your answer back to an option that wouldn't trigger the conditional question, it doesn't re-hide. For example, clicking No or Unsure in question A1 causes question A2 to appear, but if you then click Yes in A1, A2 still remains...
<script type="text/javascript">
// Place in this array the ID of the element you want to hide
var hide=['A2','A4'];
function setOpt()
{
resetOpt(); // Call the resetOpt function. Hide some elements in the "hide" array.
for(var i=0,sel=document.getElementsByTagName('input');i<sel.length;i++)
{
sel[i].onchange=function()
{
if(this.parentNode.tagName.toLowerCase()!='div')
resetOpt(); // Hides the elements in "hide" array when the first select element is choosen
try
{
document.getElementById(this.value).style.display='';
}
catch(e){} ; // When the value of the element is not an element ID
}
}
}
window.addEventListener?window.addEventListener('load',setOpt,false):
window.attachEvent('onload',setOpt);
function resetOpt()
{
for(var i=0;i<hide.length;i++)
document.getElementById(hide[i]).style.display='none'; // Hide the elements in "hide" array
}
</script>
Here's are the radio buttons that use the script above:
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>(Question A1) A prominent accident smokes on top of the blessed reactionary?</legend>
<input type="radio" name="aaa" id="aaa_0" value="notA2" />
<label for="aaa_0">Yes</label>
<input type="radio" name="aaa" id="aaa_1" value="A2" />
<label for="aaa_1">No</label>
<input type="radio" name="aaa" id="aaa_2" value="A2" />
<label for="aaa_2">Unsure</label>
</fieldset>
</div>
<div id="A2" data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>(Question A2) Does a married composite remainder the shallow whistle??</legend>
<input type="radio" name="bbb" id="bbb_0" value="" />
<label for="bbb_0">Yes</label>
<input type="radio" name="bbb" id="bbb_1" value="" />
<label for="bbb_1">No</label>
<input type="radio" name="bbb" id="bbb_2" value="" />
<label for="bbb_2">Unsure</label>
</fieldset>
</div>
If anyone has ideas about fixing this, or examples of other ways to do branching forms, I'd be very grateful!
Thanks,
Patrick
I played around a little bit with your example, removed all your plain JavaScript and added some jQuery Mobile style script, see working example here
<script>
$("input[type='radio']").bind( "change", function(event, ui) {
var mySelection = $('input[name=aaa]:checked').val();
//alert(mySelection);
if (mySelection == "A2") {
$('#A2').removeClass('ui-hidden-accessible');
} else {
$('#A2').addClass('ui-hidden-accessible');
};
});
</script>