Angular toggle switch issue on duplicated form group - javascript

I have a form group that has several form controls within it, including a toggle switch. The toggle switch changes a boolean value in the model to true or false. Dependent upon the value, there is an *ngIf that handles if form controls are displayed or not. This all currently works fine, however I have a requirement to actually basically clone the entire form group, which I have achieved. However, the toggle switch only works on the first form group, and none of the rest. And actually, if I click the toggle on the others it actually toggles just the first one on and off...what am I missing here?
Here is how it looks, I actually clicked the 2nd toggle switch:
The model has this value:
advancedOptions: boolean;
The template is like so:
<div class="advancedOptions">
<div class="service-group jbh-toggle">
Advanced Options:
<label class="toggleLabel inline-block" for="inbond-freight">Hide</label>
<input class="jbh-toggle-checkbox ng-untouched ng-valid ng-dirty" #advancedOptions id="handlingUnitAdvancedOptionsToggle" type="checkbox"
(change)="handlingUnitAdvancedOptionsToggle(advancedOptions.checked)">
<label class="jbh-toggle-label" for="handlingUnitAdvancedOptionsToggle">
<span class="jbh-toggle-inner" id="span-toggleInner3"></span>
<span class="jbh-toggle-switch" id="span-toggleSwitch3"></span>
</label>
<label class="toggleLabel inline-block" for="handlingUnitAdvancedOptionsToggle">Show</label>
</div>
</div>
The *ngIf is simply:
<div *ngIf="advancedOptions"></div>
All the other controls work fine in the duplicated form group, except for the toggle switch.

You can use your formcontrol value of toggle switch like when it's value is true then you can show/hide like below
form.controls.default_checkbox.value != 1

Related

radio button's disabled property is not working inside the reactive form

Radio button's disabled property is not working inside the reactive form but it's working fine when I put radio button outside the reactive form.
I have a condition like if my current status is CLOSED I should allow the user to edit radio button inside the reactive form I already tried with Disabled property of radio button but no luck
component.ts
conducttestlm:any={
isReadOnly:false
}
this.condutTestLM=this.formBuilder.group({
"testStatus":['',Validators.required],
})
if(success.data.status=='CLOSED'){
this.conducttestlm.isReadOnly=true;
}
component.html
<form [formGroup]="condutTestLM">
<div class="row radio-top">
<div class="col-md-6 p-l-15">
<label class="radio-box">
<input formControlName="testStatus" name="testStatus" [(ngModel)]="conducttestlm.teststatus" [disabled]="conducttestlm.isReadOnly" value="Pass" type="radio">
<span class="checkmark"></span>
<span class="font-style">Pass</span>
</label>
</div>
<div class="col-md-6 p-l-15">
<label class="radio-box">
<input formControlName="testStatus" name="testStatus" [(ngModel)]="conducttestlm.teststatus" [disabled]="conducttestlm.isReadOnly" value="Fail" type="radio">
<span class="checkmark"></span>
<span class="font-style">Fail</span>
</label>
</div>
</div>
</form >
I need to disable the radio button
Don't use template driven approach while using reactive forms. Have your code like:
<form [formGroup]="condutTestLM">
<div class="row radio-top">
<div class="col-md-6 p-l-15">
<label class="radio-box">
<input formControlName="testStatus" name="testStatus" [attr.disabled]="conducttestlm.isReadOnly ? true : null" value="Pass" type="radio">
<span class="checkmark"></span>
<span class="font-style">Pass</span>
</label>
</div>
<div class="col-md-6 p-l-15">
<label class="radio-box">
<input formControlName="testStatus" name="testStatus" [attr.disabled]="conducttestlm.isReadOnly ? true: null" value="Fail" type="radio">
<span class="checkmark"></span>
<span class="font-style">Fail</span>
</label>
</div>
</div>
</form>
See an example here: https://stackblitz.com/edit/angular-dncxac?file=src%2Fapp%2Fapp.component.html
You will notice that I have used attr.disabled instead of disabled to disable individual radio buttons.
To know the difference between attr.disabled and disabled, you can have a look at this link. In a gist, attr.disabled is an HTML attribute while disabled is a DOM property. There are some HTML attributes for which DOM properties don't exist, as shown in the added link.
From angular docs
Attributes are defined by HTML. Properties are defined by the DOM (Document Object Model).
A few HTML attributes have 1:1 mapping to properties. id is one example.
Some HTML attributes don't have corresponding properties. colspan is one example.
Some DOM properties don't have corresponding attributes. textContent is one example.
Many HTML attributes appear to map to properties ... but not in the way you might think!
This is not true for input boxes and disabled DOM property. There indeed is a disabled DOM property but there is some issue while using it individually over radio buttons. See this Github issue. The solution I provided is more of a workaround to achieve individual disabling of radio buttons.
One possibility is that the status change is not being detected while rendering. First of all:
// instead of using this:
[disabled]="conducttestlm.isReadOnly"
// Use the readonly attribute:
[readonly]="conducttestlm.isReadOnly"
Next, use ChangeDetectorRef to detect any changes manually:
// import it:
import { ChangeDetectorRef } from '#angular/core';
// and inject it into your contructor:
constructor(private ref: ChangeDetectorRef) {
...
}
// call it
if(success.data.status=='CLOSED'){
this.conducttestlm.isReadOnly=true;
this.ref.detectChanges();
}
Should detect changes in status immedietly on run. If not, try console logging your conducttestlm.isReadOnly value to ensure it's changing.
If you want to use template driven attribute, you can use [attr.disabled] instead [disabled] as well.

ng-disabled not evaluating every time on button click

I'm actually trying to disable a pair of radio buttons on the click of a button in my angularjs application.
Code Snippet of radio buttons is provided below here:
<div class="col-xs-4 btn-group" id="challenge-radio-btn">
<label class="radio-inline">
<input type="radio" ng-model="trigger" ng-value=false
name="{{path.id}} notChallengeTriggr"
ng-change = "onChange(x,y,z,w,a)"
ng-disabled="campaign.editnotscheduled || ischallengeTrigger"
checked> No
</label>
<label class="radio-inline">
<input type="radio" ng-model="trigger" ng-value=true
name="{{path.id}} challengeTriggr"
ng-change = "onChange(x,y,z,w,a)"
ng-disabled="campaign.editnotscheduled || ischallengeTrigger"> Yes
</label>
</div>
On click of the button, I have even tried printing the value of the expression which is getting evaluated inside of ng-disabled. On every click of this button, the value becomes true(as I have written js code-behind to make this true). Even the value of the ng-disabled expression is true, the radio buttons are not getting disabled.
On debugging, I had found a particular scenario where it wasn't working. Once I click on a specific dropdown in my application, after that if I come back & click on edit button to check whether these radio buttons are disabled or not. At that time, radio buttons are not disabled even though the ng-disabled expression value is true.
I think the logic of OR is causing the problem.
ng-disabled="campaign.editnotscheduled || ischallengeTrigger" checked>
ng-disabled="editnotscheduled || ischallengeTrigger">
If either of them is false.then your button should get disabled.

To disable all radio buttons if anyone of them is clicked in angularjs ng-repeat

what i am trying to do here is, i have an ng-repeat in a form and if i click anyone of those input buttons corresponding all buttons get disabled
<div ng-repeat="question in sinSurCtrl.singleSurvey" ng-show="!$first">
<hr>
<p>Q. {{question.questionText}}</p>
<form >
<div ng-repeat=" option in question.questionOptions track by $index">
<label>
<input name="options" type="radio" value="$index" ng-click="sinSurCtrl.questionId=question.questionId; sinSurCtrl.answer=$index+1; sinSurCtrl.createAnswer()" onclick="this.disabled = true">
<span> {{option}} {{$index+1}} {{question.questionId}} </span>
</label>
</div>
</form>
</div>
here is the view-
as you can see if i select anyone of those option it is getting disabled but what i am trying to do is if i attempt anyone option then options corresponding to the same question get disabled.
for example-
in Q3. which is a better orator ?
if i choose option (a) then it get selected and after that automatically bot options (a) and (b) get disabled.
Note- please try to keep solution completely in angularjs or if you want use affordable amount of javascript other then that please avoid using external libraries like jQuery(i know nobody in his senses will handle trouble of using jQuery and angular together but for the sake of example i have included its name)
Proposed solution with some suggested refactoring...
First change the ng-click directive to point to a new onOptionButtonClicked function on sinSurCtrl which takes in the two parameters question and index (which it needs to carry out it's work):
<div ng-repeat="question in sinSurCtrl.singleSurvey" ng-show="!$first">
<hr>
<p>Q. {{question.questionText}}</p>
<form>
<div ng-repeat="option in question.questionOptions track by $index">
<label>
<input
name="options"
type="radio"
value="$index"
ng-click="onOptionButtonClicked(question, $index)"
ng-disabled="question.disabled">
<span> {{option}} {{$index+1}} {{question.questionId}} </span>
</label>
</div>
</form>
</div>
Also take note of the newly added ng-disabled="question.disabled" directive. This is part of the mechanism that will enable/disable the question's controls.
Now move the variable assignments to the new onOptionButtonClicked function. The controller is generally a better place (than the view) for variable assignments, especially if there are several of them on the same directive.
sinSurCtrl.onOptionButtonClicked = onOptionButtonClicked;
function onOptionButtonClicked(question, index){
sinSurCtrl.questionId=question.questionId;
sinSurCtrl.answer=index;
sinSurCtrl.createAnswer();
question.disabled = true; // <--- This is what disables the option buttons
}
This is where an answered question object gets it's disabled property set to true. This in combination with the ng-disabled directive mentioned previously is what disables the option buttons.
On your controller, create a function that checks if a given questionId has been answered and return truthy if it has. Call that function in ng-disabled in the input tag:
<input type="radio" ng-disabled="sinSurCtrl.questionHasAnswer(question.questionId)" ... />

Angular Js - formating label when inner radio input is checked

I'm dealing with this case where I have a label tag wraps around the radio input button, something like:
<label>
<input type="radio" ng-model="question.value" value="{{option.value}}">
</label>
The label tag is the one that gets formatted for view while the radio button is hidden. When ng-model == value, a certain radio button gets checked automatically and this is happening in my app, no problem at all.
The problem is, I want to format the label tag when this happens. Normally the label is formatted by an onclick event, but this is not an event so I'm not sure how I would solve this in JavaScript. CSS styling is not an option because it can't select parent element.
use ng-class
<label ng-class="{'class-name':question.value==option.value">
<input type="radio" ng-model="question.value" value="{{option.value}}">
</label>
in CSS
.class-name{
color:green;
}

Radio button keyboard trap

I'm creating a multiple choice question exercise and am having issues with keyboard accessibility. Basically, the user is not able to cycle through the list of radio buttons through the keyboard. When the "focus" cursor is over a radio button and the user pressed the arrow key to move onto the next radio button a keyboard trap occurs. Instead of simply focusing it, the radio button is selected instead and thus the answer is displayed. How can I stop radio buttons being selected when going through them with the keyboard?
HTML markup:
<div id="contentWrapper">
<p class="instructions">Click on the correct answer.</p>
<ol start="49">
<!-- Start of multiple choice question -->
<li class="multipleChoice gradedQuestion">
<p class="question">If you receive a request for an extension from a trader, you should:</p>
<input type="hidden" name="questionNumber" value="49">
<ul>
<li>
<div class="answerOption"><label for="question49A">Refer to IP 13; if the original requirements are still being met, approve the extension.</label></div>
<div class="inputAndIdContainer"><input type="radio" name="question49" value="0" id="question49A"> A.</div>
</li>
<li>
<div class="answerOption"><label for="question49B">Refer to IP 20; if the original requirements are still being met, approve the extension.</label></div>
<div class="inputAndIdContainer"><input type="radio" name="question49" value="0" id="question49B"> B.</div>
</li>
<li>
<div class="answerOption"><label for="question49C">Refer to FW1; if the original requirements are still being met, approve the extension.</label></div>
<div class="inputAndIdContainer"><input type="radio" name="question49" value="1" id="question49C"> C.</div>
</li>
</ul>
<div class="feedback">
<div class="answeredCorrectly">Correct</div>
<div class="answeredIncorrectly">Incorrect</div>
<div class="answer">
<strong>Answer:</strong> C - Refer to FW1.
</div>
</div>
</li>
<!-- End of multiple choice question -->
Short answer is you can't, and this isn't a keyboard trap. That is the nature of a radio.
If they are grouped together (name attribute), you tab into it; by pressing space you select the first item, by using the arrow keys it selects the next item. You should write your JS to watch for focus to enter the group and then leave. Once left, show <div id="feedback"> or make a button to show it.
Edit Regarding your other post, you probably need to add a .focus() function that is similar to .click().
That's the way they should work, take a look at this document!
Basically it's this:
On IE, when a radio button group is reached via tabbing, the initially selected button is focused on, and the dotted rectangle indicates this. You can use arrow keys to move between the buttons inside the group; both "down" and "right" arrow move forward inside the group, and both "up" and "left" arrow move backward. And upon moving to a button, that button gets checked (and the button in the group that was checked gets unchecked).
On Netscape, things are different. When a set of radio buttons is reached via tabbing, the first button receives focus. You can move forward inside the group by tabbing. Moving to a button that way does not change the setting. Use the space bar or Enter key to check a button.
I solved this problem by blurring the input after it's been clicked.
At least with this way if you are navigating using tab/space/arrow keys it will not mess with the user. If they click it's very unlikely they will be using arrow keys to select the next option.
Jquery:
$('.quiz input:radio').click(function(){ $(this).blur()})

Categories

Resources