How to generate dynamic tab with data based on API in Angular8 - javascript

I have below JSON response.
From JSON response i am creating dynamic tab and inside every tab i want to push formArray based on below mentioned condition.
**In below response,
const myObj = [
{
'TabName': 'Test1',
'otherDetails': [
{
'processTechType': 'Continuous'
},
{
'processTechType': 'Batch',
},
]
},
{
'TabName': 'Test2',
'otherDetails': [
{
'processTechType': 'Batch'
}
]
}
];
For Ex - TabName Test1 and TabName Test2 are tabs name which i am displaying dynamically. Now in Test1 Tab, i want to push formArray Continuous and formArray Batch both forms. Because in Test1 Tab, i have processTechType array with Continuous and batch both. So it will show both form in Test1 Tab.
Ex - 2 -- Now in Test2 Tab, i want to push formArray Batch form only. Becuase in Test2 Tab, i have processTechType batch in otherDetails object. So it will show Batch form only in Test2 Tab.
My mean to say is everytime it will check the Tabname and otherDetails key from response and show forms based on processTechType array key on specific tab only.
I have below code. But it is pushing both forms in all tabs, not on specific tab. For ex - From my code, It is showing Continuous formArray onetime and Batch formArray two times in Test1 and Test2 tabs both.
Expected output -
In Test1 Tab, it will push one Continuous and one Batch form.
In Test2 Tab, It will show push batch form only.
Can anyone please help me get my code work to get my expected output.
getMakeLineData() {
var otherDetails = myObj.filter(m => m.otherDetails).map(m => m.otherDetails);
this.makeLineData = myObj;
if (otherDetails) {
otherDetails.forEach(element => {
for (var i of element) {
if (i.processTechType === 'Continuous') {
this.addQuantity();
}
else if (i.processTechType === 'Batch') {
this.addBatch();
}
}
});
}
}
createContinuousForm() {
return this.fb.group({
designProcess: ['', [Validators.required]]
});
}
createBatchForm() {
return this.fb.group({
avgBCT: ['', [Validators.required]]
});
}
continuousType(): FormArray {
return this.dataCollectionForm.get("continuousType") as FormArray;
}
batchType(): FormArray {
return this.dataCollectionForm.get("batchType") as FormArray;
}
addQuantity() {
this.continuousType().push(this.createContinuousForm());
}
addBatch() {
this.batchType().push(this.createBatchForm());
}
HTML Template
<div class="tabGroupDiv row">
<div class="lossLinesDiv">
<mat-tab-group class="lossMatGrpCls" mat-align-tabs="left">
<mat-tab *ngFor="let lineData of makeLineData">
<ng-template mat-tab-label>
<button class="validatorTabBgClr">{{lineData.makeLineName}}</button>
</ng-template>
<form [formGroup]="dataCollectionForm" (ngSubmit)="onSubmit()">
<!-- <--continuous Form start here -->
<div class="admin-console-main-wrapper" formArrayName="continuousType">
<div class="content-wrapper" *ngFor="let lineItem of continuousType().controls; let i=index"
[formGroupName]="i">
<div class="row list-wrapper">
<div class="col-xs-3 col-md-3 deo-dv-list-wrapper">
<h5 class="topbar-items-text">Design Process Capacity (Tonnes)</h5>
<mat-form-field appearance="outline">
<input matInput type="text" class="line-fte-input smed-input" placeholder="Design Process Capacity"
formControlName="designProcess">
</mat-form-field>
<mat-error *ngIf="lineItem?.controls?.designProcess?.hasError('required')">
Field is required
</mat-error>
</div>
</div>
</div>
</div>
<!-- <--continuous Form start here -->
<!-- <--Batch Form start here -->
<div class="admin-console-main-wrapper" formArrayName="batchType">
<div class="content-wrapper" *ngFor="let lineBatchItem of batchType().controls; let i=index"
[formGroupName]="i">
<div class="row list-wrapper">
<div class="col-xs-3 col-md-3 deo-dv-list-wrapper">
<h5 class="topbar-items-text">Average BCT (mins)</h5>
<mat-form-field appearance="outline">
<input matInput type="text" class="line-fte-input smed-input" placeholder="Average BCT"
formControlName="avgBCT">
</mat-form-field>
</div>
</div>
</div>
</div>
<!-- <--Batch Form ends here -->
</form>
</mat-tab>
</mat-tab-group>
</div>
</div>

Your object is complex to relationa tabs and FormArrays, So, imagine you has a more confortable object. Some like
[{tabName:'Tab 1',continuousType:0,batchType:0},
{tabName:'Tab 2',continuousType:1,batchType:-1}]
See that you use "-1" to indicate the tab has no a form of this type
For this create a function thah return this more confortable array
tabsConfig(obj:any){
const tab=[];
let continuousType=0;
let batchType=0;
obj.forEach((x,index)=>{
tab[index]={tabName:x.TabName,continuousType:-1,batchType:-1}
x.otherDetails.forEach(y=>{
if (y.processTechType=='Continuous')
tab[index].continuousType=continuousType++
if (y.processTechType=='Batch')
tab[index].batchType=batchType++
})
})
return tab
}
Now you can use a variable to store the config
this.tabs=this.tabConfig(this.myObj)
You can then
this.tabs.forEach(x=>{
if (x.continuousType!=-1)
this.continuousType.push(this.createContinuousForm())
if (x.batchType!=-1)
this.batchType.push(this.createBatchForm())
})
And, if you has two auxiliars forms that return the formGroup of the of the FormArrays
getContinuousForm(index:number){
return (this.dataCollectionForm.get("continuousType") as FormArray)
.at(index) as FormGroup
}
getBatchForm(index:number){
return (this.dataCollectionForm.get("batchType") as FormArray)
.at(index) as FormGroup
}
You're ready to create the mat-tab iterating over the "tabs" array
<mat-tab-group >
<mat-tab *ngFor="let tab of tabs;let i=index">
<ng-template mat-tab-label>
<button >{{tab.tabName}}</button>
</ng-template>
<form *ngIf="tab.continuousType!=-1
[formGroup]="getContinuousForm(tab.continuousType)">
....
</form>
<form *ngIf="tab.batchType!=-1
[formGroup]="getBatchForm(tab.batchType)">
....
</form>
</mat-tab>
</mat-tab-group>

Related

TypeError: Cannot read property '_rawValidators' of null after Ng build

I am new to angular. I am dynamically rendering some fields into my reactive form. Everything works great when I am using ng serve with a mock request (i.e. rendering happens properly, no error in the console.log). As soon as I build the project with ng build and use a proper backend, I get the error for each field I am rendering dynamically:
main.js:1 ERROR TypeError: Cannot read property '_rawValidators' of null
I couldn't find any background on this error. I would love to hear your thoughts.
more background
// these fields change with selection
this.datafields = [{
dfId: 48,
dfName: "Phone",
dfType: "text",
dfOptions: null,
dfValue: ""
},
{
dfId: 49,
dfName: "Eval",
dfType: "select",
dfOptions: ["","Remote","Live"],
df_value: "",
}]
typescript rendering in ngOnInit (tried ngAfterViewInit with no improvement)
dfGroup = new FormGroup({})
...
...
this.eyeForm = this.formBuilder.group({
focus: ['', Validators.required],
datafields: this.formBuilder.array([])
})
...
...
if (this.datafields != null || this.datafields != undefined) {
this.datafields.forEach((x:any) => {
this.dfGroup.setControl(x.dfName, new FormControl(x.dfValue));
});
this.getDataFields.push(this.dfGroup);
}
and HTML looks like the following:
<div [formGroup]="dfGroup">
<div class="row pt-2" *ngFor="let field of datafields; let i=index">
<div class="col-4 d-flex align-items-center 13required">
{{field.dfName}}
</div>
<div class="col-6">
<mat-form-field *ngIf="field.dfType == 'text'" appearance="outline">
<input
matInput
[type]="field.dfType"
[formControlName]="field.dfName"
required
/>
</mat-form-field>
<mat-form-field
*ngIf="field.dfType == 'select'"
appearance="outline"
>
<mat-select [formControlName]="field.dfName" placeholder="">
<mat-option
[value]="option"
*ngFor="let option of field.dfOptions"
>
{{ option }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
I ran in to this situation when I was mocking out my template and typo'd my formControlName attribute.
<mycomponent formControlName="bogusfieldSpelledWrong" ...>
Why Angular showed it as this error likely has something to do with how the component was initializing/changing the form.
it must be about formControlName. check out your form control names in ts file and html file.
for nested groups you can use formGroupName, then use formControlName.
this.yourForm = this.fb.group({
name: [''],
contact: this.fb.group({
address: ['']
})
})
<form [formGroup]="yourForm">
<input type="text" formControlName="name" />
<div formGroupName="contact">
<input type="text" formControlName="address" />
</div>
</form>
This is caused by malforming the form in the view.
It was caused by misordering formArrayName, the loop and formGroupName
The form (controller)
form = <FormGroup>this.fb.group({
hops: this.fb.array([
this.fb.group({...}),
...
])
});
The view (mistake)
<li class="asset" *ngFor="let control of hops.controls; let i = index;">
<div formArrayName="hops">
<div [formGroupName]="i">
The view (corrected)
<div formArrayName="hops">
<li class="asset" *ngFor="let control of hops.controls; let i = index;">
<div [formGroupName]="i">
In our application, we had a minifier that renamed class variable names (in this case, the name of form controls) as an optimisation. This made the issue only appear in our production environments (optimisations weren't performed during local development).
The solution was to directly reference the control instance instead of using a string, so that the variable referenced in the angular template was renamed consistently with the class local variable.
Before:
<div formGroupName="myInputGroup">
<div formControlName="myInput">...</div>
</div>
After:
<div [formGroup]="myInputGroup">
<div [formControl]="myInputGroup.controls.myInput">...</div>
</div>
another reason for this issue is when you forget to assign formGroup
wrong:
export class MyComponent{
formGroup: FormGroup;
...
}
correct:
export class MyComponent{
formGroup = new FormGroup({...});
...
}
I had a similar issue, you need to add an extra div with property [formGroupName]="i",
The final code would be,
<div [formGroup]="dfGroup">
<div class="row pt-2" *ngFor="let field of datafields; let i=index">
<div [formGroupName]="i">
<div class="col-4 d-flex align-items-center 13required">
{{field.dfName}}
</div>
<div class="col-6">
<mat-form-field *ngIf="field.dfType == 'text'" appearance="outline">
<input matInput [type]="field.dfType" [formControlName]="field.dfName" required />
</mat-form-field>
<mat-form-field *ngIf="field.dfType == 'select'" appearance="outline">
<mat-select [formControlName]="field.dfName" placeholder="">
<mat-option [value]="option" *ngFor="let option of field.dfOptions">
{{ option }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
</div>
This is resolved by adding formcontrolname value.
Type error gives you null because it didn't find value from your Component.
In your Html file formcontrolname must be the same as FormGroup value.
For example:
<formControlName = 'username'>
this.formGroupName = this.formBuilder.group({
username: ["", [Validators.required]],
})
})
//html page properties
formControlName="drugReproductive"
//ts file attributes
this.drugTypeTwo = new FormControl(0);
this.drugTypeThree = new FormControl(0);
this.drugTypeFour = new FormControl(0);
this.drugTypeFive = new FormControl(0);
this.drugWithCanisterForm = this.fb.group({
drugAntineoplastic:this.drugAntineoplastic,
drugNonAntineoplastic:this.drugNonAntineoplastic,
drugReproductive:this.drugReproductive,
drugTypeOne:this.drugTypeOne,
drugTypeTwo:this.drugTypeTwo,
drugTypeThree:this.drugTypeThree,
drugTypeFour:this.drugTypeFour,
drugTypeFive:this.drugTypeFive,
configuration: this.configuration,
deviceId:this.deviceId,
deviceTypeId: this.deviceTypeId,
isOtcExcluded: this.isOtcExcluded,
isScheduleExcluded: this.isScheduleExcluded,
isUnitOfUsageExcluded: this.isUnitOfUsageExcluded,
unitOfUsageValue: this.unitOfUsageValue,
canisterQuantity: this.canisterQuantity,
canisterSize: this.canisterSize,
searchText: this.searchText,
scheduleExcludedValue: this.scheduleExcludedValue,
nioshValue:this.nioshValue,
superCellNo:this.superCellNo,
lockingCellNo:this.lockingCellNo,
superLockingCellNo:this.superLockingCellNo,
isNioshExcluded:this.isNioshExcluded
});
In my case this problem arised, because i didn't bind the formControllName attributes in my form object

primeng checkbox with reactive form with array

I am trying to add my array of object to map the primeng checkbox and would like to get the values for selected check boxes.
I have tried FormControlName but it it's throwing undefined after submitting.
below is the rough code
data = [
{ type: dropdown
text: 'drop',
num: 1.23,
options: [
{
value=1,
text= 'drop1
},{
value=2,
text= 'drop2
}
]
},
{ type: checkbox
text: 'check',
num: 1.23,
options: [
{
value=1,
text= 'check1
},{
value=2,
text= 'check2
}
]
},
{ type: radio
text: 'radio',
num: 1.23,
options: [
{
value=1,
text= 'radio1
},{
value=2,
text= 'radio2
}
]
},
];
Template:
<form [formGroup]="group">
<div *ngFor="let d of data">
<div *ngSwitchCase = "checkbox">
<p-checkbox *ngFor="let check of options" [value]="check.value" [formControlName]="check.text"></p-checkbox>
</div>
<div *ngSwitchCase = "dropdown">
<p-dropdown *ngFor="let drop of options" [value]="drop.value" [formControlName]="d.text"> {{drop.text}}
</p-dropdown>
</div>
<div *ngSwitchCase = "radio">
<p-radioButton *ngFor="let radio of options"[value]="radio.value" [formControlName]="d.text"></p-radioButton >
</div>
</div>
</form>
How I can get the reference of my control and values the same for drop down and check boxes.
How to get the values for dynamic forms?
for reactive dynamic form first thing we have to generate the formGroup base of the form control data
getFormGroup method will return a formGroup object by loop over the data and create a form controls with name base of the text value .
getFormGroup() {
const formControls = this.data.reduce( (controls , f:FormControl)=>{
controls[f.text] = this.formBuilder.control(null);
return controls;
},{});
return this.formBuilder.group(formControls)
}
after we generate the form now we can render the form controls on the template
<form [formGroup]="form">
<div *ngFor="let d of data">
<ng-container [ngSwitch]="d.type">
<label for="">{{d.text}}</label>
<div *ngSwitchCase="'checkbox'">
<p-checkbox *ngFor="let check of d.options" [label]="check.label" [value]="check.value"
[formControlName]="d.text"></p-checkbox>
</div>
<div *ngSwitchCase="'dropdown'">
<p-dropdown [options]="d.options" [formControlName]="d.text">
</p-dropdown>
</div>
<div *ngSwitchCase="'radio'">
<p-radioButton *ngFor="let radio of d.options" [name]="d.text" [label]="radio.label"
[value]="radio.value" [formControlName]="d.text">
</p-radioButton>
</div>
</ng-container>
</div>
</form>
stackblitz demo ๐Ÿš€

Unable to render collection dynamically set at run time

I have a piece of JSON which represents some actions and parameters a user can set.
I want to display the actions in a dropdown, and when a user selects one - the required parameters associated with the action are displayed.
Example:
User selects an action with a single parameter, a single input box is displayed
User selects an action with two parameters, two input boxes are displayed.
I nearly have it working but the *ngFor isn't displaying the inputs for the selected action:
In onChange - if I print this.steps, I can see that this.steps[i].SelectedAction.UIParameters has a value so I'm not sure why it isn't being rendered.
JSON:
[
{
"ActionEnum": "CLICKELEMENT",
"Name": "Click Element",
"UIParameters": [
{
"ParameterEnum": "ELEMENTID",
"Description": "The id of the element to click"
}
]
},
{
"ActionEnum": "INPUTTEXT",
"Name": "Input Text",
"Description": "Enters text into the element identified by it's id",
"UIParameters": [
{
"ParameterEnum": "ELEMENTID",
"Description": "The id of the element"
},
{
"ParameterEnum": "TEXTVALUE",
"Description": "The text to enter into the element"
}
]
}
]
Typescript:
import { Component, Output, EventEmitter, OnInit } from "#angular/core";
import { ActionService } from "../services/action-service";
import { Action } from "../models/Action";
#Component({
selector: 'app-scenario-step-editor-component',
template: `
<form #formRef="ngForm">
<div *ngFor="let step of steps; let in=index" class="col-sm-3">
<div class="form-group">
<label class="sbw_light">Action:</label><br />
<select (change)='onChange()' [(ngModel)]="step.Action" name="action_name_{{in}}">
<option *ngFor="let action of this.availableActions" [(ngModel)]="steps[in].value" name="action_name_{{in}}" class="form-control" required>
{{action.Name}}
</option>
</select>
<div *ngIf="steps[in].SelectedAction">
<label class="sbw_light">Parameters:</label><br />
<ng-template *ngFor="let parameter of steps[in].SelectedAction.UIParameters">
<label class="sbw_light">{{parameter.ParameterEnum}}</label><br />
<input (change)='onChange()' type="text" [(ngModel)]="steps[in].Parameters" name="parameter_name_{{in}}" class="form-control" #name="ngModel" required />
</ng-template>
</div>
</div>
</div>
<button id="addStepBtn" type="button" class="btn btn-light" (click)="addScenarioStep()">Add Scenario Step +</button>
</form>`
})
export class ScenarioStepEditorComponent implements OnInit {
#Output() onSelectValue = new EventEmitter<{stepInputs: any[]}>();
steps = [];
availableActions: Action[];
constructor(private actionService: ActionService) {}
ngOnInit(): void {
this.actionService.list().subscribe( result => {
this.availableActions = result;
},
error => console.log('Error getting actions...') );
}
/* When user picks an option, save the chosen action with the rest of the parameters*/
onChange() {
for (let i = 0; i < this.steps.length; i++) {
let actionIndex = this.availableActions.findIndex(a => a.Name === this.steps[i].Action);
this.steps[i].SelectedAction = this.availableActions[actionIndex];
}
this.onSelectValue.emit( {stepInputs: this.steps} );
}
addScenarioStep() {
this.steps.push({value: ''});
}
}
<ng-template *ngFor="let parameter of steps[in].SelectedAction.UIParameters">
<label class="sbw_light">{{parameter.ParameterEnum}}</label><br />
<input (change)='onChange()' type="text" [(ngModel)]="steps[in].Parameters" name="parameter_name_{{in}}" class="form-control" #name="ngModel" required />
</ng-template>
Just replace ng-template with ng-container:
<ng-container *ngFor="let parameter of steps[in].SelectedAction.UIParameters">
<label class="sbw_light">{{parameter.ParameterEnum}}</label><br />
<input (change)='onChange()' type="text" [(ngModel)]="steps[in].Parameters" name="parameter_name_{{in}}" class="form-control" #name="ngModel" required />
</ng-container>
Reasons:
ng-container was suitable for that situation. It just holds "something" and can be iterated.
ng-template defines a template. You didn't need a template here, templates are not meant to be used for that. It could work, of course, but it's not suitable for your scenario.
Read more about ng-template and ng-container here: https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/
As a final side note, you could use ng-template by defining an item and you could use ng-container with *ngTemplateOutlet to render the template. Check the above guide for some examples.

Angular 5 Passing form data to another component's dropdown in sync

I have a form (a material dialog modal) which lets the user to create an account, once the user clicks on Register button then the user stays on the same page with the username of that account that he created. The issue I am having is its getting created but its not getting updated in sync with the closing of dialog modal. Means the user should be registered and in parallel that created user value should be populated in the dropdown for better user expereince. I dont want the user to distract from the current page because if the user have entered the details and if that page is reloaded then all the data whatever he entered will be lost. So i dont want that to happen. So for that i created this below code.
<section class="container-fluid with-maxwidth chapter">
<article class="article">
<div class="box box-default">
<div class="box-body">
<mat-horizontal-stepper [linear]="true" #stepper>
<mat-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template matStepLabel>Project Registration</ng-template>
<div class="form-group row"></div>
<div class="form-group row">
<label for="name" class="col-md-0 control-label"></label>
<div class="col-md-5">
<mat-input-container class="full-width">
<input required [(ngModel)]="project.name" formControlName="nameCtrl" id="name"
matInput placeholder="Project name">
</mat-input-container>
</div>
</div>
<!-- Repository details -->
<div class="form-group row">
<label for="name" class="col-md-0 control-label"></label>
<div class="col-md-5">
<mat-input-container class="full-width">
<input required [(ngModel)]="project.url" formControlName="urlCtrl" id="repo"
matInput placeholder="Repository URL">
</mat-input-container>
</div>
<div class="col-md-7">
<div class="callout1 text-muted callout-info1">
<p>e.g. https://github.com/username/MyApp.git or
git#github.com:username/MyApp.git.
</p>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-md-0 control-label">
</label>
<div class="col-md-5">
<mat-form-field>
<mat-select placeholder="Repository Credentials" required
[(ngModel)]="project.account.id" formControlName="typeCtrl">
<mat-option *ngFor="let account of accounts" [value]="account.id">
{{account.name}} ({{account.accountType}})
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="col-md-7">
<div class="callout1 text-muted callout-info1">
<p>
Add credentials
<br/>
Credentials are required for automatic test creation and check-in.
</p>
</div>
</div>
</div>
<div>
<mat-card-actions>
<button mat-raised-button color="primary"
class="nav-btn"
[disabled]="firstFormGroup.invalid"
(click)="save(stepper);">Save & Next
</button>
</mat-card-actions>
</div>
<div class="form-group row">
<div class="col-md-0"></div>
<div class="col-md-8">
<button [disabled]="!heroForm.valid" mat-raised-button color="primary" (click)="create();"
class="btn-w-md no-margin-left">Register
</button>
<button mat-button type="button" color="primary" class="btn-w-md" (click)="onClose();">Cancel
</button>
</div>
</div>
</form>
</mat-step>
</mat-horizontal-stepper>
</div>
</div>
</article>
</section>
From the template's below code, here if go to other page and then come to here then the username is adding to the drop down properly. But i dont want the user to go back and forth to see whether his credentials are registered or not but instead i want to show the credentials created on the fly so that he can further move.
<mat-form-field>
<mat-select placeholder="Repository Credentials" required
[(ngModel)]="project.account.id" formControlName="typeCtrl">
<mat-option *ngFor="let account of accounts" [value]="account.id">
{{account.name}} ({{account.accountType}})
</mat-option>
</mat-select>
</mat-form-field>
The code for register dialog box component
export class RegisterComponent implements OnInit{
#Input() entry: Account = new Account();
create(entry: Account) {
this.handler.activateLoader();
this.snackbarService.openSnackBar(this.entry.name + " registering...", "");
this.accountService.create(entry).subscribe(results => {
this.entry = entry;
this.handler.hideLoader();
if (this.handler.handle(results)) {
return;
}
this.snackbarService.openSnackBar(this.entry.name + " registered successfully", "");
this.onClose();
// this.router.navigateByUrl('/app/projects', {skipLocationChange: true}).then(()=>
// this.router.navigate(['/app/projects/new']));
this.router.navigate(['/app/projects/new']);
}, error => {
this.handler.hideLoader();
this.handler.error(error);
});
}
onClose(){
this.dialogRef.close();
}
}
This is where i have written the service:
import { Account } from './../models/project.model';
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { Headers } from '#angular/http';
import { Observable, Subject } from 'rxjs';
import 'rxjs/add/observable/timer';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class AccountService {
private serviceUrl = '/api/v1/accounts';
private entry = new Subject<Object>();
entry$ = this.entry.asObservable();
constructor(private http: HttpClient) {
}
create(entry: Account): Observable<any> {
return this.http.post(this.serviceUrl, entry);
}
emitAccount(entry){
this.entry.next();
}
}
I want the user to be on the same page and should update the dropdown with latest results. How is that possible? Could you please suggest me? What i have done wrong with my code.
Thanks.
create Service:
let newEntry = this.http.post(this.serviceUrl, entry);
emitAccount(newEntry);
return newEntry;
Register Component:
entry$.subscribe(updateAccount => {
accounts.push(updateAccount)
}
So to check .. it's about this section?
<mat-option *ngFor="let account of accounts" [value]="account.id">
{{account.name}} ({{account.accountType}})
</mat-option>
BEcause I don't see anything in your code repopulating accounts array after registering.
I can't see where you bind the accounts array.

Passing data from parent to child (Nested Form)

I'm creating a nested form in which I have the parent component that holds the form(s) and has the submit button. And there's the child component which is the form itself.
When I submit the form the property submitted became true, I need to inform my child component that submitted is now true when submitted.
This is the code from submit button in parent component:
enviarDados(model: dadosAcordo, isValid: boolean, isJuridica:boolean) {
this.servError = "";
this.submitted = true;
//more code
}
And this is how the child component look like so far:
export class TitularComponent implements OnChanges {
#Input('group') // this is the input for the form
#Input('submitted') // input for the status of submit
public titularForm: FormGroup;
#Output() modelChanged = new EventEmitter();
constructor(private _fb: FormBuilder, private finalizaAcordo:FinalizaNegociacaoService) {}
ngOnChanges(){
}
// more code
This is the html on the parent component:
<div class="wrap-acordo">
<form [formGroup]="formDadosBancarios" novalidate class="" (ngSubmit)="enviarDados(formDadosBancarios.value)">
<div formArrayName="dados_titular">
<div *ngFor="let dados_titular of formDadosBancarios.controls.dados_titular.controls; let i=index">
<div [formGroupName]="i">
<div class="col s12" *ngIf="formDadosBancarios.controls.dados_titular.length > 1">
<span class="span-removeTitular right-align" (click)="removeTitular(i)"> Remover {{i+1}}ยบ Titular </span>
</div>
<titular (modelChanged)="recebeValidators($event)" [group]="formDadosBancarios.controls.dados_titular.controls[i]"></titular>
</div>
</div>
</div>
<div class="col s12 m6">
<input type="submit" class="botao-medio btn-aceita" value="Aceitar">
</div>
<div class="col s12 m6">
<input type="button" class="botao-medio btn-recusa" value="Recusar">
</div>
</div>
</form>
</div>
Can someone help me? Thanks :)
In your parent component, when the button is clicked, set this.formsubmitted = true . And in child cmponent set this form submitted as input using #Input. If you need to dp something once the formsubmitted becomes true, use ngonchanges for the input formsubmitted.
Ngonchanges(change: Simplechange) {
if(changes['submitted']&& changes['submitted'].currentvalue){
Do your stuff here
}
}
You can refer https://angular.io/docs/ts/latest/api/core/index/OnChanges-class.html

Categories