Handling multiple radio buttons in a Quiz Angular 5 - html

I'm new to Angular and Implementing a Quiz containing multiple MCQs.
But I am having trouble in radio button selection.
My Questions are coming from the database and Options too.
mcq.component.html
<form (ngSubmit)="ff.form.valid && answer(ff)" #ff="ngForm">
<div *ngFor="let question of questions">
<p style="font-size: 25px;">{{question.title}}</p>
<div *ngFor="let option of question.options">
<input [(ngModel)]="option_model.selected_option_id" #selected_option_id="ngModel" type="radio" value="{{option.id}}" name="{{question.id}}">
<!-- <input type="radio" value="{{option.id}}" name="{{question.id}}" ngModel > --> //This way it works fine but I need to use [(ngModel)] to submit the form
{{option.title}}
</div>
</div>
<input style="float: right" type="submit" value="Submit"/>
</form>
Note: The {{question.id}} is unique for each question. Also, this works well if I remove the [(ngModel)] attribute.
And here is what I'm trying to accomplish
The Problem: When I select an option from the second question it deselects the selected option from the First Question. Means I am only able to select one option from both questions.
Please Help me, what I am doing wrong. I've been stuck here for two days.

Okay, Git it Sorted. The issue was with the ngModel and name attribute
It works fine like this
<input [(ngModel)]="options[question.id]" [checked]="options[question.id]" value="{{question.id}}-{{option.id}}" type="radio"
name="option{{question.id}}">
And in typescript
options: any = [];
option: any = [];

Related

Show clarity radio buttons based on a condition in Angular

I have a div which has a couple of clr radio buttons wrapped in a .I want to generate the radioButtons based on a boolean value. Following is the code.
<div class="clr-col-4">
<clr-radio-container>
<label class="display-label">Radio Div</label>
<clr-radio-wrapper *ngFor="let col of cols">
<input type="radio" clrRadio />
<label class="display-label" {{col.headerName}}</label>
</clr-radio-wrapper>
</clr-radio-container>
</div>
I have a variable named enableButton. If the enableButton is true, I want to show the radio button, else I don't want to. Could you please help me how to do this?
You can use the ngIf directive. It is an essential thing to have in mind when creating Angular templates.
<div class="clr-col-4">
<clr-radio-container *ngIf="enableButton">
<label class="display-label">Radio Div</label>
<clr-radio-wrapper *ngFor="let col of cols">
<input type="radio" clrRadio />
<label class="display-label" {{col.headerName}}</label>
</clr-radio-wrapper>
</clr-radio-container>
</div>
I suggest you read the docs to familiarise more with the directive and its other conditional variations like then, else, etc.

ngModel and checkbox/radio not working properly

I made html template for my app. Basically it's a radio/checkboxes with text inputs which contain answers to questions. It worked just fine until I've decided to add ngModel to them. The thing is that when I add 2 or more answers and click on a label to set the correct one(/s) only the last one selects, moreover the answertext disappears whenever I click on label.
html text:
<div *ngIf="question.typeQuestions==1">
<div *ngFor="let item of question.selectedAnswer; let i = index" class="checkbox-variable">
<input type="checkbox" id="customCheckbox{{i}}" name="customCheckbox" class="checkbox-square" [(ngModel)]="item.isCorrect" >
<label class="checkbox-label" for="customCheckbox{{i}}"><input class="checkbox-text" type="text" [(ngModel)]="item.text"></label>
</div>
</div>
ChrisY solved the problem.
having multiple input with the same name is definitive wrong here. Try name="customCheckbox{{i}}". When using ngModel you need a name that identifies the form control. It has to be unique

radio inputs not working correctly in angular 7

I got radio inputs, rendered using the structural directive ngFor.
<form>
<label *ngFor="let user of staffMembers" class="stuff" for="user.username">
{{user.username}}
<input type="radio" [name]="user.username" [value]="user.username">
</label>
</form>
I got the inputs correctly but i can check multiple fields like checkbox. It's not the default behavior for radio inputs.
Because you are creating a new radio group with each line, not a new radio option. The input [name] is the name of the radio group, NOT the option.
<form>
<label *ngFor="let user of staffMembers" class="stuff" for="staffMembers1">
{{user.username}}
<input type="radio" id="staffMembers1" name="staffMembers" [value]="user.username">
</label>
</form>
The name shouldn't be unique to get the normal behavior, otherwise, it's just radio with only one possibility.
<input type="radio" name="user" [value]="user.username">
You need to give all radio inputs the same name:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio
Right now it seems each radio input gets a different one since user.username is always different.

bind to ngModel through clickable options instead of select-option (dropdown)

I am trying to build a basic colorpicker with predefined colors.
for that I have an object "colors" with color-values as it's properties:
public colors = [
{ value: '#ffffff' },
{ value: '#919191' },
{ value: '#555555' },
// and some more
];
Following some examples on the web, I set up a select-option structure in my html:
<select name="role" [(ngModel)]="item.color">
<option *ngFor="let color of colors" [value]="color.value">
<div class="color-box-modal" [style.background]="color.value"></div>
</option>
</select>
This does create a dropdown menu for the options, though the colors inside don't show up. The class color-box-modal has height and width values as I did not intend to have a dropdown, but several colored boxes to click on in order to select.
Is there an alternative to the select-option structure which allows me to not have a dropdown, but just several colored boxes? Radio-buttons/checkboxes are not the desirerable way either, as I want to have a clickable field on it's own that reacts to being clicked.
If there is no alternative, is it possible to do the ngModel binding on a button-click?
edit:
After testing option 2 on Osman Ceas answer, I now have this:
<ng-template #content let-c="close" let-d="dismiss">
<i class="close icon" (click)="d('Close click x')"></i>
<div class="header">
Choose a new color
</div>
<div class="content">
<label for="col1" class="color-box-modal" style="background-color: #ffffff">
<input (click)="c('#ffffff')" id="col1" type="radio" class="hidden" [(ngModel)]="item.color" [value]="'#ffffff'">
</label>
<label for="col2" class="color-box-modal" style="background-color: #ffff00">
<input (click)="c('#ffff00')" id="col2" type="radio" class="hidden" [(ngModel)]="item.color" [value]="'#ffff00'">
</label>
<label for="col3" class="color-box-modal" style="background-color: #00ffff">
<input (click)="c('#00ffff')" id="col3" type="radio" class="hidden" [(ngModel)]="item.color" [value]="'#00ffff'">
</label>
</div>
<div class="actions">
<div class="ui button" (click)="c('Close click cancel')">Cancel</div>
</div>
</ng-template>
Though the ngModel binding does not seem to work.
The whole thing opens in a modal (the template), which in itself works, just binding to the ngModel, as I said, does not.
A native HTML select will only render text inside and any other tag will be ignored, so that's why your boxes are not showing.
If your wrap your radio button or checkbox in a <label> with the attribute for equals to an ID given to the <input>, you can basically click anywhere on the label, lets say some adjacent text, and the click will propagate to the input so the binding will still work.
You can create your own custom form controls, check out this article. So you could create a custom color picker form element that will work in any form using template forms or reactive forms.
Have a nice day
Now, this might not help everyone, but it was my solution in the end.
I started with a loop, item of items where the template in my question was meant for one single item.
I solved, or rather worked around the binding situation by just moving each item to it's own component, somewhat like this:
<div *ngFor="let item of items>
<app-sub-item [item]="item"></app-sub-item>
</div>
inside I have severel of these:
<label for="col1" class="color-box-modal" style="background-color: #ffffff">
<input (click)="setColor('#ffffff')" id="col1" type="radio" class="hidden">
</label>
With the following being in the ts-file:
setColor(color: string) {
this.item.color = color;
}
This actually works just fine at the moment.
Hope whoever reads this issue can find some use in my solution.

Naming dynamically created radio button groups with Angular2

I'd like to preface this question by noting that I am relatively new to web development and Angular2.
I have an Angular2 component whose function is to create a tree view on a webpage using the angular-tree-component library (https://angular2-tree.readme.io). For each node in the tree, I have defined a popover HTML template (from ng2-bootstrap) with radio buttons in it.
Since the tree can be of any size, the radio buttons are created dynamically in the popover using a template declared in the tree component HTML.
My issue is that the radio button groups are linked together, as if they were all a single group. I have tried several different ways of naming the button groups dynamically (ideally they would all be separate groups), but nothing seems to work.
Example code:
<div class="testTree">
<Tree #tree id="tree1" [nodes]="nodes">
<template #treeNodeTemplate let-node="node" let-index="index">
<span>{{ node.data.name }}</span>
<template #popTemplate>
<div class="popDiv">
Name: {{node.data.name}}<br>
id: {{node.data.id}}<br>
</div>
<div [innerHtml]="html"></div></template>
<template #incTemplate>
<div class="popDiv">
<input type="radio" attr.name="node.data.id"
value="ab" (change)="foo(node, $event.target.value)"> Button1<br>
<input type="radio" attr.name="node.data.id"
value="bc" (change)="foo(node, $event.target.value)"> Button2<br>
<input type="radio" attr.name="node.data.id"
value="cd" (change)="foo(node, $event.target.value)"> Button3<br>
<input type="radio" attr.name="node.data.id"
value="de" (change)="foo(node, $event.target.value)"> Button4<br><br>
<button (click)="bar(node)">ok</button>
</div>
<div [innerHtml]="html"></div></template>
<button class="nodeButton" *ngIf="node.isActive || node.isFocused"
[popover]="popTemplate" placement="right" triggers="" popoverTitle="title1" #pop="bs-popover" (click)="pop.toggle()">Details</button>
<button class="nodeButton" *ngIf="node.isActive || node.isFocused"
[popover]="incTemplate" placement="right" triggers="" popoverTitle="title2" #pop2="bs-popover" (click)="pop2.toggle()">Options</button>
</template>
</Tree>
</div>
I have tried to name the button groups in the #incTemplate in the following ways:
name = "node.data.id"
name = "{{node.data.id}}"
[attr.name] = "node.data.id"
attr.name = "{{node.data.id}}"
attr.name = "node.data.id"
To see what was happening, I gave the radio buttons an id and selected it in the angular2 class to log the name value. The name was either blank or the literal string "node.data.id".
I would use ngModel, but since there could be a large number of radio button groups I can't have them using the same variables.
Each tree node has two variables ('id' and 'name') which are unique to each node and could be used to name the radio buttons. However, I can't seem to get the name field of the button to resolve any of the expressions and take the value of the data field provided by the tree node.
How can I get the radio button groups named dynamically so that they are separate from each other?
It turns out I had included (ngModel) and id fields in the radio buttons' definitions. Removing these fields allowed the radio buttons to function as intended despite the dynamically created groups sharing the same name.
Try this approach
<div *ngFor="let location of locations">
<input
[attr.id]="location"
type="radio"
name="location"
ngModel
[value]="location">
<label [attr.for]="location">{{location}}</label>
</div>
Note this is just a example demonstrating how it works you have to
adjust your code according to your requirements