I don't know why the form is not working!
the input does not change the values in the form.
and the valueChanges is not detecting anything. any help?
applied on stackblitz:
https://stackblitz.com/edit/angular-ivy-w68v69?file=src/app/app.component.ts
import { Component, VERSION } from "#angular/core";
import { FormControl, FormGroup, Validators } from "#angular/forms";
#Component({
selector: "my-app",
template: `
<form [formGroup]="form">
<input
FormControlName="patientName"
placeholder="Enter Patient Name ..."
/>
</form>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent {
form: FormGroup;
ngOnInit() {
this.form = new FormGroup({
patientName: new FormControl("")
});
this.form.get("patientName").valueChanges.subscribe(x => console.log(x));
this.form.valueChanges.subscribe(next => {
console.log("valueChanges didtted");
console.log(next);
});
console.log("form created");
}
}
The property FormControlName in the HTML part should have the 'F' in lowercase : formControlName="patientName".
It you correct this, it works : https://stackblitz.com/edit/angular-ivy-cjntrr?file=src/app/app.component.ts
trying to understand how to bind input values in ngFor in below code both are printing same values , trying to set different value for each input , where i am making mistake ?
app.comp.html
<div *ngFor="let ques of sub.question">
<label for="subQuestionsInput">{{ques.questionText}}</label>
<input type="subQuestionsInput" class="form-control" *ngIf= "ques.answerType === 'TEXT_NUMBER'" name="TEXT_NUMBER" placeholder="Enter Dose amount Left" [(ngModel)]="TEXT_NUMBER">
<input type="subQuestionsInput" class="form-control" *ngIf= "ques.answerType === 'TEXT_DATE'" name="TEXT_DATE" placeholder="Enter Next Dose Date" [(ngModel)]="TEXT_DATE">
</div>
app.comp.ts
import {
Component,
OnInit
} from '#angular/core';
import {
ApiService
} from './api.service';
import {
EventService
} from './format-questions/format-questions.service'
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent Implement OnInit {
TEXT_NUMBER: string;
TEXT_DATE: string;
constructor(private dataService: ApiService, private eventService: EventService) {}
ngOnInit() {
console.log(TEXT_NUMBER);
console.log(TEXT_DATE);
}
}
I create a custom input and other generic element
and at that point I want to bind it to reactive forms. Now I got null as value.
HTML
<label for="name">
<span>{{title}}</span>
<input type="text" name="name" formControlName="name">
</label>
Component
export class AppInputComponent implements OnInit {
#Input() name: string;
#Input() title?: string;
#Input() form: FormGroup;
#Input() options?: Array<string>;
constructor() { }
ngOnInit() {
}
}
This one have its own module file
#NgModule({
declarations: [
GFormsFields.AppTextboxComponent,
GFormsFields.AppSelectComponent,
GFormsFields.AppInputComponent,
GFormsFields.AppCheckboxComponent
],
imports: [
CommonModule,
BrowserModule,
],
exports: [
GFormsFields.AppTextboxComponent,
GFormsFields.AppSelectComponent,
GFormsFields.AppInputComponent,
GFormsFields.AppCheckboxComponent
],
providers: [],
bootstrap: []
})
And now I want to bind it to place where I create the reactive form.
HTML
<form [formGroup]="reactiveForms" (ngSubmit)="onSubmit()">
<app-app-input [title]="'First Name Dude'" [name]="'firstName'" [form]="'form'"></app-app-input>
<button type="submit" [disabled]="!reactiveForms.valid">Submit</button>
</form>
Component
import { Component } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms'
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
reactiveForms = new FormGroup({
name: new FormControl
});
onSubmit(): void {
console.log(this.reactiveForms);
}
}
How can I pass from this custom input to app (it's as test purpose. This will be nested at other component).
What did I do wrong?
change AppInputComponent.html like this :
<label for="name">
<span>{{title}}</span>
<input type="text" name="name" [formControl]="form.controls.name">
</label>
and use component like this :
<app-app-input [title]="'First Name Dude'" [name]="'firstName'" [form]="reactiveForms"></app-app-input>
===============================
with above changes your problem will be solved but i would suggest u extra changes for better design .
change AppInputComponent.ts like this :
export class AppInputComponent implements OnInit {
#Input() name: string;
#Input() title?: string;
#Input() nameControl: FormControl;
#Input() options?: Array<string>;
constructor() { }
ngOnInit() {
}
}
change AppInputComponent.html like this :
<label for="name">
<span>{{title}}</span>
<input type="text" name="name" [formControl]="nameControl">
</label>
and finally use it like this :
<app-app-input [title]="'First Name Dude'" [name]="'firstName'" [nameControl]="reactiveForms.controls.name"></app-app-input>
AppInputComponent only needs FormControl of "name" not whole FormGroup . so it is not a good design to pass the entire FormGroup .
I have created a form but I am not able to create nested form as I need to add certain input fields dynamically which I am getting but now what is required is like when I click add a link it should add form nested.
Form image
Add button near input field should add only social media link and GitHub input field others will remain same.
HTML
<div class="container">
<p> </p>
<div>
<form [formGroup]="searchForm" novalidate (ngSubmit)="submit(searchForm.value)">
<div formArrayName="properties">
<div *ngFor="let prop of searchForm.get('properties').controls; let i = index">
<div class="row" [formGroupName]="i">
<select formControlName="desg" class="form-control">
<option value="CEO">CEO</option>
<option value="CTO">CTO</option>
<option value="CMO">CMO</option>
<option value="Project Manager">Project Manager</option>
</select>
<input formControlName="name" type="text" class="form-control" placeholder="Name">
<input formControlName="linkedin" type="text" class="form-control" placeholder="LinkedIn Url">
<input formControlName="github" type="text" class="form-control" placeholder="Github Url">
<button *ngIf="searchForm.controls['properties'].length > 1 " (click)="onDelProperty(i)">Delete</button>
</div>
</div>
</div>
<p>
</p>
<a (click)="onAddProperty()">Add</a>
<button class="btn btn-bold btn-primary" type="submit">submit</button>
</form>
</div>
</div>
component.ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, FormArray, FormControl } from '#angular/forms';
import { IcoService } from '../../services/ico.service';
import { debug } from 'util';
#Component({
selector: 'app-team',
templateUrl: './team.component.html',
styleUrls: ['./team.component.css']
})
export class TeamComponent implements OnInit {
searchForm: FormGroup;
searchForm1: FormGroup;
constructor(private fb: FormBuilder,private icoService: IcoService,) { }
ngOnInit() {
this.searchForm = this.fb.group({
properties: this.fb.array([this.createItem()])
});
}
createItem(): FormGroup {
return this.fb.group({
name: '',
desg: '',
social_media: '',
github:''
});
}
submit(formData: any) {
this.icoService.teamDetail(formData).subscribe((result) => {
console.log()
}, (err) => { console.log('err',err) })
}
onAddProperty() {
for(var i=1; i<=1; i++) {
(this.searchForm.get('properties') as FormArray).push(this.createItem());
}
}
onDelProperty(index:any) {
for(var i=1; i<=1; i++) {
(this.searchForm.get('properties') as FormArray).removeAt(index);
}
}
}
You Can try for following, This may help for you:
import { ToasterContainerComponent, ToasterService, ToasterConfig} from 'angular2-toaster';
// ======================== Internal Dependency Module Loading Start ================================
import {TabViewModule} from 'primeng/tabview';
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators,FormArray, FormControl} from '#angular/forms';
import { Router } from '#angular/router';
import { GlobalAjaxMethodHandler } from '../util/GlobalAjaxMethodHandler';
import { GlobalValidationService } from '../util/GlobalValidationService';
import { AjaxMethodName } from '../util/GlobalAjaxPathHandler';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
form = new FormGroup({
cities: new FormArray([
// new FormControl('drp')
this.initAddress()
]),
});
constructor(public _fb: FormBuilder, private _GlobalAjaxMethodHandler: GlobalAjaxMethodHandler, public router: Router,public _toasterService:ToasterService) { }
ngOnInit() {
this.formIntialization();
}
initAddress() {
// initialize our address
return this._fb.group({
third : ['', Validators.required],
second: [''],
first: [''],
four: ['']
});
}
//================================= Initialize form Value ============================================
formIntialization() {
this.loginForm = this._fb.group ({
Email : ['', [Validators.required, GlobalValidationService.emailValidator]],
Password : ['', [Validators.required, GlobalValidationService.passwordValidator]]
});
}
get cities(): FormArray { return this.form.get('cities') as FormArray; }
addCity() {
this.cities.push(this._fb.group({
third : ['', Validators.required],
second: [''],
first: [''],
four: ['']
}));
}
onSubmit() {
console.log(this.cities.value); // ['SF', 'NY']
console.log(this.form.value); // { cities: ['SF', 'NY'] }
}
setPreset() {
if(this.cities.length > 1){
this.cities.removeAt(this.cities.length-1);
}
}
}
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div formArrayName="cities">
<!-- <div *ngFor="let city of cities.controls; index as i">
<input [formControlName]="i" placeholder="City">
</div> -->
<div *ngFor="let city of cities.controls; index as i">
<div [formGroupName]="i">
<select formControlName="first">
<option [selected]="true">--Select--</option>
<option>A1</option>
<option>B1</option>
<option>C1</option>
</select>
<select formControlName="second">
<option [selected]="true">--Select--</option>
<option>A2</option>
<option>B2</option>
<option>C2</option>
</select>
IN : <input type="checkbox" formControlName="third" value="+">
Out :<input type="checkbox" formControlName="four" value="+">
</div>
</div>
</div>
<input type="button" name="" value="Enable integration" (click)="onSubmit()">
</form>
I'm not sure what your for loop is for in your onAddProperty and onDelProperty methods.
And if I understand correctly, your name and desg controls should be added to the fb.group defined in ngOnInit. Those will then be defined only one time. Only add to the createItem method those controls that you want repeated each time the user clicks the Add.
I have similar code that adds an address block. My code looks something like this:
#Component({
selector: 'my-signup',
templateUrl: './app/customers/customer.component.html'
})
export class CustomerComponent implements OnInit {
customerForm: FormGroup;
get addresses(): FormArray{
return <FormArray>this.customerForm.get('addresses');
}
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.customerForm = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(3)]],
lastName: ['', [Validators.required, Validators.maxLength(50)]],
addresses: this.fb.array([this.buildAddress()])
});
}
addAddress(): void {
this.addresses.push(this.buildAddress());
}
buildAddress(): FormGroup {
return this.fb.group({
addressType: 'home',
street1: '',
street2: '',
city: '',
state: '',
zip: ''
});
}
}
In the above example, the first name and last name appear only once, but the address fields are repeated each time the user clicks an add button.
For a full working example, check out this github: https://github.com/DeborahK/Angular2-ReactiveForms (specifically the Demo-Final folder)
UPDATE to include YOUR code:
Make the following change ... notice that everything you do not want repeated is in the ngOnInit. Everything you do want repeated is in the createItem.
ngOnInit() {
this.searchForm = this.fb.group({
name: '',
desg: '',
properties: this.fb.array([this.createItem()])
});
}
createItem(): FormGroup {
return this.fb.group({
social_media: '',
github:''
});
}
You also, of course, need to remove the fields you don't want repeated from the ngFor in your html. Just move them up above the ngFor.
here is the parent component
import { Component, OnInit } from '#angular/core';
import {ViewEncapsulation} from '#angular/core';
#Component({
selector: 'app-bukkacorporateform',
templateUrl: './bukkacorporateform.component.html',
styleUrls: ['./bukkacorporateform.component.css'],
encapsulation: ViewEncapsulation.None
})
export class BukkacorporateformComponent implements OnInit {
constructor() { }
ngOnInit() {
}
check: number = 6;
indi = function individual(){
this.check = 4;
}
cliq = function clique(){
this.check = 5;
}
comp = function company(){
this.check = 6;
}
}
and here is the child component
import { Component, OnInit, Input, NgZone } from '#angular/core';
import {ViewEncapsulation} from '#angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule } from '#angular/forms';
import {Observable} from 'rxjs/Rx';
import {FormService} from '../../services/form.service';
import {CompaniesData} from '../../models/companies-data';
#Component({
selector: 'app-corporateform',
templateUrl: './corporateform.component.html',
styleUrls: ['./corporateform.component.css'],
encapsulation: ViewEncapsulation.None,
providers: [FormService]
})
export class CorporateformComponent implements OnInit {
#Input('data') type:number;
value: boolean = true;
subscriptionForm : FormGroup;
constructor(fb: FormBuilder, private formService: FormService){
this.subscriptionForm = fb.group({
'contactname' : '',
'phonenumber': '',
'type' : '',
'email' : '',
'companyname' : '',
'approxbudget' : '',
'approxbudget' : '',
'noofpeople' : '',
'eventtype': ''
})
}
submitForm(value: any):void{
value.type = this.type;
value.phonenumber += '';
value.phonenumber = '0' + value.phonenumber;
console.log(value);
}
}
when i submit the form the type variable is actually changing as expected, however the ngIf in the view is not responding to the same variable changes
and in the template
<div class="three-in" *ngIf="type == 6">
<!--<div class="form-group col-3 drop_fields">
</div>-->
<div class="form-group col-3">
<input class="form-control" id="corporate_lead_event_at" name="corporate_lead[event_at]" placeholder="Date of event" readonly="readonly" style="background-color: #fff;" type="text">
</div>
<div class="form-group col-3">
<input class="form-control" data-error="Invalid number" data-wrong="Invalid number" id="corporate_lead_budget" name="corporate_lead[budget]" placeholder="Approx Budget" type="number">
</div>
<div class="form-group col-3">
<input class="form-control" id="corporate_lead_number_of_people" name="corporate_lead[number_of_people]" placeholder="No. of people" type="number">
</div>
<div class="clear"></div>
</div>