Unable to populate tick mark on angular checkbox - javascript

I have angular code something like this: and I want to populate checkbox ticked for the option which are default selected
export class InformationComponent implements OnInit{
dataIds: FormControl;
#Input()
requestBody:Request;
requestForm: FormGroup;
constructor(private _formBuilder: FormBuilder){}
ngOnInit(){
this.dataIds = new FormControl(this.requestBody.dataIds);
this.requestForm = this._formBuilder.group({
dataIds: this.dataIds;
})
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<form [formGroup]="reqForm" #mainForm>
<div>
<app-data-list [dataIds]="dataIds" [disabled]="disabled"> </app-data-list>
</div>
</form>
and below is my app-data-list component
export class EntityListComponent implemments OnInit, OnDestroy{
#Input()
public disabled:boolean;
public entitiesFilter:FormControl = new FormControl();
protected entityList = new RequestEntity[];
#Input()
public dataIds:FormControl;
#ViewChild('multiSelect', {static:true}) multiselect:MatSelect;
protected _onDestroy = new Subject<void>();
public filteredEntityList:ReplaySubject<RequestEntity[]> = new ReplaySubject<RequestEntity[]>
ngOnInit(){
this.myservice.getData().subscribe((resp:RequestEntity[])=>{
entityList = resp;
})
this.filteredEntityList.next(this.entityList.slice());
this.entitiesFilter.valueChanges.pipe(takeUntil(this._onDestroy)).subscribe(() => { this.filterEntitiesList();});
}
ngAfterViewInit(){
this.setInitialValue();
}
setInitialValue(){
this.filteredEntitiesList.pipe(take(1), takeUntil(_onDestroy)).subscribe(() => {
this.multiSelect.compareWith =(a:RequestEntity, b:RequestEntity) => a && b && a.entity == b.entity;
})
}
}
<div [formGroup]="form">
<mat-form-field>
<mat-label> Data ids</mat-label>
<mat-select [formControl]="dataIds" [multiple]="true" #multiSelect [disabled]="disabled">
<ngx-mat-select-search [formControl]="entitiesFilter" placeholderLabel="Search">
</ngx-mat-select-search>
<mat-option *ngFor="let entity of filterdEntitiesList |async" [value]"entity"> {{entity?.entity?.entityName}} </mat-option>
</mat-select>
</mat-form-field>
</div>
but my code is not pre populating the checked option against selected dataIds from back end but I had similar snippet in my code which does exactly same thing

Related

how do i pass a date from appcomponent .ts to dialog?

I'm trying to create a seat reservation application with datepicker. initially all the messages are seen on an alert, but I decided to move them to the dialogs.
as you know better than me to create the dialog you have to create a new component. the problem is that, I can't pass the date that is captured in the first component inside a method that formats the date.
how can I do?
I am attaching the relevant codes
appcomponent.html:
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Prenota</mat-label>
<input matInput [matDatepicker]="picker" [(ngModel)]="this.datari.myFormattedDates" (dateChange)="openDialog($event)">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker [dateClass]="dateClass()" #picker> </mat-datepicker>
</mat-form-field>
appcomponent.ts:
export class AppComponent implements OnInit {
dateOfBirth = Date();
pipe = new DatePipe('it-IT');
currentDate = moment().format('DD/MM/YYYY');
datari: MyConst = new MyConst();
openDialog(event) {
//catch date
this.dateOfBirth = event.value;
//I format the date
this.datari.myFormattedDates = this.pipe.transform(this.dateOfBirth, 'dd/MM/yyyy');
// open dialog
this.dialog.open(DialogComponent );
}
dialogcomponent.ts:
export class DialogComponent implements OnInit {
dialogTitle = 'Parking';
dialogMessage = 'do you want to book for' + '?' ;
constructor(public dialog: MatDialog, public dialogRef: MatDialogRef<DialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit() {
}
}
dialogcomponent.html:
<h3 mat-dialog-title>{{dialogTitle}}</h3>
<div mat-dialog-content>
{{dialogMessage}}
</div>
<div style="float:right;margin:20px;">
<input style="margin:0px 10px;" type="button" value="confirm" [mat-dialog-close]="true">
<input type="button" value="cancel" [mat-dialog-close]="false">
</div>
thanks a lot to everyone :)
You will be able to pass data through the open method like this :
this.dialog.open(DialogComponent, {
data: { date: this.datari.myFormattedDates },
// Others options
// width: ...
// height: ...
// panelClass: ...
});
And in your dialog component :
constructor(public dialog: MatDialog, public dialogRef: MatDialogRef<DialogComponent>, #Inject(MAT_DIALOG_DATA) public data: { data: any }) { }
ngOnInit() {
console.log(this.data.date);
}
Take a look at https://material.angular.io/components/dialog/overview

How to Clear the ngModel value coming from other component?

I have a component in which [(ngModel)]=attrProps._value is getting set on user input and also getting value when already present by default.
Now there is a button which leads to a toggle button for value option when the user wants to have custom value.
But when the user clicks on the refresh button the value in the input field should get clear?
#Component({
selector: 'n-customValue',
template: `
<mat-form-field class="inputfield-attr-view">
<input matInput [(ngModel)]="attrProps._value" placeholder="{{bKeeperService.getAttributeType(attrProps).displayAs}}">
<mat-icon matSuffix (click)="revertIcon()" class="editButton">
<img class="attributeview-button" src="../../assets/icons/refresh.svg">
</mat-icon>
</mat-form-field>
`
})
export class customValueComponent implements OnInit {
#Output() clickEvent: EventEmitter<string> = new EventEmitter<string>();
constructor(public myservice: customService) { }
ngOnInit(): void { }
revertIcon() {
this.clickEvent.emit('REVERT_EVENT');
}
}
I tried using element ref but could not solve it.
#Component({
selector: 'n-customvalue',
template: `
<mat-form-field class="inputfield-attr-view">
<input matInput [(ngModel)]="attrProps._value" #searchInput placeholder="{{bKeeperService.getAttributeType(attrProps).displayAs}}">
<mat-icon matSuffix (click)="revertIcon()" class="editButton">
<img class="attributeview-button" src="../../assets/icons/refresh.svg">
</mat-icon>
</mat-form-field>
`
})
export class customvalueComponent implements OnInit {
#Output() clickEvent: EventEmitter<string> = new EventEmitter<string>();
#Input('nAttrProps') nAttrProps;
#ViewChild('searchInput') searchInput: ElementRef;
attrPropsValue;
constructor(public myservice: customService) { }
ngOnInit(): void { }
revertIcon() {
this.clickEvent.emit('REVERT_EVENT');
this.searchInput.nativeElement.value = '';
}
}

Input Material Chips -- Init Form Array

I want to init my mat chips input with input data but when I have two chips, it forms only one form :
*.component.ts
#Component({
selector: 'app-pps-dialog',
templateUrl: './pps-dialog.component.html',
})
export class PPSDialogComponent implements OnInit {
patientid: string;
ppsForm: FormGroup;
ppssToDisplay;
visible: boolean = true;
selectable: boolean = true;
removable: boolean = true;
addOnBlur: boolean = true;
// Enter, comma
separatorKeysCodes = [ENTER, COMMA];
constructor(
private route: ActivatedRoute,
private ppssService:PPSsService,
private _changeDetectorRef: ChangeDetectorRef,
private location: Location,
private router: Router,
public dialog: MatDialog,
private formBuilder: FormBuilder,
public dialogRef: MatDialogRef<PPSDialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: any)
{ this.initForm(); }
ngOnInit(): void {
this.ppssToDisplay = this.ppssService.getSinglePPS(this.key)
.subscribe(res => {
this.ppssToDisplay = res;
this.ppsForm.controls['requirements'].setValue(Array(this.ppssToDisplay.effetsind));
console.log(this.ppssToDisplay.effetsind));
});
add(event: MatChipInputEvent): void {
let input = event.input;
let value = event.value;
// Add our requirement
if ((value || '').trim()) {
this.requirements = this.ppsForm.get('requirements') as FormArray;
this.requirements.push(this.formBuilder.control(value.trim()));
}
// Reset the input value
if (input) {
input.value = '';
}
}
remove(index: number): void {
const requirements = this.ppsForm.get('requirements') as FormArray;
if (index >= 0) {
requirements.removeAt(index);
}
}
initForm(): void {
this.ppsForm = this.formBuilder.group({
requirements: this.formBuilder.array(['']),
// I don't know why, but I must init my form with empty chips if I want to receive data from service.
});
}
get formData() {
return <FormArray>this.ppsForm.get('requirements');
}
*ppss.service
import { Injectable } from '#angular/core';
import { Patient } from '../models/patient.model';
import { PPS } from '../models/pps.model';
import { AngularFireDatabase, AngularFireList, AngularFireObject} from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import {switchMap, map} from 'rxjs/operators';
import * as firebase from 'firebase';
import DataSnapshot = firebase.database.DataSnapshot;
#Injectable({
providedIn: 'root'
})
export class PPSsService {
ppss: AngularFireList<any>;
constructor(private database: AngularFireDatabase) {this.ppss = database.list('ppss');}
getSinglePPS(key: string){
return this.database.object('ppss/' + key).valueChanges();
}
}
console.log(this.ppssToDisplay.effetsind):
(2) ["Troubles de la vessie", "Troubles de l'érection"]
I've used the example of Angular Material:
*.component.html
<mat-form-field style="width:50%" appearance="outline">
<mat-label>Description du traitement</mat-label>
<textarea matInput formControlName="description"></textarea>
</mat-form-field>
<mat-form-field style="width:50%" appearance="outline">
<mat-label>Effets indésirables du traitement</mat-label>
<mat-chip-list #chipList>
<mat-chip *ngFor="let requirement of formData.controls; let i = index;" [selectable]="selectable"
[removable]="removable" (removed)="remove(i)">
{{requirement.value}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input placeholder="Nouvel effet indésirable..."
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)"/>
</mat-chip-list>
</mat-form-field>
ERROR Error: Must supply a value for form control at index: 0:
> core.js:1598 ERROR Error: Must supply a value for form control at index: 0.
at forms.js:4304
at forms.js:4274
at Array.forEach (<anonymous>)
at FormArray.push../node_modules/#angular/forms/fesm5/forms.js.FormArray._forEachChild (forms.js:4274)
at FormArray.push../node_modules/#angular/forms/fesm5/forms.js.FormArray._checkAllValuesPresent (forms.js:4302)
at FormArray.push../node_modules/#angular/forms/fesm5/forms.js.FormArray.setValu
I have the same problem if I init my form with :["Troubles de la vessie", "Troubles de l'érection",...]
Reactive FormArray are pretty tricky to use. Check this minimal and valid example:
import {Component, OnInit} from '#angular/core';
import {COMMA, ENTER} from '#angular/cdk/keycodes';
import {FormArray, FormBuilder, FormGroup} from '#angular/forms';
import {MatChipInputEvent} from '#angular/material';
#Component({
selector: 'app',
template: `
<mat-form-field [formGroup]="formData">
<mat-label>Effets indésirables du traitement</mat-label>
<mat-chip-list #chipList>
<mat-chip *ngFor="let requirement of formData.get('requirements').value; let i = index;"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(i)">
{{requirement}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input
placeholder="Nouvel effet indésirable..."
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)"/>
</mat-chip-list>
</mat-form-field>
`
})
export class AppComponent implements OnInit {
formData: FormGroup;
selectable = true;
removable = true;
addOnBlur = true;
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.initForm();
this.ppssToDisplay();
}
initForm(): void {
this.formData = this.formBuilder.group({
requirements: this.formBuilder.array([]),
})
}
ppssToDisplay() {
// Simulate your async call to ppssService
setTimeout(() => {
const control = <FormArray>this.formData.controls.requirements;
['Troubles de la vessie', 'Troubles de l\'érection'].map(x =>
control.push(this.formBuilder.control(x))
);
}, 300)
}
add(e: MatChipInputEvent) {
const input = e.input;
const value = e.value;
if ((value || '').trim()) {
const control = <FormArray>this.formData.controls.requirements;
control.push(this.formBuilder.control(value.trim()));
}
if (input) {
input.value = '';
}
}
remove(i: number) {
let control = <FormArray>this.formData.controls.requirements;
control.removeAt(i);
}
}

How to build Field Array withen Nested Array Fields in Angular Reactive Form?

I have a form That is responsible for Creating survey.
Each Survey has Questions and Each Question has options.
Survey can have many Questions.
Question can have Many options.
Therefore i need something like bellow screenshot.
Check this out. I am using FormGroupArray to create a dynamic Question / Option List.
// Component
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, FormArray } from '#angular/forms';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
public view: any;
surveyForm: FormGroup;
surveyQuestions: FormArray;
surveyOptions: any[] = [];
formData: string;
constructor(private formbuilder: FormBuilder) {
}
ngOnInit() {
this.surveyForm = this.formbuilder.group({
survey: this.formbuilder.array([this.createSurveyQuestion()])
});
}
createSurveyQuestion(): FormGroup {
return this.formbuilder.group({
question: [''],
options: this.formbuilder.array([this.createOption()])
});
}
createOption(): FormGroup {
return this.formbuilder.group({
option: ['']
});
}
addQuestion(): void {
this.surveyQuestions = this.surveyForm.get('survey') as FormArray;
this.surveyQuestions.push(this.createSurveyQuestion());
}
addOption(indx: number): void {
let questCtrl = <FormArray>this.surveyForm.get('survey');
let m = questCtrl.controls[indx];
let opts = m.get('options') as FormArray;
opts.push(this.createOption());
}
get getSurveyControls() {
return <FormArray>this.surveyForm.get('survey');
}
getQuestionOptionControls(questIndex: number){
let questCtrl = <FormArray>this.surveyForm.get('survey');
let m = questCtrl.controls[questIndex];
let opts = <FormArray>m.get('options');
return opts;
}
convertFormData() {
this.formData = JSON.stringify(this.surveyForm.value);
}
}
Template -
// Template
<form [formGroup]="surveyForm">
<button (click)="addQuestion()">Add Question</button>
<div formArrayName="survey" *ngFor="let quest of getSurveyControls.controls; index as i;" [attr.data-index]="i">
<div [formGroupName]="i">
<input formControlName="question" placeholder="Question"/>
<button (click)="addOption(i)">Add Option</button>
<div formArrayName="options" *ngFor="let opt of getQuestionOptionControls(i).controls; index as oidx;"[attr.data-index]="oidx">
<div [formGroupName]="oidx">
<input formControlName="option" placeholder="option"/>
</div>
</div>
</div>
</div>
</form>
<pre> {{surveyForm.value | json }}</pre>

Angular2: Bind form context to ngTemplateOutlet

I'm trying to define a Component containing a dynamic Form (using ReactiveForms) where the user should be able to add / delete Controls.
The Controls can take many forms, and has to be defined outside of the Component, so I think that TemplateRef is the most appropriate for this.
I'm struggling to find a way to bind the externally defined Control to the internal Form, through the use of formControlName
Here is a start of the implementation:
// expandable.component.ts
[...]
#Component({
selector: 'expandable',
templateUrl: 'app/component/common/expandable/expandable.component.html',
styleUrls: ['app/component/common/expandable/expandable.component.css']
})
export class ExpandableComponent {
#ContentChild('childTemplate') childTemplate: TemplateRef<any>;
#Input() children: Array<any>;
public form: FormGroup;
constructor(private _changeDetector: ChangeDetectorRef,
private _formBuilder: FormBuilder) {
this.children = [];
}
public ngOnInit(): void {
this.form = this._formBuilder.group({
children: this._formBuilder.array([])
});
const arrayControl = <FormArray>this.form.controls['children'];
this.children.forEach(child => {
const group = this.initChildForm();
arrayControl.push(group);
});
}
private initChildForm(): AbstractControl {
return this._formBuilder.group({
key: ['Initial Key', [Validators.required]],
value: ['Initial Value', [Validators.required]]
});
}
public addChild(): void {
const control = <FormArray>this.form.controls['children'];
control.push(this.initChildForm());
this._changeDetector.detectChanges();
}
}
-
<!-- expandable.component.html -->
<form [formGroup]="form">
<div class="form-group">
<div formArrayName="children">
<div *ngFor="let child of form.controls.children.controls; let i=index">
<div [formGroupName]="i">
<template
[ngTemplateOutlet]="childTemplate"
[ngOutletContext]="{ $implicit: child }"></template>
</div>
</div>
</div>
</div>
<a (click)="addChild()">Add Child</a>
</form>
Attempt to define the the template externally:
<expandable>
<template #childTemplate>
<input class="form-control"
formControlName="value" />
</template>
</expandable>
I'm naively trying to bind the formControlName to the implicitly passed context from the outter , but with no luck, as I'm getting "Cannot find control with name: 'value'". Ideally, I would like to be able to do the formControlName binding into the expandable.component.html instead, but I see no way of doing this either.
Any thoughts about this?
Yes, this is possible:
You need to implement the ControlValueAccessor interface which ngModel and formControlName inject, like so:
#Directive({
selector: 'control',
providers: [
{provide: NG_VALUE_ACCESSOR, multi: true, useExisting: SwitchControlComponent}
]
})
export class SwitchControlComponent implements ControlValueAccessor {
isOn: boolean;
_onChange: (value: any) => void;
writeValue(value: any) {
this.isOn = !!value;
}
registerOnChange(fn: (value: any) => void) {
this._onChange = fn;
}
registerOnTouched() {}
toggle(isOn: boolean) {
this.isOn = isOn;
this._onChange(isOn);
}
}
html:
<expandable>
<template #childTemplate>
<div [formGroup]="form">
<input control class="form-control"
formControlName="value" />
</template>
</div>
</expandable>
Further reading:
With new forms api, can't add inputs from child components without adding additional form tags

Categories