In angular 5 I am trying to add new row and remove row functionality. For add new row and delete row I have taken code from here. Everything is working fine but when I am trying to get the user entered value in the new row fields I am not getting those values.
I am getting the value for Event Name. But for other 3 fields like Package Name, Package Price, Max Purchase Limit, I am not getting them.
Here is the code what I have tried.
my event-create.component.html looks like this
<div class="container col-md-12">
<h1 class="page-header">Create Event</h1>
<div class="row show-hide-message">
<div [ngClass]= "messageClass">{{message}}</div>
</div>
<form [formGroup] = "form" (ngSubmit)="onEventSubmit()">
<fieldset>
<div class="form-group">
<label for="eventname">Event Name</label>
<div class='form-group' [ngClass]="{'has-error': form.controls.eventname.errors && form.controls.eventname.dirty,
'has-success': !form.controls.eventname.errors
}">
<input type="text" class="form-control" autocomplete="off" placeholder="Event Name" formControlName="eventname">
<ul class="help-block">
<li *ngIf="(form.controls.eventname.errors?.minlength ) && form.controls.eventname.dirty">Event name should be atleast 5 characters</li>
</ul>
</div>
</div>
<h4>Package Price</h4>
<hr>
<div class="row" formArrayName="sections">
<div class="col-md-12" *ngFor="let section of getSections(form); let i = index">
<div class="form-group col-md-5">
<label for="packagename">Package Name</label>
<input type="text" class="form-control" autocomplete="off" placeholder="Package Name" formControlName="packagename" >
</div>
<div class="form-group col-md-2">
<label for="packageprice">Package Price</label>
<input type="number" class="form-control" autocomplete="off" placeholder="Package Price" formControlName="packageprice" >
</div>
<div class="form-group col-md-2">
<label for="packagelimit">Max Purchase Limit</label>
<input type="number" class="form-control" formControlName="packagelimit" autocomplete="off" >
</div>
<div class="form-group col-md-1">
<br/>
<input type="button" (click)="addPackageRow()" class="btn btn-md btn-success" value="+" name="">
</div>
<div class="form-group col-md-1" *ngIf="getSections(form).length > 1">
<br/>
<input type="button" (click)="removeSection(i)" class="btn btn-md btn-error" value="-" name="">
</div>
</div>
</div>
<input [disabled]=!form.valid type="submit" class="btn btn-primary" value="Submit">
<pre>{{form.value | json}}</pre>
</fieldset>
</form>
</div>
and my event-create.component.ts looks like this
import { Component, OnInit } from '#angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
import { FormControlName } from '#angular/forms/src/directives/reactive_directives/form_control_name';
#Component({
selector: 'app-event-create',
templateUrl: './event-create.component.html',
styleUrls: ['./event-create.component.css']
})
export class EventCreateComponent implements OnInit {
form : FormGroup;
packagesArray: FormArray;
constructor(
private formBuilder : FormBuilder,
) { this.createEventForm() }
createEventForm() {
this.form = this.formBuilder.group({
eventname: ['', Validators.compose([
Validators.required,
Validators.minLength(5)
])],
packages: this.packagesArray
})
}
ngOnInit() {
this.form = new FormGroup({
eventname: new FormControl(''),
sections: new FormArray([
this.initSection(),
]),
});
}
initSection() {
return new FormGroup({
packagename: new FormControl(''),
packageprice: new FormControl(''),
packagelimit: new FormControl('')
});
}
initItemRows() {
return this.formBuilder.group({
itemname: ['']
});
}
onEventSubmit() {}
public addPackageRow() {
const control = <FormArray>this.form.get('sections');
control.push(this.initSection());
}
initOptions() {
return new FormGroup({
optionTitle: new FormControl('')
});
}
addSection() {
const control = <FormArray>this.form.get('sections');
control.push(this.initSection());
}
getSections(form) {
return form.controls.sections.controls;
}
public removeSection(i){
const control = <FormArray>this.form.get('sections');
control.removeAt(i);
}
}
Its not showing user entered value in html page also not doing any validation for the eventname field.
Here is the demo what I have done so far
https://stackblitz.com/edit/angular-3s5wwf
Can someone tell me what is going wrong here. Any suggestion or advice will be really appreciable. Thanks.
You need to add this in line 23 and 24
<div class="row" formArrayName="sections">
<div class="col-md-12" *ngFor="let section of getSections(form); let i = index" [formGroupName]="i">
you missed adding the formGroupName for the formArrayName
workinglink
Related
I want to update existing data information using update data form. The input should populate the existing values. How to do that?
As of now, I have to enter all the fields manually to update the form.
Update doctor .ts file
import { Component, OnInit } from '#angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup } from '#angular/forms';
import { ActivatedRoute, Router } from '#angular/router';
import { Doctor } from '../doctor';
import { DoctorService } from '../doctor.service';
#Component({
selector: 'app-update-doctor',
templateUrl: './update-doctor.component.html',
styleUrls: ['./update-doctor.component.css']
})
export class UpdateDoctorComponent implements OnInit {
id:any;
doctor:Doctor;
updateForm:FormGroup;
constructor(private route: ActivatedRoute, private router: Router,private doctorservice: DoctorService,private formbuilder:FormBuilder) {
}
ngOnInit() {
this.doctor = new Doctor();
}
updateDoctor(){
this.doctorservice.updateDoctor( this.doctor)
.subscribe(data =>{
console.log(data);
this.doctor = new Doctor();
window.location.reload();
})
this.gotoList();
}
onSubmit(){
this.updateDoctor();
}
gotoList() {
this.router.navigate(['doctor']);
}
}
update doctor .html file
<div class="card col-md-4 offset-md-4 mt-3" >
<h3>Update Doctor</h3>
<div style="width: 100% ;">
<form (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="doctorId"> Id</label>
<input type="text" class="form-control" id="doctorId" required [(ngModel)]="doctor.doctorId" name="doctorId" #doctorId>
</div>
<div class="form-group">
<label for="doctorName"> Name</label>
<input type="text" class="form-control" id="doctorName" value="{{doctor.doctorName}}" required [(ngModel)]="doctor.doctorName" name="doctorName" #doctorId>
</div>
<div class="form-group">
<label for="doctorProfile">Profile</label>
<input type="text" class="form-control" id="doctorProfile" required [(ngModel)]="doctor.doctorProfile" name="doctorProfile">
</div>
<div class="form-group">
<label for="doctorSpeciality">Speciality</label>
<input type="text" class="form-control" id="doctorSpeciality" value="{{doctor.doctorSpeciality}}" required [(ngModel)]="doctor.doctorSpeciality" name="doctorSpeciality">
</div>
<div class="form-group">
<label for="doctorQualification">Qualification</label>
<input type="text" class="form-control" id="doctorQualification" value="{{doctor.doctorQualification}}" required [(ngModel)]="doctor.doctorQualification" name="doctorQualification">
</div>
<div class="form-group">
<label for="doctorEmail">Email</label>
<input type="text" class="form-control" id="doctorEmail" value="{{doctor.doctorEmail}}" required [(ngModel)]="doctor.doctorEmail" name="doctorEmail">
</div>
<div class="form-group">
<label for="doctorPassword">Password</label>
<input type="password" class="form-control" id="doctorPassword" required [(ngModel)]="doctor.doctorPassword" name="doctorPassword">
</div>
<button type="submit" class="btn btn-dark">Submit</button>
</form>
</div>
</div>
From this function I am navigating to update doctor form
updateDoctor(){
this.router.navigate(['update'])
}
service method for update.
updateDoctor(doctor:Object):Observable<Object>{
return this.http.put(`${this.baseUrl1}`,doctor);
}
You could write a service to get the existing form data and load the data in the form through this.doctor object on load.
I am working on a small project that allows the user to add dynamic fields. On clicking a button I have been able to create input fields dynamically. I am trying to access the value of each field and push it to the service. On the other hand, another component should make the number of div depending upon the number of input fields created by the user and each div should contain a title depending upon the user input in the input field.
register.component.html
<h2>Demo App</h2>
<form [formGroup]="myForm">
<button (click)="addRooms()">Add Room </button>
<div formArrayName="addRoom">
<div *ngFor="let r of Rooms.controls; let i=index" [formGroupName]="i">
<mat-form-field>
<input matInput placeholder="Enter A Room Name" formControlName="roomName" (keyup)="abc()"/>
</mat-form-field>
<button (click)="deleteRoom(i)">Delete</button>
</div>
</div>
<input type="button" (click)="getRoomValues()" value="Get">
</form>
register.component.ts
import { Component, OnInit} from '#angular/core';
import { RegisterModel } from '../models/register.model';
import {FormGroup, FormBuilder, Validators, FormArray, FormControl } from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit, AfterViewInit {
myForm: FormGroup;
room: FormGroup;
constructor(private formBuilder:FormBuilder, private r:Router, private _ele:ElementRef, private _render: Renderer) { }
ngOnInit() {
this.myForm = this.formBuilder.group({
addRoom: this.formBuilder.array([]),
tst: new FormControl()
});
}
getVal(){
console.log(this.myForm.value.tst);
}
get Rooms(){
return this.myForm.get('addRoom') as FormArray;
}
addRooms(){
this.room = this.formBuilder.group({
roomName:new FormControl()
})
this.Rooms.push(this.room);
console.log(this.Rooms);
}
abc(){
console.log(this.room.value.roomName);
}
deleteRoom(i){
this.Rooms.removeAt(i);
}
get roomNames(){
return this.myForm.get('roomNames') as FormArray;
}
getRoomValues(){
console.log(this.myForm.value.addRoom)
}
Below is the code sample for couple of fields with dynamic Add & Remove functionality.
<form [formGroup]="linksForm" class="form-horizontal">
<div class="form-group">
<label class="col-md-2 control-label">Links
</label>
<div class="col-md-10">
<div formArrayName="links" *ngFor="let item of linksForm.get('links').controls; let i = index;">
<div [formGroupName]="i">
<div class="col-md-5">
<input class="form-control col-md-5" formControlName="name" placeholder="Name">
</div>
<div class="col-md-5">
<input type="url" pattern="https?://.+" placeholder="http://example.com" class="form-control col-md-5"
formControlName="link">
</div>
<div class="col-md-2">
<button class="btn btn-warning btn-xs m-t-sm" type="button" (click)="removeItem(i)">
<i name="save" class="fa fa-trash"></i>
</button>
<button *ngIf="i == linksForm.get('links').controls.length - 1" class="btn btn-primary btn-xs m-t-sm" type="button" (click)="addItem()">
<i name="save" class="fa fa-plus"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</form>
TS : Declare below variables in class :
linksForm: FormGroup;
links: FormArray;
Inside ngOnInit() initialize form with at least one row :
this.linksForm = new FormGroup({
'links': new FormArray([this.createItem()])
});
Add below functions for Add / Remove :
addItem(): void {
this.links = this.linksForm.get('links') as FormArray;
this.links.push(this.createItem());
}
removeItem(index: any) {
this.links.removeAt(index);
if (this.links.length == 0) {
this.addItem();
}
}
createItem(): FormGroup {
return new FormGroup({
id: new FormControl(),
name: new FormControl(),
link: new FormControl(),
createdAt: new FormControl()
});
}
I have a simple template driven form like so:
HTML:
<div class="container">
<h1>Hero Form</h1>
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" [(ngModel)]="model.name" name="name" #name="ngModel">
</div>
<div class="form-group">
<label for="alterEgo">Alter Ego</label>
<input type="text" class="form-control" id="alterEgo" [(ngModel)]="model.alterEgo" name="alterEgo">
</div>
<div class="form-group">
<label for="power">Hero Power</label>
<select class="form-control" id="power" [(ngModel)]="model.power" name="power">
<option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
</select>
</div>
<button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
</form>
</div>
Component:
import { Component, OnInit } from '#angular/core';
import { Hero } from './hero';
#Component({
selector: 'at-hero',
templateUrl: './hero.component.html',
styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit {
constructor() {
//
}
ngOnInit() {
//
}
powers = ['Really Smart', 'Super Flexible', 'Super Hot', 'Weather Changer'];
model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
submitted = false;
onSubmit() { this.submitted = true; }
newHero() {
this.model = new Hero(42, '', '');
}
}
How can I:
Reset the whole form from the component (not from the markup)?
Reset a single form field (e.g. the name field) also from the component and not the markup?
You can get the form by using ViewChild
Markup
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
...
</form>
Component
#ViewChild('heroForm') public heroForm: NgForm;
I suggest you also to look at Reactive Forms too. I think this will be more handy if you want to work with form in the typescript, not in the markup
I am trying to create a dynamic field with an add button and a delete button with the Address class. I am stuck as to why the addAddress function does not work. I searched around for a solution but nothing I have searched has worked. I am a novice with Angular so I might be making this more complicated then it needs to be. Here is the app.component.ts
import { FormGroup, FormControl, FormArray, FormBuilder } from
'#angular/forms';
import { Component, OnInit } from '#angular/core';
import { Validators} from '#angular/forms';
class Address{
constructor(public stName, public aptNo, public pinCode){
}
}
class registrationModel{
constructor(public firstName, public lastName,public age,public fromStates,
public state, public homeAddress:Array<Address> ){}
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private _formObject:FormGroup;
private _formModel:registrationModel;
private _addressObject:Address;
private _createFormGroup(){
this._formObject = this._formBuilder.group({
addLabelTitle:["", Validators.minLength(2)],
addLabelType:["", Validators.minLength(2)],
firstName:[],
lastName:[],
age:[18, [Validators.min(18), Validators.max(60)]],
fromStates:[false],
state:[],
stName: [],
aptNo: [],
pinCode: [],
homeAddress:this._formBuilder.array([Address])
});
this._formObject.reset(this._formModel);
console.info(this._formObject);
}
private _submitValue(){
// this._formObject = this._formBuilder.group({
// addLabelTitle:[],
// addLabelType:[],
// firstName:[],
// lastName:[],
// age:[],
// fromStates:[false],
// state:[]
// });
console.info(this._formObject.value);
}
private _resetValue(){
this._formObject.reset();
}
private _addAddress(){
this._addressObject = new Address("","","");
/*
Create a address model.
Inject it to formObject.
*/
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<small>{{this._formObject.value|json}}</small>
<!--The content below is only a placeholder and can be replaced.-->
<div class="registrationForm" [formGroup]="_formObject">
<!-- Name Input box -->
<div class="formGroup">
<label>Name :</label>
<input type="text" placeholder="First Name" formControlName="firstName"
ngModel required>
<input type="text" formControlName="lastName" placeholder="Last Name"
ngModel required>
</div>
<!-- Name Age box -->
<div class="formGroup">
<label>Age :</label>
<input type="number" placeholder="Age" formControlName="age">
<small *ngIf="_formObject.controls.age.errors">
{{getErrors(_formObject.controls.age.errors)}}</small>
</div>
<!-- form United States -->
<div class="formGroup">
<label>From United States </label>
<input type="checkbox" formControlName="fromStates" ngModel required>
</div>
<!-- States -->
<div class="formGroup">
<label>States :</label>
<select formControlName="state">
<option value="co">Colordo</option>
<option value="ca">California</option>
</select>
</div>
<div class="formGroup">
<label>formControlName </label>
<select formControlName="state">
<option value="co">Colordo</option>
<option value="ca">California</option>
</select>
</div>
<hr/>
<div formArrayName="homeAddress">
<button>Delete</button>
<div *ngFor="let address of this._formObject.controls.homeAddress.controls;
let i=index">
<div [formGroupName]="i">
<div class="formGroup">
<label>St Name :</label>
<input type="text" placeholder="" formControlName="stName" ngModel
required>
</div>
<div class="formGroup">
<label>Apt Number :</label>
<input type="text" placeholder="" formControlName="aptNo" ngModel
required>
</div>
<div class="formGroup">
<label>Pincode :</label>
<input type="text" placeholder="" formControlName="pinCode" ngModel
required>
</div>
<!-- <div class="formGroup">
<label>Add Label: </label>
<input type="text" placeholder="Label Title"
formControlName="addLabelTitle">
<input type="text" placeholder="Type (Text, Checkbox, etc)"
formControlName="addLabelType">
</div>
-->
</div>
<hr/>
</div>
<div class="formGroup text-center">
<button (click)="_addAddress()">Add address</button>
<!-- Submit -->
<button (click)="_submitValue()">Submit</button>
<!-- Cancel -->
<button (click)="_resetValue()">Cancel</button>
</div>
</div>
You need to add a formgroup to your form array, if you like to use the class Address you have, you can do it by
_addAddress() {
let formArr = this._formObject.controls.homeAddress;
formArr.push(this._formBuilder.group(new Address('','','')))
}
You can remove all ngModel and required from your form, these belong with template driven forms.
The build of the form is I would create an empty FormArray, and then just call _addAddress after the build of the form since you probably want an initial formgroup in your form array.
As a sidenote, I can't see that the following would even work (?)
homeAddress:this._formBuilder.array([Address])
So I would scrap that and do:
_createFormGroup(){
this._formObject = this._formBuilder.group({
// all other form controls here
homeAddress:this._formBuilder.array([])
});
this._addAddress();
}
I am not able to get selected text of primeng dropdown on button click.
i use formgroup to div and add multiple entries to grid.
i tried a lot and get only selected value. i need dropdown label also.
please help me.
HTML markup:
<div class="row">
<div class="form-group row" formGroupName="FarePaxDetails">
<label for="AirportName" class="col-sm-1 control-label">Pax Type</label>
<div class="col-sm-1">
<p-dropdown [options]="paxes" [(ngModel)]="PaxTypeId" (onChange)="ChangePaxType($event)" formControlName="PaxType"></p-dropdown>
</div>
<label for="AirportName" class="col-sm-2 control-label">Baggage Allow</label>
<div class="col-sm-1">
<input type="text" class="form-control" formControlName="BeggageAllow" [(ngModel)]="BeggageAllow" placeholder="Baggage Allow" />
</div>
<label for="AirportName" class="col-sm-2 control-label">Adult Fare(%)</label>
<div class="col-sm-1">
<input type="text" class="form-control" [(ngModel)]="Percentage" formControlName="Percentage" placeholder="Adult Fare(%)" />
</div>
<label for="AirportName" class="col-sm-1 control-label">Amount</label>
<div class="col-sm-1">
<input type="text" class="form-control" [(ngModel)]="Amount" formControlName="Amount" placeholder="Amount" />
</div>
<div class="col-sm-1">
<button type="button" (click)="AddFarePaxType(FarePaxDetails)" pButton class="btn btn-info" label="Add"></button>
</div>
</div>
</div>
Here is the code in HTML component:
import { Component, ViewEncapsulation } from '#angular/core';
import { TabViewModule, CheckboxModule, DropdownModule, RadioButtonModule, SelectItem, FieldsetModule } from 'primeng/primeng';
import { Response } from '#angular/http';
import { PayTypeService } from '../../Service/PaxTypeService';
import { FormGroup, FormControl, Validators, FormsModule, ReactiveFormsModule } from '#angular/forms';
import { DataTableModule, SharedModule, LazyLoadEvent, DataTable, ConfirmDialogModule, ConfirmationService } from 'primeng/primeng';
#Component({
selector: 'main-fairtype',
templateUrl: './mainfaretype.component.html',
styleUrls: ['./mainfaretype.component.css'],
encapsulation: ViewEncapsulation.None,
providers: [PayTypeService]
})
export class MainFareTypeComponent {
paxes: SelectItem[];
PaxFareTypeList: any[];
public mainForm: FormGroup;
constructor(private PayTypeService: PayTypeService) {
this.mainForm = new FormGroup({
FareType: new FormControl('', [Validators.required]),
FareColor: new FormControl(''),
TourCode: new FormControl('', [Validators.required]),
FareBasis: new FormControl('', [Validators.required]),
MinStay: new FormControl('', [Validators.required]),
MaxStay: new FormControl('', [Validators.required]),
TicketBefore: new FormControl('', [Validators.required]),
ReservationBefore: new FormControl('', [Validators.required]),
Restrictions: new FormControl(''),
FareRule: new FormControl(''),
FarePaxDetails: new FormGroup({
PaxType: new FormControl('', [Validators.required]),
BeggageAllow: new FormControl('', [Validators.required]),
Percentage: new FormControl('', [Validators.required]),
Amount: new FormControl('', [Validators.required])
})
});
this.PayTypeService.GetAllPaxes().then((data: any) => {
debugger
this.paxes = [];
for (var i = 0; i < data.length; i++)
this.paxes.push({ label: data[i].paxTypeName, value: data[i].paxTypeId });
});
this.PaxFareTypeList = [];
}
AddFarePaxType(data: any) {
this.PaxFareTypeList.push({
PaxType: this.mainForm.controls.FarePaxDetails.get('PaxType').value,
Baggage: this.mainForm.controls.FarePaxDetails.get('BeggageAllow').value,
Percentage: this.mainForm.controls.FarePaxDetails.get('Percentage').value,
Amount: this.mainForm.controls.FarePaxDetails.get('Amount').value
})
}
I faced this problem and after brainstorming few hour I fixed using below hack.
Add a reference to your dropdown component and pass that to your "onChange" event handler something like below.
<p-dropdown #dd [options]="paxes" [(ngModel)]="PaxTypeId" (onChange)="ChangePaxType($event, dd)"
formControlName="PaxType"></p-dropdown>
ChangePaxType(event, dd: Dropdown){
console.log(dd.selectedOption.label) // this is your selected item label
}
This is the only way and works!
Try this:
<div formGroupName="FarePaxDetails">
<div class="col-sm-1">
<p-dropdown [options]="paxes" [(ngModel)]="PaxTypeId" (onChange)="ChangePaxType($event)"
formControlName="PaxType"></p-dropdown>
</div>
<label for="AirportName" class="col-sm-2 control-label">Baggage Allow</label>
<div class="col-sm-1">
<input type="text" class="form-control" formControlName="BeggageAllow" [(ngModel)]="BeggageAllow"
placeholder="Baggage Allow"/>
</div>
<label for="AirportName" class="col-sm-2 control-label">Adult Fare(%)</label>
<div class="col-sm-1">
<input type="text" class="form-control" [(ngModel)]="Percentage" formControlName="Percentage"
placeholder="Adult Fare(%)"/>
</div>
<label for="AirportName" class="col-sm-1 control-label">Amount</label>
<div class="col-sm-1">
<input type="text" class="form-control" [(ngModel)]="Amount" formControlName="Amount" placeholder="Amount"/>
</div>
<div class="col-sm-1">
<button type="button" (click)="AddFarePaxType(FarePaxDetails)" pButton class="btn btn-info"
label="Add"></button>
</div>
</div>