I created a dynamically adding/deleting rows using Angular reactive forms. Rows are getting added and deleted. But how you can send all these row values from Angular application to java controller.I am pasting the code below.
app.component.html
<div class="container">
<h3 class="page-header">Seasons</h3>
<button type="button" class="btn btn-primary" (click)="addTeam()">Add New Row</button><br/>
<form [formGroup] = "seasonsForm">
<div formArrayName = "teamRows">
<div *ngFor = "let team of seasonsForm.controls.teamRows.controls; let i=index" [formGroupName] = "i">
<h4>Team- #{{i+1}}</h4>
<div class="form-group">
<label>Team Name</label>
<input formControlName = "teamName" class="form-control">
</div>
<div class="form-group">
<label>Stadium</label>
<input formControlName = "stadiumName" class="form-control">
</div>
<div class="form-group">
<label>Capacity</label>
<input formControlName = "capacity" class="form-control">
</div>
<div class="form-group">
<label>Founded</label>
<input formControlName = "founded" class="form-control">
</div>
<div class="form-group">
<label>Head Coach</label>
<input formControlName = "headCoach" class="form-control">
</div>
<div class="form-group">
<label>Last Season</label>
<input formControlName = "lastSeason" class="form-control">
</div>
<button *ngIf = "seasonsForm.controls.teamRows.controls.length" (click) = "deleteTeam(i)" class="btn btn-danger">Delete Button</button>
</div>
</div>
</form>
<pre>{{ seasonsForm.value |json }}</pre>
</div>
app.component.ts
import { Component, OnInit } from '#angular/core';
import { FormGroup,FormArray,FormBuilder,Validators} from '#angular/forms';
import { Teams } from '../service/http-client.service';
#Component({
selector: 'app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
public seasonsForm: FormGroup;
public teams:Teams[];
constructor(private _fb: FormBuilder) { }
ngOnInit() {
this.seasonsForm = this._fb.group({
teamRows: this._fb.array([this.initTeamRows()])
});
}
get formArr() {
return this.seasonsForm.get('teamRows') as FormArray;
}
initTeamRows() {
return this._fb.group({
teamName: [''],
stadiumName: [''],
capacity: [''],
founded: [''],
headCoach: [''],
lastSeason: ['']
});
}
addTeam() {
this.formArr.push(this.initTeamRows());
}
deleteTeam(index: number) {
this.formArr.removeAt(index);
}
}
createTeam(): void {
this.httpClient.post<Teams>("http://localhost:8080/addTeam", seasonsForm);
.subscribe( res => {
alert("Successful");
})
};
export class Teams {
constructor(
public teamName:string,
public stadiumName:string,
public capacity:string,
public founded:string,
public headCoach:string,
public lastSeason:string,
) {}
}
I tried to send entire formGroup(seasonsForm) but it is getting failed.I am relatively new to Angular and i searched in Google but i didn't find much help. So any help in this would be appreciated.
you need to send form value on your createTeam function. If you console.log(seasonsForm), you can see there are some other attributes which is only about your form.
Also if you want you can check is form valid.
createTeam(): void {
if(seasonsForm.valid){
this.httpClient.post<Teams>("http://localhost:8080/addTeam", seasonsForm.value);
.subscribe( res => {
alert("Successful");
})
};
}
First of all if you are using NoSQL database then you can send a JSON file containing arrays. So here i decided to send a json file containing Array values to server side and then i converted the form group name to JSON.Stringify. In Server side you can retrieve that json in String format and parse it and send to DB. Here is the code below
onSubmit() {
this.httpClient.post("http://localhost:8080/addTeams",JSON.stringify(this.seasonsForm.value))
.subscribe((response: Response) => {
})
alert("Successful");
}
Related
I am trying to achieve edit form with angular and I am having an error from binding value with [(ngModel)]
ERROR TypeError: Cannot read property 'name' of undefined
Here is my typescript code:
import { Component, OnInit } from "#angular/core";
import { HttpService } from "./../http.service";
import { ActivatedRoute, Router } from "#angular/router";
#Component({
selector: "app-edit",
templateUrl: "./edit.component.html",
styleUrls: ["./edit.component.scss"],
})
export class EditComponent implements OnInit {
id: string;
private sub: any;
author: any;
error: any;
constructor(
private _httpService: HttpService,
private _route: ActivatedRoute,
private _router: Router
) {}
ngOnInit() {
this.sub = this._route.params.subscribe((params) => {
this.id = params["id"];
});
this.oneAuthorInfoRetrieve();
}
oneAuthorInfoRetrieve() {
let observable = this._httpService.getOneTask(this.id);
observable.subscribe((data) => {
console.log("Successfully got data from get one author", data);
this.author = data["data"];
});
}
onEdit() {
let observable = this._httpService.editTask(this.id, this.author);
observable.subscribe((data) => {
console.log("Successfully update", data);
});
}
}
And here is my HTML code:
<a [routerLink]="['/home']"> Home </a>
<b>
<p>Edit this Author:</p>
</b>
<form class="border">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" class="form-control" name="name" [(ngModel)]="author.name">
</div>
<div class="form-group">
<button class="btn btn-danger" id="cancel">Cancel</button>
<button class="btn btn-primary" id="submit" (click)="onEdit()">Submit</button>
</div>
</form>
What can I do to fix this error?
DemoCreate your author model rather than using any
export class Author{
public name:string="";
constructor(){}
}
then in component
author: Author;
in ngOnInit or constructor initialize it
this.author=new Author();
You have this error because author is undefined. You can add a value to author throw a constructor or simply at the declaration author: any = {};
Or, you can display the form only of author is defined :
<form class="border" *ngIf="!!author">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" class="form-control" name="name" [(ngModel)]="author.name">
</div>
<div class="form-group">
<button class="btn btn-danger" id="cancel">Cancel</button>
<button class="btn btn-primary" id="submit" (click)="onEdit()">Submit</button>
</div>
</form>
You have to initialize object author. Because at first author.name does not exist.
Solution:
// declare author such as
author = {};// not null
The answer as you see that the author is undefined, and this also appears whenever an instance is undefined but you try to access it's properties!
Ex:
[(ngModel)]="author.name" // But author is undefined, it'll tell you that the 'name' is undefined,
// instead of 'author' remember this.
But if [(ngModel)]="author" // This will never cause an error
One more thing, author = {}; will not solve your problem, you should define a class (Recommended) like author = new author('Fes', 'Nguyen'); because {} have no property if you don't init or set value for it pro!
I'm using angular 9 and I need to bind HTML forms data to the angular class.
I have the following angular class:
export interface MyData {
field1: string,
textArea1: string,
textArea2: string
}
and I have the following HTML code:
<div class="modal-body">
<label>Field1</label>
<input type="text" class="form-control" aria-label="Process id"/>
<label>TextArea1</label>
<textarea class="form-control" aria-label="With textarea"></textarea>
<label>TextArea2</label>
<textarea class="form-control" aria-label="With textarea"></textarea>
</div>
How can I bind data from the HTML form to the MyData angular class?
Why don't you use Angular Form for that ?
In your component:
import { Component } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms';
#Component({
selector: 'app-your-component-selector',
templateUrl: './your-component.component.html',
styleUrls: ['./your-component.component.css']
})
export class YourComponent {
/** new form group instance */
form: FormGroup;
constructor() {}
ngOnInit(): void {
this.initForm();
}
initForm(): void {
/** field1, textArea1, textArea2 are form control instances */
this.form = new FormGroup({
field1: new FormControl(''),
textArea1: new FormControl(''),
textArea2: new FormControl(''),
});
}
onSubmit(): void {
// code here after submit
console.info(this.form.value);
}
}
A form group tracks the status and changes for each of its controls, so if one of the controls changes, the parent control also emits a new status or value change.
In your template:
<div class="modal-body">
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<label>Field1</label>
<input type="text" class="form-control" formControlName="field1" aria-label="Process id"/>
<label>TextArea1</label>
<textarea class="form-control" formControlName="textArea1" aria-label="With textarea"></textarea>
<label>TextArea2</label>
<textarea class="form-control" formControlName="textArea2" aria-label="With textarea"></textarea>
</form>
</div>
More information here
I have this template-driven form:
<form #form="ngForm" (submit)="submitForm()" novalidate>
<div class="form-group" [class.has-error]="linkName.invalid">
<label class="control-label" for="name">Name</label>
<input #linkName="ngModel" type="text" class="form-control" name="name" id="name" [(ngModel)]="finalData.name" required />
<div *ngIf="linkName.invalid" class="alert alert-danger">Name is required</div>
</div>
<div class="form-group">
<label for="url">Url</label>
<input type="text" class="form-control" id="url" name="url" [(ngModel)]="finalData.url" readonly/>
</div>
<div class="checkbox" *ngFor="let tag of finalData.tags; index as i" [attr.data-index]="i">
<label><input type="checkbox" name="{{ 'checkbox' + tag }}" id="{{ 'checkbox' + tag }}" (ngModel)="finalData.tags[i]"/>{{ tag }}</label>
</div>
<button type="submit" [disabled]="form.invalid" class="btn btn-primary btn-success">Save</button>
</form>
I want to POST value from checkboxes based on whether they checked or not.
This way with one-way binding (ngModel) it will POST all tags whether they checked or not. If I use two-way binding [(ngModel)] it will POST boolean values and it will change name and id based on boolean value, which I don't want.
Example:
If i check this I want POST foo instead of true
<label><input type="checkbox" name="footag" id="footag" value="foo" [(ngModel)]="finalData.tags[i]"/>foo</label>
This is component used for data binding:
import { Component, OnInit, Injectable } from "#angular/core";
import { DataService } from "../shared/dataService";
import { FinalFormData } from "../shared/finalFormData";
import { ActivatedRoute, Router } from '#angular/router';
import { Observable } from "rxjs/Observable";
import { NgForm } from "#angular/forms";
#Component({
selector: "final-form",
templateUrl: "finalForm.component.html"
})
export class FinalFormComponent implements OnInit{
constructor(private data: DataService, private route: ActivatedRoute, private router: Router) {
}
public finalData: FinalFormData;
public errorMessage = "";
public isBusy = true;
submitForm() {
this.data.postData(this.finalData)
.subscribe(data => {
this.finalData = data;
this.router.navigate(["/"]);
}, err => console.log(err));
}
ngOnInit(): void {
//let url = encodeURIComponent(this.route.snapshot.queryParams['url']);
//this.data.loadData(url)
// .subscribe(finalData => {
// this.finalData = finalData;
// });
this.finalData = this.route.snapshot.data['finalData'];
}
}
FinalFormData class:
export class FinalFormData {
name: string;
url: string;
dateCreated: Date;
tags: any[];
}
you can use the ngModelChange method to pass the value and set it to any variable you want. Refer sample code snippet below:
<label><input type="checkbox" name="footag" id="footag" value="foo" [ngModel]="finalData.tags[i]" (ngModelChange)="CheckBoxValueChange('foo',finalData)"/>foo</label>
in the component.ts file, you can access the value and set it to any variable you want:
CheckBoxValueChange(checkboxValue:string,finalData:any){
finalData.checkboxText=checkboxValue;
alert(checkboxValue);
}
I have an edit profile page. So when the user clicks on the edit profile page the users details should be displayed in the input tag fields in the HTML. But I am unable to display the details I am retrieving.
edit-profile.component.html
<form novalidate (ngSubmit)="onFormSubmit(signupForm)" #signupForm="ngForm">
<div class="form-inputs clearfix">
<div class="row">
<div class="col-md-6">
<p>
<label class="required">First Name<span>*</span></label>
<input
type="text"
[value]="accountDetails.firstName"
name="firstName"
[(ngModel)] = "user.firstName"
#firstName = "ngModel"
required><p>{{accountDetails.firstName}} </p>
<span *ngIf="firstName.invalid && (firstName.dirty || firstName.touched)" class="input-error">
<span *ngIf = "firstName.errors?.required">
First Name field can't be blank
</span>
</span>
</p></form>
edit-profile.component.ts
import { Component, OnInit } from '#angular/core';
import { ApiServiceProvider } from '../services/api.service';
#Component({
selector: 'app-edit-profile',
templateUrl: './edit-profile.component.html',
styleUrls: ['./edit-profile.component.css']
})
export class EditProfileComponent implements OnInit {
public user: any = {};
public accountDetails: any = {}
constructor(
private api: ApiServiceProvider
) { }
ngOnInit() {
let profile = JSON.parse(localStorage.getItem("profile"));
this.accountDetails = profile.user;
console.log(this.accountDetails);
}
public onFormSubmit({ value, valid }: { value: any, valid: boolean }) {
this.user = value;
this.api.put("/users/editprofile", value.userId, false)
.subscribe((data) => {
console.log(data)
localStorage.setItem("profile", JSON.stringify(data));
location.href = "/profile"
}, (err) => {
alert("Registartion failed " + err);
})
}
}
you only populate your accountDetails variable but you try to bind your user variable.
so you have:
this.accountDetails = profile.user;
but you bind your input to the user variable:
<input type="text" [(ngModel)]="user.firstName" #firstName="ngModel" required>
Either populate your user variable:
this.user = profile.user;
or bind to your account details variable:
<input type="text" [(ngModel)]="accountDetails.firstName" #firstName="ngModel" required>
Also you need to close your div clearfix, div row and div column correctly before closing the form tag. </div></div></div></form>
i'm working on angular 4 form and set some validations on the input field but the validation is show when the page load's but i want the validation when the form is submitted or the email pattern is not valid.
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)"
[class.error]="!myForm.valid && myForm.touched">
<div class="field" [class.error]="!email.valid && email.touched">
<label for="email">Email</label>
<input type="email" id="email" name="email" [formControl]="email">
<div *ngIf="!email.valid"
class="ui error message">Email is invalid</div>
<div *ngIf="email.hasError('required')"
class="ui error message">Email is required</div>
</div>
<div *ngIf="!myForm.valid"
class="ui error message">Form is invalid</div>
<button type="submit">login</button>
</form>
Typescript code:
function EmailValidator(control: FormControl): { [s: string]: boolean } {
if (!control.value.match('^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$'))
{
return {invalidEmail: true};
}
}
#Component({
selector: 'app-login-form',
templateUrl: './login-form.component.html',
styleUrls: ['./login-form.component.css']
})
export class LoginFormComponent implements OnInit {
myForm: FormGroup;
email: AbstractControl;
constructor(fb:FormBuilder) {
this.myForm = fb.group({
'Email': ['', Validators.compose([
Validators.required, EmailValidator])
]
});
this.email = this.myForm.controls['Email'];
}
onSubmit(form: string): void {
console.log('you submitted value:', form);
}
}
you can use
<div
*ngIf="myForm.get('email').hasErrors('required') &&
myForm.get('email').touched">
Email is required
</div>
And adapt hasError to your validation