Reputation: 2637
I have Angular-12 dynamic FormArray:
import {
Component,
OnInit,
VERSION
} from '@angular/core';
import {
FormArray,
FormBuilder,
FormGroup,
Validators
} from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
contactInfoForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.updateContact();
}
get contacts() {
return this.contactInfoForm.controls['contacts'] as FormArray;
}
getFormGroup(index: number): FormGroup {
return this.contacts.at(index) as FormGroup;
}
updateContact() {
this.contactInfoForm = this.fb.group({
id: [''],
current_residential_address: [
'', [
Validators.required,
Validators.minLength(2),
Validators.maxLength(500)
]
],
contacts: this.fb.array([this.addContactFormGroup()])
});
}
addContactFormGroup(): FormGroup {
return this.fb.group({
phone_type_id: ['', Validators.required],
phone_number: ['', [Validators.required, Validators.maxLength(15)]],
is_primary_contact_number: ['']
});
}
public addContactButtonClick() {
const contacts = this.contactInfoForm.get('contacts') as FormArray
contacts.push(this.addContactFormGroup())
}
get fc() {
return this.contactInfoForm.controls;
}
}
<form [formGroup]="contactInfoForm">
<div class="row">
<div class="col-12 col-md-12">
<div class="form-group">
<label for="current_residential_address">Current Residential Address:<span style="color:red;">*</span></label>
<textarea rows="2" formControlName="current_residential_address" name="description" type="text" placeholder="22, Alexander Close ..." class="form-control mb-3" required>
</textarea>
</div>
<div *ngIf="fc.current_residential_address.touched && fc.current_residential_address.invalid">
<div *ngIf="fc.current_residential_address.hasError('required')">
<div class="text-danger">
Current Residential Address is required!
</div>
</div>
<div *ngIf="fc.current_residential_address.hasError('minlength')">
<div class="text-danger">
Current Residential Address cannot be less than 2 characters!
</div>
</div>
<div *ngIf="fc.current_residential_address.hasError('maxlength')">
<div class="text-danger">
Current Residential Address cannot be more than 500 characters!
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div formArrayName="contacts" class="col-md-12" *ngFor="let contact of contacts.controls; let i = index">
<div [formGroupName]="i" class="row">
<div class="col-12 col-md-4">
<div class="form-group">
<label for="phone_number">Phone Number:<span style="color:red;">*</span></label>
<div class="input-group mb-4">
<input type="text" formControlName="phone_number">
</div>
</div>
<div *ngIf="getFormGroup(i).get('phone_number').touched && getFormGroup(i).get('phone_number').invalid">
<div *ngIf="getFormGroup(i).get('phone_number').hasError('required')">
<div class="text-danger">
Phone Number is required!
</div>
</div>
<div *ngIf="getFormGroup(i).get('phone_number').hasError('validatePhoneNumber')">
<div class="text-danger">
Invalid Phone Number!
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4">
<div class="form-group">
<label for="phone_type_id">Phone Type:<span style="color:red;">*</span></label>
<input type="text" formControlName="phone_type_id">
</div>
<div *ngIf="getFormGroup(i).get('phone_type_id').touched && getFormGroup(i).get('phone_type_id').invalid">
<div *ngIf="getFormGroup(i).get('phone_type_id').hasError('required')">
<div class="text-danger">
Phone Type is required!
</div>
</div>
</div>
</div>
<div class="col-12 col-md-2">
<div class="form-group">
<label for="is_primary_contact_number">Is Primary Line?:</label><br>
<input type="checkbox" class="form-check-input" id="exampleCheck2">
</div>
</div>
<div class="col-12 col-md-2">
<div class="form-group">
<button type="button" class="btn btn-danger float-right"><i class="fas fa-minus"></i> Remove</button>
</div>
</div>
</div>
<button type="button" class="btn btn-primary float-right" (click)="addContactButtonClick()" matTooltip="Add"><i class="fas fa-plus"></i> Add item</button>
</div>
</div>
{{ "Is Form Valid : "+contactInfoForm.valid}}
</form>
A user can only have one primary line. So in the FormArray, I want the user to be able to check only one of the checkboxes for is_primary_contact_number
to only be selected or checked once.
How do I achieve this?
Thanks.
Upvotes: 0
Views: 1589
Reputation: 51135
(change)
event with onIsPrimaryContactChecked(i)
by parsing the FormArray
index.onIsPrimaryContactChecked
method, iterate with this.contacts
FormArray, skip current checkbox index, otherwise set the remaining checkboxes to false
.app.component.html
<input type="checkbox" class="form-check-input" id="exampleCheck2" formControlName="is_primary_contact_number" (change)="onIsPrimaryContactChecked(i)">
app.component.ts
onIsPrimaryContactChecked(index: number) {
for (let i = 0; i < this.contacts.length; i++) {
if (i == index) continue;
this.getFormGroup(i)
.get('is_primary_contact_number')
?.setValue(false);
}
}
Upvotes: 1
Reputation: 353
import {Component, HostListener, OnDestroy, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {Subscription} from 'rxjs';
import {IQuery} from '../../../../shared/interfaces/query.interface';
import {LocationChangeListener} from "@angular/common";
import {faAsterisk} from "@fortawesome/free-solid-svg-icons";
import {IGroupPermission} from "../group.permission.interface";
import {GroupPermissionService} from "../group.permission.service";
import {GroupPermission} from "../group.permission.model";
import {IGroup} from "../../group/group.interface";
import {IPermission} from "../../permission/permission.interface";
import {GroupService} from "../../group/group.service";
import {PermissionService} from "../../permission/permission.service";
@Component({
selector: 'app-permission-group-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.scss']
})
export class EditComponent implements OnInit, OnDestroy {
faIcon = {faAsterisk};
formGroup!: FormGroup;
submitted: boolean;
editId: number;
subscription: Subscription[];
permissionGroupDetail!: IGroupPermission;
groupRows!: IGroup;
permissionRows!: IPermission;
isGet: boolean;
isPut: boolean;
isPost: boolean;
isDelete: boolean;
isCheck: boolean;
@HostListener('window:popstate', ['$event'])
onPopState(event: LocationChangeListener): void {
let params: IQuery = {};
this.subscription.push(this.permissionGroupService.getQueryArgumentObservable().subscribe((qParams: IQuery) => {
params = qParams;
}));
this.permissionGroupService.setQueryArgument(params);
this.router.navigate(['./admin/group-permission/list'], {
queryParams: params,
});
}
constructor(private formBuilder: FormBuilder,
private permissionGroupService: GroupPermissionService,
private aRoute: ActivatedRoute,
private router: Router,
private groupService: GroupService,
private permissionService: PermissionService,
) {
this.submitted = false;
this.editId = 0;
this.isDelete = false;
this.isGet = false;
this.isPost = false;
this.isPut = false;
this.isCheck = false;
this.subscription = [];
}
ngOnInit(): void {
this.formGroup = this.formBuilder.group({
permissionId: new FormControl('', [
Validators.required,
Validators.maxLength(255)
]),
groupId: new FormControl('', [
Validators.required,
Validators.maxLength(255)
]),
actions: this.formBuilder.array([], [])
});
this.subscription.push(this.aRoute.params.pipe().subscribe((params: Params) => {
this.editId = +params.id;
}));
this.groupService.query();
this.subscription.push(
this.groupService.getDataObservable().subscribe((groups: IGroup) => {
this.groupRows = groups;
})
);
this.permissionService.query();
this.subscription.push(
this.permissionService.getDataObservable().subscribe((permision: IPermission) => {
this.permissionRows = permision;
})
);
this.permissionGroupService.query(this.editId);
this.subscription.push(this.permissionGroupService.getDataObservable().subscribe((permission: IGroupPermission) => {
this.permissionGroupDetail = permission;
this.formGroup.controls.groupId.setValue(permission.data![0].groupId);
this.formGroup.controls.permissionId.setValue(permission.data![0].permissionId);
}));
this.permissionGroupDetail.data![0].actions.split("-").forEach(value => {
if (value === "get")
this.isGet = true;
else if (value === "post")
this.isPost = true;
else if (value === "put")
this.isPut = true;
else if (value === "delete")
this.isDelete = true;
});
}
onSubmit(): void {
if (this.formGroup.invalid) {
return;
}
this.submitted = true;
const actions: FormArray = this.formGroup.get('actions') as FormArray;
let combineAction = '';
actions.controls.forEach(ctl => combineAction += ctl.value);
const permissionGroup = new GroupPermission({
id: this.editId,
groupId: this.formGroup.value.groupId,
permissionId: this.formGroup.value.permissionId,
actions: combineAction,
});
this.permissionGroupService.clearAlert();
this.permissionGroupService.update(permissionGroup);
}
ngOnDestroy(): void {
this.subscription.forEach(sub => sub.unsubscribe());
this.permissionGroupService.unsubscribe();
}
onCheckboxChange(e: any) {
const actions: FormArray = this.formGroup.get('actions') as FormArray;
if (!this.isCheck) {
this.isCheck = true;
const actBox = this.permissionGroupDetail.data![0].actions.split("-");
actBox.forEach(value => {
if (value)
actions.push(new FormControl("-" + value));
});
}
if (e.target.checked) {
const index = actions.controls.findIndex(x => x.value === e.target.value);
if (index == -1)
actions.push(new FormControl(e.target.value));
} else {
const index = actions.controls.findIndex(x => x.value === e.target.value);
actions.removeAt(index);
}
}
}
<form novalidate (ngSubmit)="onSubmit()" [formGroup]="formGroup">
<div class="form-group">
<app-alert></app-alert>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">{{ 'filed.group' | translate }}</div>
<select
id="groupId"
name="groupId"
class="form-control"
formControlName="groupId"
required
[ngClass]="{ 'is-invalid': formGroup.controls.groupId.invalid && formGroup.controls.groupId.touched }"
>
<option disabled selected value>{{ 'common.selectInputMessage' | translate }}</option>
<option *ngFor="let group of this. permissionRows?.data; let i=index" value="{{group.id}}">{{group.name}}</option>
</select>
<div class="input-group-addon">
<fa-icon [icon]="faIcon.faAsterisk" ></fa-icon>
</div>
<div
*ngIf=" !submitted &&formGroup.controls.groupId.invalid ||formGroup.controls.groupId.touched"
class="invalid-feedback">
<div *ngIf="formGroup.controls.groupId.hasError('required')" class="pull-right"> {{ 'common.required' | translate }}
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">{{ 'filed.permissionId' | translate }}</div>
<select
id="permissionId"
name="permissionId"
class="form-control"
formControlName="permissionId"
required
[ngClass]="{ 'is-invalid': formGroup.controls.permissionId.invalid && formGroup.controls.permissionId.touched }"
>
<option disabled selected value>{{ 'common.selectInputMessage' | translate }}</option>
<option *ngFor="let group of this.groupRows?.data; let i=index" value="{{group.id}}">{{group.name}}</option>
</select>
<div class="input-group-addon">
<fa-icon [icon]="faIcon.faAsterisk" ></fa-icon>
</div>
<div
*ngIf=" !submitted &&formGroup.controls.permissionId.invalid ||formGroup.controls.permissionId.touched"
class="invalid-feedback">
<div *ngIf="formGroup.controls.permissionId.hasError('required')" class="pull-right"> {{ 'common.required' | translate }}
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">{{ 'filed.actions' | translate }}</div>
<div class="form-control form-check-inline form-check" style="border: none">
<!-- <label *ngFor="let act of this.actionsArray; let i = index"-->
<!-- for="inline-checkbox1"-->
<!-- class="switch switch-text switch-primary switch-pill m-r-10 m-l-20">-->
<!-- <input-->
<!-- (change)="onCheckboxChange($event)"-->
<!-- type="checkbox"-->
<!-- id="inline-checkbox1"-->
<!-- value="{{act.value}}"-->
<!-- class="form-check-input witch-input">{{ act.name}}-->
<!-- </label>-->
<label style=" transform: scale(1)" class="switch switch-text switch-primary switch-pill lg m-r-10 m-l-20">
<input value="-get" (change)="onCheckboxChange($event)" type="checkbox" class="switch-input " [checked]="isGet" >
<span data-on="Get" data-off="Get" class="switch-label"></span>
<span class="switch-handle"></span>
</label>
<label style=" transform: scale(1)" class="switch switch-text switch-success switch-pill m-r-5 m-l-5">
<input value="-post" (change)="onCheckboxChange($event)" type="checkbox" class="switch-input" [checked]="isPost" >
<span data-on="Pst" data-off="Pst" class="switch-label"></span>
<span class="switch-handle"></span>
</label>
<label style=" transform: scale(1)" class="switch switch-text switch-warning switch-pill m-r-5 m-l-5">
<input value="-put" (change)="onCheckboxChange($event)" type="checkbox" class="switch-input" [checked]="isPut" >
<span data-on="Put" data-off="Put" class="switch-label"></span>
<span class="switch-handle"></span>
</label>
<label style=" transform: scale(1)" class="switch switch-text switch-danger switch-pill m-l-5">
<input value="-delete" (change)="onCheckboxChange($event)" type="checkbox" class="switch-input" [checked]="isDelete" >
<span style="font-size: 10px !important;" data-on="Del" data-off="Del" class="switch-label"></span>
<span class="switch-handle"></span>
</label>
</div>
<div class="input-group-addon">
<fa-icon [icon]="faIcon.faAsterisk"></fa-icon>
</div>
</div>
</div>
<div class="form-actions form-group ">
<button [disabled]="formGroup.invalid" type="submit" class="btn btn-primary btn-sm">{{ 'common.submit' | translate }}</button>
</div>
</form>
Upvotes: 0