How to add and delete item from array in Angular - javascript

I am doing a project that need to display an array and user can add in new data or delete existing data from the array.
I am stuck with how to add and delete item from array.
I tried to use push function to add and pop function to delete but failed.
HTML
<div class="write">
<h1>Student Details</h1>
<div class="data" *ngIf="selectedStudent">
<li> Name: <input type="text" [(ngModel)]="name" placeholder="Please enter Name" value={{selectedStudent.name}}>
</li>
<li> Age:<input type="text" [(ngModel)]="age" placeholder="Please enter Age" class="age"
value={{selectedStudent.age}}></li>
<li>College:<input type="text" [(ngModel)]="college" placeholder="Please enter College"
value={{selectedStudent.college}}></li>
</div>
<p>
<button class="btnA" onclick="addStudent()">Add</button>
<button class="btnE" onclick="editStudent()">Edit</button>
<button class="btnD" onclick="deleteStudent()">Delete</button>
</p>
<li *ngFor="let student of student" [class.selected]="student === selectedStudent" (click)="onSelect(student)">
<span class="badge">{{student.name}} {{student.age}} {{student.college}}</span>
</li>
</div>
.ts
export class WriteComponent implements OnInit {
name: string;
age: number;
college: string;
student = STUDENTS;
selectedStudent: Student;
constructor() {}
ngOnInit(): void {}
onSelect(student: Student): void {
this.selectedStudent = student;
}
}
mock-student.ts (where I store my array)
import { Student } from './student';
export const STUDENTS : Student[]=[
{name:'Johnny',age:24,college:'Harvard'},
{name:'Samantha',age:20,college:'INTI'},
{name:'Aditya',age:21,college:'Sunway'},
{name:'Troy',age:25,college:'TARUC'},
]

Hope this helps.....
Result:
app.component.html
<div class="container">
<h2>Add User</h2>
<form class="form-inline" autocomplete="off" (submit)="addStudent()">
<div class="form-group">
<label for="email">Name:</label>
<input type="text" class="form-control" id="name" name="name" [(ngModel)]="user.name">
</div>
<div class="form-group">
<label for="pwd">Age:</label>
<input type="number" class="form-control" id="age" name="age" [(ngModel)]="user.age">
</div>
<div class="form-group">
<label for="pwd">College:</label>
<input type="text" class="form-control" id="college" name="college" [(ngModel)]="user.college">
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
<div class="user-list" *ngIf="usersList && usersList.length">
<h2>List of Users</h2>
<table class="table table-condensed">
<thead>
<tr>
<th>SL.No</th>
<th>Name</th>
<th>Age</th>
<th>College</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of usersList; let i = index">
<th>{{i}}</th>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{user.college}}</td>
<td>
<button style="margin-right: 5px;" class="btn btn-warning" (click)="editStudent(i)">Edit</button>
<button class="btn btn-danger" (click)="deleteStudent(i)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
app.component.ts
export class AppComponent implements OnInit{
user: User;
usersList: User[] = []
ngOnInit(): void {
this.resetForm();
}
addStudent() {
this.usersList.push(this.user);
this.resetForm();
}
editStudent(index: number) {
this.user = this.usersList[index];
this.deleteStudent(index);
}
deleteStudent(index: number) {
this.usersList.splice(index, 1);
}
resetForm() {
this.user = {age: null, name: '', college: ''};
}
}
interface User {
name: string;
age: string;
college: string;
}

Deleting an item from the array
You are setting your selectedStudent to one of the instances in your array, so it is simple enough to find its index when you want to remove it from the array.
You can use the splice array function to remove the item at the index.
// declare students here for the purpose of the answer
students: Student[] = [
{name:'Johnny', age:24, college:'Harvard'}
// ... more students here
];
selectedStudent : Student;
onSelect(student:Student): void {
this.selectedStudent = student;
}
deleteStudent(): void {
if (!this.selectedStudent) {
return;
}
// find the index of the selected student
// this works because your selected student is one of the array items
// it wouldn't work if selected student was a copy
const index = this.students.indexOf(this.selectedStudent);
// use splice to remove 1 item starting at the given index
this.students.splice(index, 1);
// todo: logic to reset this.selectedStudent
}
Adding an item to the array
Adding is simple. Use the push array function to append an item to an array.
students: Student[] = [];
name: string;
age: number;
college: string;
addStudent() {
const student = {
name: this.name,
age: this.age,
college: this.college
};
this.students.push(student);
}

Related

How would I go about binding form input from multiple child components to an array defined in a parent component?

I am trying to bind form input from multiple child components (item-input-component) to array itemList[] defined in a parent component (add-invoice-component). I want to take three inputs (itemName, quantity, price), create an Item object out of them, then output that Item object from item-input-component and add it to itemList[]. How can I do that ? Is that even possible ? And if not, what's a good solution ?
add-invoice-component.html
<form>
<div>
<h2>Items</h2>
<app-item-input *ngFor="let item of numArray"></app-item-input>
<button (click)="incrementNumOfItems()">Add Item</button>
</div>
</form>
add-invoice-component.ts
import { Component, ElementRef, OnInit, Renderer2 } from '#angular/core';
import { Item } from 'src/app/models/item';
#Component({
selector: 'app-add-invoice',
templateUrl: './add-invoice.component.html',
styleUrls: ['./add-invoice.component.css']
})
export class AddInvoiceComponent implements OnInit {
description!: string;
invoiceDate!: Date;
clientName!: string;
clientAddress!: string;
itemList!: Item[];
numOfItems: number = 2;
numArray: number[] = Array(2).fill(0).map((x,i)=>i);
constructor( private el: ElementRef) { }
ngOnInit(): void {
}
incrementNumOfItems() {
this.numOfItems++;
this.numArray = Array(this.numOfItems).fill(0).map((x,i)=>i);
}
removeItem() {
this.el.nativeElement.remove()
}
}
item-input-component.html
<div class="mb-3 row item">
<div class="col">
<label for="item-name" class="form-label">Item Name</label>
<input type="text" id="item-name" name="clientName" class="form-control">
</div>
<div class="col">
<label for="quantity" class="form-label">Quantity</label>
<input type="text" id="quantity" name="quantity" class="form-control">
</div>
<div class="col">
<label for="price" class="form-label">Price</label>
<input type="text" id="price" name="price" class="form-control">
</div>
<button (click)="removeItem()">Delete Item</button>
item-input-component.ts
import { Component, ElementRef, OnInit , Renderer2} from '#angular/core';
#Component({
selector: 'app-item-input',
templateUrl: './item-input.component.html',
styleUrls: ['./item-input.component.css']
})
export class ItemInputComponent implements OnInit {
itemName!: string;
quantity!: number;
price!: number;
constructor(private el: ElementRef) { }
ngOnInit(): void {
}
removeItem() {
this.el.nativeElement.remove()
}
}
Item.ts
export interface Item {
itemName: string,
quantity: number,
price: number
}
The question is about pass to your child component an object, to Delete you need use Output to comunicate with the parent
This object will be an object with properties: itemName, quantity and price -and the you use [(ngModel)] or a FormGroup -and you use ReactiveForms-
#Input()element:any
#Output() deleteItem:EventEmitter<any>:new EventEmitter<any>()
<input ... [(ngModel)]="element.clientName">
<input ... [(ngModel)]="element.quantity">
<input ... [(ngModel)]="element.price">
<button (click)="deleteItem.emit(null)">Delete Item</button>
Your parent
<app-item-input *ngFor="let item of list;let i=index"
[element]="list[i]"
(deleteItem)="removeItem(i)"
></app-item-input>
where
list:any[]=this.numArray.map(_=>({
clientName:'',
quantity:0,
price:0
}))
//see that removeItem remove one value of the array.
//**NOT** about your .html
removeItem(index:number) {
this.list.splice(index,1)
}
Using a FormArray is looks like
formGroup:FormGroup;
#Input('group') set _group(value)
{
this.formGroup=value as FormGroup
}
#Output() deleteItem:EventEmitter<any>:new EventEmitter<any>()
<form [formGroup]="fromGroup">
<input ... formControlName="clientName">
<input ... formControlName="quantity">
<input ... formControlName="price">
</form>
<button (click)="deleteItem.emit(null)">Delete Item</button>
And the parent
<app-item-input *ngFor="let item of listFormArray.controls;let i=index"
[group]="listFormArray.at(i)"
(deleteItem)="removeItem(i)"
></app-item-input>
listFormArray:FormArray[]=new FormArray(
this.numArray.map(_=>(new FormGroup({
clientName:new FormControl(null),
quantity:new FormControl(0),
price::new FormControl(0)
})))
)
removeItem(index:number) {
this.formArray.removeAt(index)
}
Looks like you're not familiar with Angular services, so here's an example to show you how it works.
Stackblitz: https://stackblitz.com/edit/angular-ivy-afppeb?file=src/app/item.service.ts
Here's a simple service to hold the items, it has add and delete methods
Item Service
#Injectable({ providedIn: 'root' })
export class ItemService {
itemList: Item[] = [];
addItem(item: Item) {
this.itemList.push(item);
}
deleteItem(index: number) {
this.itemList.splice(index, 1);
}
}
To access this service you just inject it via the constructor of any component:
Add Invoice Component
export class AddInvoiceComponent {
constructor(private itemService: ItemService) {}
get items() {
return this.itemService.itemList;
}
delete(index: number) {
this.itemService.deleteItem(index);
}
}
<app-item-input></app-item-input>
<h1>Items</h1>
<ng-container *ngFor="let item of items; index as i">
<pre>{{ item | json }}</pre>
<button (click)="delete(i)">Delete</button>
</ng-container>
And here's a simple way to convert the form data to an object
Item Input Component
export class ItemInputComponent {
formGroup = new FormGroup({
itemName: new FormControl(''),
quantity: new FormControl(0),
price: new FormControl(0),
});
constructor(private itemService: ItemService) {}
onSubmit() {
this.itemService.addItem(this.formGroup.getRawValue());
}
}
<h1>Input</h1>
<form [formGroup]="formGroup" (ngSubmit)="onSubmit()">
<div>
<label>Item Name:</label>
<input type="text" formControlName="itemName" />
</div>
<div>
<label>Quantity:</label>
<input type="number" formControlName="quantity" />
</div>
<div>
<label>Price:</label>
<input type="number" formControlName="price" />
</div>
<button type="submit">Submit</button>
</form>
You may want to do form validation as well, but this is just to show you how the service works.

How to test pipes in angular

I have a scenerio where a pipe return the class name based on the input and my test case is getting failed if I trying to test the pipe. My implementation is as follows, can anyone pls help.Thanks.
I have a html as follows,
<div [class]="type | functionTester: getNameOfClass: this">
....
</div>
Ts,
type = 'high';
getNameOfClass() {
if (type === 'high') {
return 'HIGH';
} else {
return 'LOW';
}
}
Pipe,
export class functionTesterPipe implements PipeTransform {
public transform(
value: any,
handler: (value: any) => any,
context?: any
): any {
if (context) {
return handler.call(context, value);
}
return handler(value);
}
}
Spec,
const { find } = await shallow
render({
bind: { chartData: chartData, type: 'ORG_BENCHMARK' }
});
const pipe = new functionTesterPipe();
expect(pipe.transform('high', instance.prepareClassName)).toBe('High');
fixture.detectChanges();
expect(find('.High').length).toBe(1); -> Failing at this line as [expect 0 to be 1]
I have a scenerio where a pipe return the class name based on the input and my test case is getting failed if I trying to test the pipe. My implementation is as follows, can anyone pls help.Thanks.
Basic setup for pipe testing:
import { Pipe } from './pipe.pipe';
describe('Pipe', () => {
let pipeToTest: Pipe;
// synchronous beforeEach
beforeEach(() => {
pipeToTest = new Pipe();
});
it('should be instanciated', () => {
expect(pipeToTest).toBeDefined();
});
});
<table>
<tr>
<th>Employee Name</th>
<th>Employee ID</th>
<th>Mail</th>
<th>Salary</th>
<th>Actions</th>
<th></th>
</tr>
<tr *ngFor="let data of empolyeeDetails ">
<td> {{data?.name}} </td>
<td> {{data?.id}} </td>
<td> {{data?.email}} </td>
<td> {{data?.salary}} </td>
<td><button type="Edit" class="btn btn-primary" (click)="onEdit(data) ">Edit</button></td>
<td><button type="Delet" class="btn btn-primary" (click)="onDelete(data)">Delete</button></td>
</tr>
</table>
<br>
<div class="crudForm">
<form [formGroup]="crudForm">
<div class="form-group">
<label for="exampleInputEmail1">Name</label>
<input type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
placeholder="Enter Name" formControlName="name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
placeholder="Enter email" formControlName="email">
</div>
<div class="form-group">
<label for="exampleInputEmail1">salary</label>
<input type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
placeholder="Enter Salary" formControlName="salary">
</div>
<!-- <div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div> -->
<button type="submit" class="btn btn-primary" (click)="onSubmit()">Submit</button>
</form>
</div>
===============================================================
import { Component } from '#angular/core';
import { FormBuilder } from '#angular/forms';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'credApp';
crudForm: any;
isEdit = false;
empolyeeDetails = [
{ name: "Ragu", id: "123", email: "rag#mail.com", salary: 50000 },
{ name: "Ramu", id: "345", email: "ram#mail.com", salary: 40000 },
{ name: "Raju", id: "678", email: "raju#mail.com", salary: 45000 }
];
constructor(public fb: FormBuilder) {
this.loadForm();
if (this.getFromLocalStorage()) {
this.empolyeeDetails = this.getFromLocalStorage();
}
}
loadForm() {
this.crudForm = this.fb.group({
name: [''],
id: [''],
email: [''],
salary: ['']
});
}
onEdit(data: any) {
this.isEdit = true;
this.crudForm.controls['name'].setValue(data.name);
this.crudForm.controls['id'].setValue(data.id);
this.crudForm.controls['email'].setValue(data.email);
this.crudForm.controls['salary'].setValue(data.salary);
}
onDelete(data: any) {
var index = this.empolyeeDetails.findIndex(function(element) {
return (element.id === data.id);
});
this.empolyeeDetails.splice(index, 1);
this.performStorageAction();
}
onSubmit() {
var randomNum = Math.floor(Math.random() * 90 + 10);
if (this.isEdit) {
this.onDelete(this.crudForm.value);
} else {
this.crudForm.controls['id'].setValue(randomNum);
}
this.empolyeeDetails.push(this.crudForm.value);
this.performStorageAction();
this.crudForm.reset();
}
storeInLocalStorage() {
localStorage.setItem("data", JSON.stringify(this.empolyeeDetails));
}
getFromLocalStorage() {
return JSON.parse(localStorage.getItem('data') || '');
}
performStorageAction() {
this.storeInLocalStorage();
this.empolyeeDetails = this.getFromLocalStorage();
}
}

Only first line of database code is returning

I am creating a website which calls a list of items from an external API.
The list has an "Order" button alongside it which when pressed, opens a modal with an order form.
The form is submitted, the API correctly receives the form data. But I am trying to send the row information to the API aswell to inform what has actually been ordered.
The problem is that only the first row returned is ever sending no matter which line is "Ordered".
My html code file is:
<head>
</head>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<div class="body">
<h1 class="header">Carpet Clearance</h1>
<h2 class="header">
The Mega Day carpet clearance list
</h2>
</div>
<table class="table">
<th>
<td>Range</td>
<td>Size</td>
<td>Colour</td>
<td>Cost</td>
<td>Value</td>
<td>Order</td>
<tr *ngFor="let row of carpet;">
<td class="td2">{{row.ID}}</td>
<td>{{row.Range}}</td>
<td>{{row.Size}}</td>
<td>{{row.Colour}}</td>
<td>{{row.Cost}}</td>
<td>{{row.Value}}</td>
<td><button onclick="document.getElementById('id01').style.display='block'" class="btn">Order Item</button>
<div id="id01" class="w3-modal">
<div class="w3-modal-content w3-animate-bottom w3-card-4">
<header class="w3-container w3-teal">
<span onclick="document.getElementById('id01').style.display='none'"
class="w3-button w3-display-topright">×</span>
<h2 class="body">Order this item</h2>
</header>
<div class="modal">
<p class="form">To order this range, please enter your customer account number, delivery address and Rep ID.</p>
<form class="form" [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value, row)">
<div>
<label for="Rep ID">
Rep ID<br>
</label>
<input id="Rep" type="text" formControlName="Rep">
</div>
<div>
<label for="Account">
Account Number<br>
</label>
<input id="Account" type="text" formControlName="Account">
</div>
<div>
<label for="address">
Address<br>
</label>
<input id="Address" type="text" formControlName="Address">
</div>
<button class="button" type="submit">Order</button>
</form>
</div>
</div>
</div>
</td>
</tr>
</table>
My TS file is:
import { Component, OnInit } from '#angular/core';
import { ApiService } from '../../shared/api.service';
import { FormBuilder } from '#angular/forms';
#Component({
selector: 'app-carpet',
templateUrl: './carpet.component.html',
styleUrls: ['./carpet.component.scss']
})
export class CarpetComponent implements OnInit {
checkoutForm;
carpet = [];
loadingIndicator = true;
reorderable = true;
columns = [
{ prop: 'ID', summaryFunc: () => null },
{ prop: 'Range', summaryFunc: () => null },
{ prop: 'Colour', summaryFunc: () => null },
{ prop: 'Size', summaryFunc: () => null },
{ prop: 'Cost', summaryFunc: () => null },
{ prop: 'Value', summaryFunc: () => null }
];
constructor(private apiService: ApiService,
private formBuilder: FormBuilder
) {
this.checkoutForm = this.formBuilder.group({
Rep: '',
Account: '',
Address: ''
});
}
ngOnInit() {
this.apiService.getCarpet()
.subscribe((carpet: any[]) => {
this.carpet = carpet;
this.loadingIndicator = false;
});
}
onSubmit(customerData, row) {
const data = {
customerData, row
};
this.apiService.sendFormData(data)
.subscribe();
this.checkoutForm.reset();
console.warn('Your order has been submitted', customerData);
}
}
Can anyone point me towards the error here?

Angular Reactive Forms Array

I am having problem accesssing products array located inside opticanOrders which is inside orderForm. In the console, I see that in order to access products array, I should reference it like that:
orderForm.controls.opticianOrders.controls.products.controls
But it doesn't work.
This is my component:
constructor(private customerService: CustomerService, private fb: FormBuilder) { }
orderForm: FormGroup;
ngOnInit() {
this.orderForm = this.fb.group({
name: [''],
surName: [''],
opticianOrders: this.fb.group({
orderDescription: [''],
products: this.fb.array([
this.initProduct()
])
}),
});
}
save(model: Customer) {
// call API to save customer
console.log(model);
}
onCancel(form: NgForm){
this.createState.emit(false);
}
initProduct(){
return this.fb.group({
name: [''],
manufacturerName: ['']
})
}
addProduct(){
const control = <FormArray>this.orderForm.controls['products'];
control.push(this.initProduct());
}
removeProduct(i: number){
const control = <FormArray>this.orderForm.controls['products']
}
Html
<form [formGroup]="orderForm" novalidate (ngSubmit)="save(orderForm)">
<!-- name -->
<div class="form-group">
<label>Name</label>
<input type="text" formControlName="name">
</div>
<!-- surName -->
<div class="form-group">
<label>Last Name</label>
<input type="text" formControlName="surName">
</div>
<div formGroupName="opticianOrders" class="form-group">
<label>Order Description</label>
<input type="text" formControlName="orderDescription">
</div>
<div formArrayName="products">
<div *ngFor="let product of orderForm.controls.opticianOrders.controls.products.controls; let i=index">
<div>
<span>Address {{i + 1}}</span>
<span *ngIf="orderForm.controls.opticianOrders.controls.products.controls.length > 1"
(click)="removeProduct(i)">
</span>
</div>
<div [formGroupName]="i">
<div>
<label>Product name</label>
<input type="text" formControlName="name">
</div>
</div>
</div>
</div>
<button type="submit" [disabled]="!orderForm.valid">Submit</button>
</form>
Please replace your HTML Code as per below
<form [formGroup]="orderForm" (ngSubmit)="save()">
<!-- name -->
<div class="form-group">
<label>Name</label>
<input type="text" formControlName="name">
</div>
<!-- surName -->
<div class="form-group">
<label>Last Name</label>
<input type="text" formControlName="surName">
</div>
<div class="form-group">
<label>Order Description</label>
<input type="text" formControlName="orderDescription">
</div>
<div formArrayName="products">
<div *ngFor="let product of orderForm.controls.products['controls']; let i=index">
<div>
<span><strong>Product {{i + 1}}</strong></span>
<span class="fa fa-times" *ngIf="orderForm.controls['products'].controls.length > 1" (click)="removeProduct(i)">
</span>
</div>
<div [formGroupName]="i">
<div>
<label>Product name</label>
<input type="text" formControlName="name">
</div>
<div>
<label>Product Manufacturer name</label>
<input type="text" formControlName="manufacturerName">
</div>
</div>
</div>
<div class="margin-20">
<a (click)="addProduct()" style="cursor: pointer; text-transform: uppercase; font-weight: 500">
Add another Entry +
</a>
</div>
</div>
<button class="btn btn-primary" type="submit" [disabled]="orderForm.invalid">Submit</button>
</form>
Please replace TS code as per below. I have used a trick in save form method, check whether it works for you or not?
constructor(private fb: FormBuilder) { }
orderForm: FormGroup;
ngOnInit() {
this.orderForm = this.fb.group({
name: ['', Validators.required],
surName: ['', Validators.required],
orderDescription: ['', Validators.required],
products: this.fb.array([
this.initProduct()
])
});
}
save() {
console.log(this.orderForm.value);
const obj = {
name: this.orderForm.value.name,
surName: this.orderForm.value.surName,
orderDescription: this.orderForm.value.orderDescription,
opticianOrders: {
products: this.orderForm.value.products
},
};
console.log(obj);
}
initProduct() {
return this.fb.group({
name: ['', Validators.required],
manufacturerName: ['', Validators.required]
})
}
addProduct() {
const control = <FormArray>this.orderForm.controls['products'];
control.push(this.initProduct());
}
removeProduct(i: number) {
const control = <FormArray>this.orderForm.controls['products'];
control.removeAt(i);
}
Your stackblitz code does not work. You did not import the ReactiveFormsModule and you implemented the forms code in the hello.component.ts also you put the template code in the app.component.html.
See my working sample on stackblitz. It let you add (click on Add) and remove (click on 'x') products from your FormArray.
Form value with two products:
{
name: 'John',
surName: 'Doe',
opticianOrders: {
orderDescription: '1234',
products: [
{ name: 'Cookies', manufacturerName: '' },
{ name: 'More Cookies', manufacturerName: '' }
]
}
}
For typescript this.orderForm.controls.opticianOrders is an AbstractControl which has no controls property. You have to cast it to a FormGroup first. Same with products, you have to cast it to a FormArray.
removeProduct(i: number){
const aFormGroup = this.orderForm.controls.opticianOrders as FormGroup;
const aFormArray = aFormGroup.controls.products as FormArray;
aFormArray.removeAt(i);
}
Try this
orderForm.controls.opticianOrders.controls

Angular 5 not showing user entered values from formarray

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

Categories

Resources