Angular - change the content from Radio button on submit button - javascript

I'm stuck in a problem where I want to change a div based on which radio button is clicked. I've been using it without form tag and it changes as soon as I click on the button, NOT ON SUBMIT BUTTON. I want it the other way, i.e, it should submit value on button click and then changes the content, any suggestion what I might've been doing wrong.
It should show different questions based on the radio I select. In the case of YES it shows other and in case of NO, another. Then further questions will be the same. (This logic works fine)
onItemChange(value) {
console.log(value)
this.previous = false;
if (value == 1) {
this.yesOption = true;
} else if (value == 0) {
this.noOption = true;
}
}
Working demo: https://stackblitz.com/edit/angular-ivy-4lhhxh

I created a demo that implements what you asked.
HTML
<div>
<h3>{{ 'Question ' + (currentQuestionIndex+1) }}</h3>
<div>
<div *ngIf="currentQuestionIndex === 0">
<div class="">
<label>Yes</label>
<input value="yes" [(ngModel)]="firstAnswer" type="radio">
</div>
<div class="">
<label>No</label>
<input value="no" [(ngModel)]="firstAnswer" type="radio">
</div>
</div>
<p *ngIf="currentQuestionIndex > 1">Normal question</p>
<p *ngIf="currentQuestionIndex === 1">You selected {{ firstAnswer === 'yes' ? '"Yes"' : '"No"' }} for question 1</p>
</div>
<button (click)="next()">Next</button>
</div>
component.ts
export class AppComponent {
questionsLength = 5;
questions = Array(this.questionsLength);
currentQuestionIndex = 0;
firstAnswer;
next() {
if (this.currentQuestionIndex < this.questionsLength - 1) {
this.currentQuestionIndex++;
}
}
}
You can use ngModel on the radio input and later use that variable to check what has been selected.
Update
If you want to display some divs conditionally:
<ng-container *ngIf="currentQuestionIndex === 1">
<div *ngIf="firstAnswer === 'yes'">You selected "Yes" for question 1</div>
<div *ngIf="firstAnswer === 'no'">You selected "No" for question 1</div>
</ng-container>

If you are not using a form, you need to either:
Store the value somewhere else using [(ngModel)] (don't forget to change configuration to Standalone), or..
Have an object with values and assign individual values in onItemChange callback (if you don't want to use [(ngModel)]
Use #ViewChild to reference the input and get the value (which is.. ugly)
In any case, the logic you currently have in the onItemChange would have to be moved to the nextQuestion.
Per your request, I have made an example on StackBlitz: https://stackblitz.com/edit/angular-ivy-2mwzxd

Related

(Angular) Make checkox disable or enable <mat-slide-toggle>

I have a list of Users to select for a team. Imagine that i select a User, he can either be active or inactive in his team. Now, if i don't select him at all, i should not be able to either activate or deactivate him.
This is made by a checkbox and a slider, like this:
When I click the checkbox, i need to disable the toggle. I have tried doing this by:
$("#2048").prop('disabled', true);
or
document.querySelector('[name="' + '#2048' + '"]').disabled = true;
Does not work either (And yes, i know that IDs should not be numbers, but it's because every toggle is inside a *ngFor. Still, i can use them as numbers, as jQuery can select them anyway)
Either way, i strongly believe that the only way to do something like this is to data-bind the 'disabled' attribute as some back-end variable that returns either a 'true' or 'false' value.
Something like:
<mat-slide-toggle
[id]='data.id'
class="status"
[disabled]='disableVariable'
>Active
</mat-slide-toggle>
and then:
disableVariable = someFunction(); //that returns true or false
This works, but the variable is 'too generic', i mean, every single slider will become disabled. Another problem is that this is not 'real-time', so i cant disable and enable multiple times.
Basically, it does not do the job.
What should i be doing here? If i had a way to select those tags using their unique ID's, that would fix the problem, but neither jQuery or Javascript's Query selector can disable or enable this tag.
EDIT:
A litle more of my code:
<div id="table" *ngFor="let data of User; let i = index">
<div [id]='data.id' *ngIf='data.user== 0' class="item">
<label class="container" style="width: 90%">
<input
type="checkbox"
*ngIf='data.status== 0'
id={{i}}
class="checkbox"
color=primary
checked>
<span class="checkmark"></span>
<div *ngIf='data.status== 0'>{{data.name}}
<mat-slide-toggle
[id]='data.id'
(change)=toggle(data.id)
*ngIf='data.status== 0'
color=primary
class="status"
>Active
</mat-slide-toggle>
</div>
</label>
</div>
</div>
When i add the ([ngModel)], my checkboxes stop working, and yes, i'm importing the FormsModule
You can use two-way binding to update the status of the checkbox as follows:
Add [(ngModel)] and disabled property to the input field
// Declare variable in component
CheckboxVar:boolean;
// In Html write below code
<input type="checkbox" [(ngModel)]="CheckboxVar" [disabled]="!CheckboxVar">
// Disabled checkbox when checkboxvar = false;
<input type="checkbox" [disabled]="!CheckboxVar">
Update CheckboxVar variable as per your need in your component.
Example with mat-slide-toggle
TS Code:
checked = false;
disabled = false;
HTML Code:
<input type="checkbox" [(ngModel)]="checked">
<mat-slide-toggle [disabled]="checked">
Slide me!
</mat-slide-toggle>
Now in the above example, if you checked the checkbox checked variable will be updated and if checked equals true then your toggle will be disabled.
If I understand the requirement correctly:
HTML Code:
<div *ngFor="let obj of list">
<mat-checkbox [(ngModel)]="obj.inTeam">In Team</mat-checkbox>
<br><br>
<mat-slide-toggle [(ngModel)]="obj.inTeam">Active</mat-slide-toggle>
</div>
TS Code:
list = [
{ id : 1,inTeam: false, isActive: false },
{ id : 3,inTeam: false, isActive: false },
{ id : 3,inTeam: false, isActive: false },
{ id : 4,inTeam: false, isActive: false }
]
StackBlitz

Angularjs checkbox checked onload but gives undefined when unchecked first time inside nested ng-repeat

I am using AngularJS, Ionic (v 1) frameworks. On load of the mobile app screen, the checkboxes are to displayed as checked & then user may check or uncheck the checkboxes. The checkboxes are checked on load fine, however, when first time user unchecks a checkbox then the checkbox status value is undefined even though the checkbox is seen to be unchecked. After this when it is checked then it works fine whereby either the checkbox value is true or false depending upon if user checked it or unchecked it. Below if the html section of the code that is displaying the nested ng-repeat and checkboxes displayed. Also, there are multiple checkboxes that can be displayed and that is why second ng-repeat is used to load all the values for the checkboxes. Below the HTML code is the Javascript functions in controllers.
The togglegroup & isgroupshown functions are used to show or hide the checkboxes when the user clicks on the icon next to Extras.
HTML
<form name="list" class="list">
<div ng-repeat="(i, item) in menu_items track by $index">
<div class="item item-divider">
{{item.p_name}}
</div>
<select ng-show="item.Customizable == 1" ng-model="data.cmbIngredient[i]">
<option selected="selected" value="">Select the size</option>
<option ng-repeat="x in item.ProductSizes" value="{{x}}">
{{x.ProductName}}: €{{x.ProductPrice | number:2}}
</option>
</select>
<div>
{{item.p_description}}
</div>
<!-- if the Extras value equates to 1 then the checkbox is displayed-->
<div ng-show="item.Extras == 1">
<i ng-click="toggleGroup(item)" class="icon balanced icon" ng-class="isGroupShown(item) ? 'ion-minus' : 'ion-plus-round'"></i> Extras
<label ng-repeat="(j, ext) in item.ExtraDetails track by $index" class="checkbox" ng-show="isGroupShown(item)">
<input type="checkbox" ng-checked="1" ng-change="AddExtras(data.data[j].chkextras[i],item.p_id)" ng-model="data.data[j].chkextras[i]"> {{ext.CIngredientName}}
</label>
</div>
</div>
</form>
Controller functions
$scope.AddExtras=function(extraStatus,pid){
if(extraStatus == true){
//pass it to service
}
else if (extraStatus == false){
//pass it to a service
}
};
$scope.toggleGroup = function(group) {
if ($scope.isGroupShown(group)) {
$scope.shownGroup = null;
} else {
$scope.shownGroup = group;
}
};
$scope.isGroupShown = function(group) {
return $scope.shownGroup === group;
};
If you read the docs for ng-checked you can clearly read what causes the issue:
Note that this directive should not be used together with ngModel, as this can lead to unexpected behavior.
Conclusion: you should either use ng-checked or ng-model and not mix both.
You should be looking for something like this.
ng-true/false-value

Checked radio button

I need to know if a radio button has been selected to hide / show other options.
<input #r4 type="radio" name="x">
<span>Group</span>
<div class="subOption" *ngIf="r4.checked"></div>
div.subOption must be displayed when it has been selected.
it's correct?¿
I would just create a new boolean variable in the component, that you set as true when radio button has been checked. With that boolean you then display the div. So for example:
isChecked: boolean = false; // our new variable
<input type="radio" name="x" (click)="isChecked = true">
<div *ngIf="isChecked">
<!-- Your code here -->
</div>
EDIT: As to multiple radiobuttons... as mentioned in a comment, radio buttons seems at this point be kind of buggy with Angular. I have found the easiest way to deal with radio buttons seems to be using a form. So wrap your radio buttons in a form, like so:
<form #radioForm="ngForm">
<div *ngFor="let val of values">
<input (change)="changeValue(radioForm.value)" type="radio" [value]="val.id" name="name" ngModel />{{val.name}}
</div>
</form>
whereas on radio button would look like the following in this example:
{
id: 1,
name: 'value1'
}
In the form there is a change event, from which we pick up the chosen radio button value.
(change)="changeValue(radioForm.value)"
Then I would just play with boolean and the value chosen:
changeValue(val) {
this.valueChosen = true; // shows div
this.chosenVal = val.name; // here we have the value chosen
}
A plunker to play with: here

How can I show forms one after another in angularjs?

I am trying to ask one question at a time like "How much did you score in X", when a user selects any of the given buttons, next question will be displayed, this will continue to a certain limit say 10.
Currently I'm displaying all those questions through a loop ng-repeat.
<div ng-repeat="subcode in subjects">
<label class="control-label" for="radios">How much did you score in SUBJECT {{subcode}}?</label>
<div class="btn-group btn-group-m">
<button ng-repeat="grade in gradebuttons" ng-click="saveclick(subcode,grade)" type="button" class="btn btn-default">{{grade}}</button>
</div>
<br/>
</div>
<button ng-click="calculate()">Calculate</button>
my calculate function uses the subcode,grade from saveclick function to process them and display the result just beneath the button.
Also I'm not sure how do I allow user to select just one button, like if they select A1 and again selects A2 in the same subject, previous A1 should be replaced. At this time all grades are selected from all subjects.
You can use ng-show to show current step by using $index and create a variable like currentStep
<div ng-repeat="subcode in subjects" ng-show="currentStep == $index">
which shows only the current question in the list while hiding others
You should update currentStep everytime you save a click to jump up to next question...
$scope.saveclick = function (subcode,grade) {
$scope.answers.push({'subcode' : subcode, 'grade' : grade});
$scope.currentStep++;
}
here is my PLUNKER
try something like
<div ng-repeat="i in [1,2,3,4,5,6,7,8,9]" ng-click="increment(j)" ng-show="$index+1 == j">
<div >{{$index}} How much did you score in SUBJECT {{i}}</div>
</div>`
increment is the scope method which increments the index.
I think you need something like this:
<div ng-repeat="subcode in subjects">
<label class="control-label" for="radios">How much did you score in SUBJECT {{subcode}}?</label>
<div class="btn-group btn-group-m">
<button ng-repeat="grade in gradebuttons" ng-click="saveclick(subcode,grade)"
type="button" class="btn btn-default" ng-show="selectedGrades[subjects[$parent.$index-1]] || $parent.$index== 0" ng-class="{selected: selectedGrades[subcode] == grade}" >{{grade}}</button>
</div>
<br/>
</div>
<button ng-click="calculate()">Calculate</button>
Your JS code:
$scope.saveclick = function (subcode,grade){
$scope.selectedGrades[subcode] = grade; //replace previous selected grade.
};
$scope.selectedGrades = {};
Try:
ng-show="selectedGrades[subjects[$parent.$index-1]] || $parent.$index== 0" to show 1 question at a time and show next when the previous question has been answered.
ng-class="{selected: selectedGrades[subcode] == grade}" to highlight the current selected grade for the subject.
DEMO
If you need to hide the entire question instead of just buttons, move the ng-show to the question and change it to ng-show="selectedGrades[subjects[$index-1]] || $index== 0"
DEMO
If you need to hide the question as soon as it's answer, try: ng-show="(selectedGrades[subjects[$index-1]] || $index== 0) && !selectedGrades[subcode]"
DEMO

toggle checkbox values

I am trying to toggle the value of a checkbox using the following code:
<div class="control-group">
<label class="control-label checkbox" for="IsViewAsWebpage">
{{#if this.IsViewAsWebpage}}
<input type="hidden" id="IsViewAsWebpage" name="IsViewAsWebpage" value="true"/>
<input type="checkbox" class="enable-checkbox" checked />
{{else}}
<input type="hidden" id="IsViewAsWebpage" name="IsViewAsWebpage" value="false"/>
<input type="checkbox" class="enable-checkbox" />
{{/if}}
<span>View as Webpage</span>
</label>
</div>
'click .enable-checkbox': function (e) {
if (e.currentTarget.parentElement.htmlFor == "IsViewAsWebpage") {
this.$('#IsViewAsWebpage').is(':checked');
}
}
I know I am misssing something in the click function. I would basically want to toggle the checkbox value when the user clicks on it. Can someone point me to the right directions pls. Thank you.
When your checkbox gets clicked, it's going to toggle. That's the way checkboxes work.
If you want the hidden input to change value when the checkbox is toggled, I think what you want is this:
$(".enable-checkbox").change(function (e) {
if($(this).parent().attr("for") == "IsViewAsWebpage") {
var checked = $(this).is(":checked"); // Returns true/false.
$('#IsViewAsWebpage').attr("value", checked); // Sets true/false.
}
});
If you want to use handlebars.js to switch content when you click an check box, you will need to replace your content by calling handlebars each time you make a modification to your checkbox
$(".enable-checkbox").change(function (e) {
if($(this).parent().attr("for") == "IsViewAsWebpage") {
var checked = $(this).is(":checked");
IsViewAsWebpage = checked;
$("#yourcontainer").html(Handlebars.compile(yourtemplatesource));
}
}
then your IsViewAsWebpage variable should be global and your mustache condition should only be :
{{#if IsViewAsWebpage}}
But this is complicated for nothing... just use Aesthete solution, it will save you a lot of time.

Categories