ngModel in input radio? - javascript

I'm developing an application using Angular 6. I have a big problem.
Using a template-driven form I would like that the item selected in a radio button can be sent when I press the submit button.
It's all right when I work with <input type="text" [(ngModel)] = "value" /> (value is a data field of my component), but if I try with this:
<div class="form-group">
<div *ngFor = "let option of options">
<div class="radio">
<input type = "radio"
name = "radio"
[(ngModel)] = "value"
/>
<label for="{{option.id}}">{{option.id}}</div>
</label>
</div>
</div>
</div>
The result is a bug! I can't even click the multiple buttons by moving the selector! Everything is stuck! Obviously it does not work with the form.
If I remove [(ngModel)] = "value" graphically it works, but without ngModel directive if I enter this code inside a template-driven form that uses (ngSubmit) it does not work.
Thanks a lot.

You are missing a value for each of the radio buttons so the binding does not work correctly. It is unable to determine which input should be checked so none of them get checked. Update the template to be something like:
<div *ngFor="let option of options">
<div class="radio">
<input type="radio"
name="radio"
id="radio-{{option.id}}"
[(ngModel)]="value"
[value]="option.value"
/>
<label for="radio-{{option.id}}">{{option.id}}
</label>
</div>
Stackblitz Demo

Radio buttons work different. To need to add a value to make it work. If you want to assign a value from angular use [value].
I have make it running in an example of stackblitz:
<div class="form-group">
<div *ngFor="let option of options; let i=index">
<div class="radio">
<input type="radio" id="{{option.id}}" name="radio{{i}}" [(ngModel)]="option.value" [value]="option.id" />
<label for="{{option.id}}">{{option.id}}</label>
</div>
</div>
</div>
<hr>
<h2>Values for options</h2>
<ul>
<ng-container *ngFor="let option of options; let i=index">
<li *ngIf="option.value !== ''">Value for {{option.id}}: {{option.value}}</li>
</ng-container>
</ul>
Component
value: any;
options = [
{
id: "test1",
value: ''
},
{
id: "test2",
value: ''
},
{
id: "test3",
value: ''
}];
Extension/Hints:
You can even use [(ngModel)] = "value" to assign the last selected value to value.
Give these radio buttons the same name name="radio" to ensure that only one of this group can be selected.

Inside the ts file :
radio_button_value = null;
box_options = [
{
"name": "Word",
"value": "word",
},
{
"name": "Line",
"value": "line"
},
]
Inside the html file:
Do notice of the tag 'name', it would we a great concern inside another for loop.
<div *ngFor="let box_opt of box_options; let i=index">
<input name="option-{{i}}" type="radio" [value]="box_opt.value" [(ngModel)]="radio_button_value">
{{box_opt.name}}
<br>
</div>

Related

ngIf an angular reactive form component value

I have a set of radio buttons. If a user selected the value "yes" I want to show an additional box on the form.
https://stackblitz.com/edit/angular-4bgahw?file=src/app/personal/personal.component.ts
HTML.component
<div formGroupName="radioButtonsGroup" class="form-group col-6 pl-0 pt-3">
<div class="form-check-inline" *ngFor="let item of personal.radioButtonsdata">
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input [value]="item" id="{{item.section}}" type="radio" formControlName="selectedButton"/>
<span class="checkmark"></span>
</label>
</div>
<!-- <div class="col-md-8" *ngIf="selectedButton.control.item === 'yes'"> --> //my attempt to target above input value
<div class="col-md-8" >
<input type="text" formControlName="title" class="form-control" placeholder="Title">
</div>
</div>
Can anybody get this to work and show me what I am doing wrong here please?
You need to access the value of the form control:
*ngIf="form.get('radioButtonsGroup.selectedButton').value.section === 'yes'">
STACKBLITZ
Everything you write in the template is resolved against the corresponding class (or against template variables), so you have to refer to the JavaScript control like this:
*ngIf="form.controls['selectedButton'].value === 'yes'"
Call a function to set flag based on value of the radio button, (ngModelChange)="onRadiochange($event)"
Try like this:
Working Demo
.html
<input [value]="item" (ngModelChange)="onRadiochange($event)" id="{{item.section}}" type="radio" formControlName="selectedButton" />
<div class="col-md-8" *ngIf="showTitle">
<input type="text" formControlName="title" class="form-control" placeholder="Title">
</div>
.ts
onRadiochange(e) {
if(e.section == 'yes'){
this.showTitle = true
} else {
this.showTitle = false
}
}
It can also be done in one line like this:
<input [value]="item" (ngModelChange)="$event.section == 'yes' ? showTitle=true:showTitle=false" id="{{item.section}}" type="radio" formControlName="selectedButton" />
Whenever yes checkbox is selected, you have to display the title textbox.
In that case, change your code like this.
In personal.component.ts, add this variable.
yesSelected: boolean = true;
Also in ngOnInit(),
this.form.valueChanges.subscribe(val=>{
if(val.radioButtonsGroup.selectedButton.section === "yes")
this.yesSelected = true;
else
this.yesSelected = false;
});
In personal.component.html, rewrite your if condition like this.
<div class="col-md-8" *ngIf="yesSelected">
<input type="text" formControlName="title" placeholder="Title">
</div>
These changes will show the title textbox only when the yes check box is selected.

Angular.js Bind ng-model with ng-repeat in input:checkbox

I have an App using Angularjs v1.69
I Get a Json Response of Time Slot
The below is the Current Code:
$scope.TimeSlotList = JSON.parse(localStorage.getItem("TimeSlots"));
Console.log($scope.TimeSlotList);
Output:
[
{
"id": 1,
"time": "7am - 10am"
},
{
"id": 2,
"time": "10am - 1pm"
},
{
"id": 3,
"time": "1pm - 4pm"
},
{
"id": 4,
"time": "4pm - 7pm"
},
{
"id": 5,
"time": "7pm - 10pm"
}
]
and this is done in the partial
<div class="col-md-6">
<div class="form_pad20">
<label>Prefered Time</label>
<div class="clearfix">
<div class="form-field field-destination">
<div class="radio-checkbox display_inline" ng-repeat="x in TimeSlotList">
<input id="check-{{x.id+9}}" type="checkbox" class="checkbox" ng-model="TimeSlotList[$index]">
<label for="check-{{x.id+9}}">{{x.time}}</label>
</div>
</div>
</div>
</div>
</div>
The Required output is Whichever Checkbox is selected i want that value
For Ex: if the user select time slot 2 and 3
i want to send 23 to the backend
i.e Timeslot-2 and Timeslot-3 should return true
or something else i want output as
var FinalTime="23";
Trying to figure out from last 2 days
But After Few Atempts basically th best solution was
ng-model="TimeSlot-{{x.id}}"
but this throughs error
Error: [ngModel:nonassign] Expression 'ScdItem.TSlot(x.id)' is non-assignable.
please can anybody help me ?
Change the TimeSlotList so that it contains a selected field. The initial value can be set to false.
$scope.TimeSlotList = JSON.parse(localStorage.getItem("TimeSlots"));
$scope.TimeSlotList.forEach(item => item.selected = false);
Then bind the selected field to the corresponding checkboxes using ng-model:
<input id="check-{{x.id+9}}" type="checkbox" class="checkbox" ng-model="x.selected">
This will change the selected's value based on checkbox is checked/not checked. When you send the data to the server, you can extract the IDs of the slots based on the value of selected field, like this:
var selectedSlots = $scope.TimeSlotList
.filter(slot => slot.selected) // Get all the selected slots
.map(slot => slot.id) // Extract IDs of the slots
.join(''); // Join the IDs to form a string
This way selectedSlots will contain the IDs of the slots selected.
<div class="col-md-6">
<div class="form_pad20">
<label>Prefered Time</label>
<div class="clearfix">
<div class="form-field field-destination">
<div class="radio-checkbox display_inline" ng-repeat="x in TimeSlotList">
<input id="check-{{x.id+9}}" type="checkbox" class="checkbox" ng-model="x.id" ng-change="checkTimeslot(x.id)">
<label for="check-{{x.id+9}}">{{x.time}}</label>
</div>
</div>
</div>
</div>

Draw open closing tag if value is true in angularjs

Let's say I have a form, which iterates over some fields.
I want to wrap some fields in a container, so that I can split the form into sections.
I have tried to put field_open = true under the item I want to start opening the div, and then field_close = true under the last field in that container and then I repeat this process.
<form name="{{form.form_name}}" id="{{form.form_id}}">
<div ng-if="field.field_open == true" class="halfCol">
<div ng-repeat="field in form.form_fields">
<div class="{{field.field_class}}">
<field-directive field="field"></field-directive>
</div>
</div>
</div ng-if="field.field_close == true">
</form>
Obviously this doesn't work, but I'm wondering how I can achieve this?
The below HTML is how it should be rendered:
<form name="test" id="test">
<div class="halfCol">
<label for="apple">Apple</label>
<input type="text" name="apple" id="apple" />
<label for="fruit">Fruit</label>
<input type="text" name="fruit" id="fruit" />
</div>
<div class="halfCol">
<label for="dog">Dog</label>
<input type="text" name="dog" id="dog" />
</div>
</form>
The above html should be drawn from the following data.
var data = {
"form_name": "test",
"form_fields": [
{
"field_title": "Apple",
"field_open" : false
"field_open" : true
}{
"field_title": "Fruit",
},{
"field_title": "Dog",
"field_close" : true
"field_open" : true
}
]}
I'm more or less looking for a way to wrap certain elements in the same field scope.
What will the decision to separete the fields in sections depend on?
If the decision depends on some aspect of presentation, I think you don't need to use model data as you do. I mean you could write simple html without ng-repeat directives.
If you insist to use model data, your model structure will be like below.
var data = {
"form_name": "test",
"form_sectinons": [
{
"section_title": "section 1",
"fields": [
{"field_title": "Apple"},
{"field_title": "Fruit"},
]
},
{
"section_title": "section 2",
"fields": [
{"field_title": "Dog"},
]
}
]
}
And Html will be like below.
<form>
<div ng-repeat="section in data.form_sections">
<div ng-repeat="field in section.fields" class="halfCol">
<field-directive field="field"></field-directive>
</div>
</div>
</form>
I'm not sure quite what you are trying to do but you should do like this:
<form name="{{form.form_name}}" id="{{form.form_id}}">
<div ng-if="field.field_open == true && field.field_close == true" class="halfCol">
<div ng-repeat="field in form.form_fields">
<div class="{{field.field_class}}">
<field-directive field="field"></field-directive>
</div>
</div>
</div>
</form>

Angularjs input radio and ng-repeat issue

Okay so here is my setup i have the following array:
answers = [answer1, answer2]
with these i do the following:
<form>
<div class="col-xs-12" ng-repeat="answer in component.question.answers">
<div class="col-xs-1" style="width: 1%">
<div class="radio">
<label class="i-checks">
<input type="radio" name="a" ng-model="answer.is_correct">
<i></i>
</label>
</div>
</div>
<div class="col-xs-11">
<input type="text" ng-model="answer.answer" class="form-control" placeholder="Svar">
</div>
</div>
</form>
Now the input[radio] are inside the same form as they should. My goal is that when i set one as selected both of the answer objects should be updated so that only one of the object has the value is_correct = true
However what happens right now is that if i click the first and then second both values have is_correct = true
So what can i do?
Radio buttons are used to choose between different values for a single field or, in Angular's case, a single model. The logical solution would be to select the correct answer:
<input type="radio" ng-model="component.question.correctAnswer" ng-value="answer">
If you really need to set a flag you can easily achieve that with a watcher:
$scope.$watch('component.question.correctAnswer', function(correctAnswer) {
component.question.answers.forEach(function(answer) {
answer.is_correct = answer === correctAnswer ? true : false;
});
});

Radio Button check issue using knockout foreach

Iam running foreach loop above the radio button but unfortunately i could not check any of radio button.Here is my view
<div class="tab-pane" id="tab3">
<div class="form-body">
<div class="row">
<div class="col-md-12">
<h3 class="form-section">Qualification Factor</h3>
<div class="row" data-bind="foreach: leadqualificlist">
//Here is my foreach loop
<div class="col-md-6">
<div class="form-group">
<div class="radio-list radio-list-padding">
<label class="radio-inline">
<input type="radio" name="serious" value="0" data-bind="checked:Scoreschk, attr: { name: 'grp' + $data.Negativescore}" />
Negative
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Iam having list in leadqualificlist observable array.
Radio buttons behave differently than checkboxes, see documentation:
For radio buttons, KO will set the element to be checked if and only if the parameter value equals the radio button node’s value attribute or the value specified by the checkedValue parameter. <...> When the user changes which radio button is selected, KO will set your model property to equal the value of the selected radio button.
So, having that said, you cannot set different names for your checkboxex (using attr binding), but should set value in binding, like this:
...
<input type="radio" name="serious" data-bind="value: Scoreschk, checked:$parent.selectedScoreCheck" />
...
Now your view model should look like this:
function ViewModel() {
var self = this;
self.leadqualificlist = ko.observableArray([new Qualification(0, 5),
new Qualification(1, 2),
new Qualification(2, 1)]);
self.selectedScoreCheck = ko.observable("2"); // Note here must be string!
}
Where Qualification is:
function Qualification(scoreCheck, negativeScore) {
this.Scoreschk = scoreCheck;
this.Negativescore = negativeScore;
}
See demo.

Categories