Angular 7: patching value of radio button Form Control does not update UI - css

I am using a HTML template in Angular 7 that consists of a number of radio buttons, each with an associated label - this is associated with a FormGroup object. Clicking on the label should change the state of the radio button to be selected and update the value of the associated FormControl. This works, the problem I have is setting a particular radio button to be selected when the UI loads, or using patchValue - the state of the formGroup is correct when the template is loaded, but the UI does not reflect that a particular radioButton has been selected.
Here's code that shows the problem:
export class AppComponent {
frequencyMinutesOptions: number[] = [1, 2, 5, 10, 60];
myForm: FormGroup;
constructor() {
}
ngOnInit() {
this.myForm = new FormGroup({
frequencyMinutes: new FormControl(5,[])
});
this.myForm.patchValue({'frequencyMinutes':10})
}
}
The HTML template:
<form [formGroup]="myForm">
<ul>
<li *ngFor="let frequency of frequencyMinutesOptions">
<input id="asset-frequency-{{frequency}}" type="radio" value={{frequency}} formControlName="frequencyMinutes" />
<label for="asset-frequency-{{frequency}}"> {{frequency}} </label>
</li>
</ul>
</form>
Relevant CSS:
input {
display: none;
}
input:checked+label {
background-color: blue;
color: #ffffff;
}
You may see a working demo of this here:
https://stackblitz.com/edit/angular-of2ubt
(I know that I'm supposed to embed code examples within the Stackoverflow editor but I'm not sure how to do this with Angular 7 / typescript or if its even possible)

it's a type error. In your html form, the value="10" is interpreted as the string '10'.
You have to use
this.myForm.patchValue({'frequencyMinutes':'10'}) or (see [value])
<input id="asset-frequency-{{frequency}}" type="radio" [value]="frequency" formControlName="frequencyMinutes" />

Either use formGroupName or call external function to make default radio button as true.
<div class="container">
<form [formGroup]="myForm">
<ul>
<li *ngFor="let frequency of frequencyMinutesOptions">
<input id="asset-frequency-{{frequency}}" type="radio" value="{{frequency}}" formControlName="frequencyMinutes" [checked]="isDefaultSelection(frequency)" >
<label for="asset-frequency-{{frequency}}"> {{frequency}} </label>
</li>
</ul>
</form>
<div class="debug">{{myForm.value | json}}
</div>
</div>
export class AppComponent {
frequencyMinutesOptions: number[] = [1, 2, 5, 10, 60];
myForm: FormGroup;
constructor() {
}
ngOnInit() {
this.myForm = new FormGroup({
frequencyMinutes: new FormControl(5,[])
});
this.myForm.patchValue({'frequencyMinutes':10})
}
isDefaultSelection(frequency) {
return frequency == 10 ? true : false;
}
}
or simply use property-binding
<input id="asset-frequency-{{frequency}}" type="radio" [value]="frequency" formControlName="frequencyMinutes">

Related

how to get the name and value of the checked checkbox of child component from parent component in vue js?

Child Component
<template>
<ul>
<li class="dropdown">
<div>
<label class="form-control" ref="checkValue" v-for="(item, index) in list" :key="index">
<input type="checkbox" ref="checkUpdatedBox" :name="item.name" :value="item.name" #click="selectedFilteredArray(item)" />
{{ item.name }}
</label>
</div>
</li>
</ul>
</template>
Here I want the name(item.name) or value(item.name) of the checkbox from the child component. As the input box is rendered dynamically with for loop.
Parent Component
<template>
<ChildComponent ref="checkboxes"/>
</template>
<script>
import SideBar from '../layouts/SideBar.vue'
export default {
methods: {
updateFunction() {
const unCheckBoxes = this.$refs.checkboxes.$refs.checkUpdatedBox
const unCheckBoxes1 = this.$refs.checkboxes.$refs.checkValue
console.log('unCheckBoxes1 ', unCheckBoxes1.innerText)
console.log(unCheckBoxes.checked) // true
}
}
}
</script>
In parent component, I'm trying to access name and value of the checkbox with the help of $refs and yes I'm trying to get name and value of the checkbox from a function. I'm only getting to know that whether the checkbox is checked or not.
But i want to know that checked checkbox value(item.name) or name(item.name).
is there something I'm missing out?
or
Is there any other method to get the name or value?
You can slimily use JavaScript to get value of selected checkbox.
var checkedValue = [];
var inputElements = document.getElementsByClassName('checkbox');
for(var i=0; inputElements[i]; ++i){
if(inputElements[i].checked){
checkedValue.push({value:inputElements[i].value,name:inputElements[i].name});
}
}
console.log(checkedValue);

Populate a field with another field value in gravity forms

I currently have a simple gravity form on my Wordpress website that includes a radio button field with 3 options: (Single, Married, Exempt).
I am wanting to dynamically populate a separate hidden text field on the same form with the value "Exempt" if the user selects the option Exempt in the radio button field. If the user selects one of the other options (Single or Married), I would like the value in the text field to be NULL.
Has anyone done something similar to this before, and if so, could you assist me with the steps to accomplish this?
You would need to add the code to a custom JavaScript file. You can read up on enqueuing JavaScript files here. In your comment you only provide one ID for the radio inputs, but each input should have it's own unique ID. So assuming your only radio inputs on this form are those 3 inputs, you could also target by type(as I have done below). If you want to share the HTML of your form I can tailor the answer more to your specific scenario.
// Document ready function for Wordpress
jQuery(function($) {
$('form#25 input[type="radio"]').change(function(){
if (this.value === 'exempt') {
$('input#26').val(this.value);
} else {
$('input#26').val(null);
}
})
});
label {
display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="25">
<label>Single<input type="radio" name="marriage-status" value="single" /></label>
<label>Married<input type="radio" name="marriage-status" value="married" /></label>
<label>Exempt<input type="radio" name="marriage-status" value="exempt" /></label>
<!-- HIDDEN INPUT -->
<input id="26" type="text" />
</form>
It looks like your form only has radio inputs for "Filing Status," so you can do it like this:
// Document ready function for Wordpress
jQuery(function($) {
$('form#gform_25 input[type="radio"]').change(function(){
if (this.value === 'Exempt') {
$('input#input_25_24_valid').val(this.value);
} else {
$('input#input_25_24_valid').val(null);
}
})
});
ul {
padding-left:0;
}
li {
list-style-type:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="gform_25">
<li id="field_25_9" class="gfield gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible">
<label class="gfield_label">Filing Status<span class="gfield_required">*</span></label>
<div class="ginput_container ginput_container_radio">
<ul class="gfield_radio" id="input_25_9">
<li class="gchoice_25_9_0"><input name="input_9" type="radio" value="Single or Married filing sperately" id="choice_25_9_0"><label for="choice_25_9_0" id="label_25_9_0">Single or Married filing sperately</label></li>
<li class="gchoice_25_9_1"><input name="input_9" type="radio" value="Married filing jointly" id="choice_25_9_1"><label for="choice_25_9_1" id="label_25_9_1">Married filing jointly (or Qualifying widow(er))</label></li>
<li class="gchoice_25_9_2"><input name="input_9" type="radio" value="Head of household" id="choice_25_9_2"><label for="choice_25_9_2" id="label_25_9_2">Head of household (Check only if you're unmarried and pay more than half the costs of keeping up a home for yourself and a qualifying individual.)</label></li>
<li class="gchoice_25_9_3"><input name="input_9" type="radio" value="Exempt" id="choice_25_9_3"><label for="choice_25_9_3" id="label_25_9_3">Exempt</label></li>
</ul>
</div>
</li>
<!-- Your hidden input -->
<input type="text" class="gform_hidden" name="input_25_24_valid" id="input_25_24_valid">
</form>

Angular 6 - change checkbox style whether is checked

I have a list of checkbox and I want to underline the one that is checked. My code looks like the following:
TS file:
currentQuarter: string;
quarters: Observable<MeseRiferimento[]>;
q1: MeseRiferimento = new MeseRiferimento();
q2: MeseRiferimento = new MeseRiferimento();
ngOnInit() {
q1.desc = "One";
q1.id = "1";
q2.desc = "Two";
q2.id = "2"
currentQuarter = q1.id;
quarters.of([q1, q2]);
}
isQuarterSelected(q: MeseRiferimento): boolean {
return this.currentQuarter === this.getKeyFromQuarter(q);
}
HTML file:
<div *ngFor="let q of quarters | async" class="col-1 my-auto m-stati">
<label class="custom-control custom-checkbox ra-check">
<input type="checkbox" class="custom-control-input" [ngClass]="{'checked': isQuarterSelected(q) }">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">{{q.descrizione}}</span>
</label>
</div>
CSS file:
.custom-control-input:checked~.custom-control-indicator {
color: #fff;
background-color: #3bb8eb;
}
These are the issue with this code:
1. when I load the page, the default checked checkbox has correctly the class 'checked' but the CSS is not applied, i.e. it's not underlined
2. when I manually select a checkbox the class 'checked' correctly applies and the CSS too applies
3. when I manually select another checkbox, the class 'checked' correctly switches from one to the other, but the CSS of the former do not update, i.e. the previous checkbox remains underlined
Thanks for any advice.
.custom-control-input:checked~.custom-control-indicator
:checked doesn't mean that it has the checked class, but it means that it's actually checked. If you want to select the checked class, use a dot in place of a colon:
.custom-control-input.checked~.custom-control-indicator

How to dynamically set 'was-validated' class on form to show validation feedback messages with angular 5 after submit

I am using a template based form in angular. I also use bootstrap (v4) and I wish to show some validation messages when the form was submitted.
This is my form:
<form [ngClass]="{'was-validated': wasValidated}">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name" class="form-control" [(ngModel)]="category.name" #name="ngModel" required maxlength="100"/>
<div *ngIf="name.invalid" class="invalid-feedback">
<div *ngIf="name.errors.required">
Name is required.
</div>
</div>
</div>
<button type="submit" class="btn btn-success" (click)="save()">Save</button>
</form>
My component looks as follows:
category: Category;
wasValidated: boolean = false;
ngOnInit() {
this.reset();
}
save() {
this.wasValidated = true;
this.categoriesService.createCategory(this.category).subscribe(
() => {
this.notificationService.add(notifications.category_saved, {name: this.category.name});
this.reset();
},
() => this.notificationService.add(notifications.save_category_failed)
);
}
reset() {
this.wasValidated = false;
this.category = {} as Category;
}
This works, but I have a feeling it's overly complex and more like a workaround rather than the right way. What is the best way to accomplish this?
Note: the class was-validated must be present on the form element in order to show the div with class invalid-feedback. I'm using this: https://getbootstrap.com/docs/4.0/components/forms/#validation
Note 2: I have currently no mechanism yet to prevent form submission on error. I'd like to know a good solution for that as well!
With the answer from #Chellappan V I was able to construct the solution I wanted.
I have applied to following changes:
First added #form="ngForm" to the form tag in the template. Secondly I changed the ngClass expression to reference the submitted state of the form, rather than referring to a boolean which was set to true manually when form was submitted. Last but not least I pass the form in the submit method on the save button.
<form novalidate #form="ngForm" [ngClass]="{'was-validated': form.submitted}">
<!-- form controls -->
<button type="submit" class="btn btn-success" (click)="submit(form)">Save</button>
</form>
In the component I injected the template variable in the component with #ViewChild.
#ViewChild("form")
private form: NgForm;
The submit method now takes a form parameter of type NgForm which is used to check if the form was valid before sending a request to the backend:
submit(form: NgForm) {
if (form.valid) {
this.categoriesService.createCategory(this.category).subscribe(
() => {
this.notificationService.add(notifications.category_saved, {name: this.category.name});
this.reset();
},
() => this.notificationService.add(notifications.save_category_failed)
);
} else {
this.notificationService.add(notifications.validation_errors);
}
}
Finally the reset method resets the form and the model so it can be re-entered to submit a next instance:
reset() {
this.form.resetForm();
this.category = {} as NewCategoryDto;
}

Get user input from textarea

I'm new to angular2. I want to store user input from a text area in a variable in my component so I can apply some logic to this input. I tried ngModel but it doesn't work. My code for the textarea:
<textarea cols="30" rows="4" [(ngModel)] = "str"></textarea>
And inside my component:
str: string;
//some logic on str
But I don't get any value in str inside my component. Is there an error with the way I'm using ngModule ?
<pre>
<input type="text" #titleInput>
<button type="submit" (click) = 'addTodo(titleInput.value)'>Add</button>
</pre>
{
addTodo(title:string) {
console.log(title);
}
}
I think you should not use spaces between the [(ngModel)] the = and the str. Then you should use a button or something like this with a click function and in this function you can use the values of your inputfields.
<input id="str" [(ngModel)]="str"/>
<button (click)="sendValues()">Send</button>
and in your component file
str: string;
sendValues(): void {
//do sth with the str e.g. console.log(this.str);
}
Hope I can help you.
Tested with Angular2 RC2
I tried a code-snippet similar to yours and it works for me ;)
see [(ngModel)] = "str" in my template
If you push the button, the console logs the current content of the textarea-field. Hope it helps
textarea-component.ts
import {Component} from '#angular/core';
#Component({
selector: 'textarea-comp',
template: `
<textarea cols="30" rows="4" [(ngModel)] = "str"></textarea>
<p><button (click)="pushMe()">pushMeToLog</button></p>
`
})
export class TextAreaComponent {
str: string;
pushMe() {
console.log( "TextAreaComponent::str: " + this.str);
}
}
Just in case, instead of [(ngModel)] you can use (input) (is fired when a user writes something in the input <textarea>) or (blur) (is fired when a user leaves the input <textarea>) event,
<textarea cols="30" rows="4" (input)="str = $event.target.value"></textarea>
Here is full component example
import { Component } from '#angular/core';
#Component({
selector: 'app-text-box',
template: `
<h1>Text ({{textValue}})</h1>
<input #textbox type="text" [(ngModel)]="textValue" required>
<button (click)="logText(textbox.value)">Update Log</button>
<button (click)="textValue=''">Clear</button>
<h2>Template Reference Variable</h2>
Type: '{{textbox.type}}', required: '{{textbox.hasAttribute('required')}}',
upper: '{{textbox.value.toUpperCase()}}'
<h2>Log <button (click)="log=''">Clear</button></h2>
<pre>{{log}}</pre>`
})
export class TextComponent {
textValue = 'initial value';
log = '';
logText(value: string): void {
this.log += `Text changed to '${value}'\n`;
}
}
Remove the spaces around your =:
<div>
<input type="text" [(ngModel)]="str" name="str">
</div>
But you need to have the variable named str on back-end, than its should work fine.
If ngModel is used within a form tag, either the name attribute must be set or the form.
control must be defined as 'standalone' in ngModelOptions.
use either of these two:
<textarea [(ngModel)]="person.firstName" name="first"></textarea>
<textarea [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}"></textarea>
it worked for me.

Resources