How to get the value of dynamically created input in angular - html

I have created an empty hash map of a 'question' object in angular according to the no. of questions given in the earlier page.Then i am rendering the 'question' objects in the hash map when the page initializes.I want to get the values of the inputs given for each question object when the user clicks 'add paper' button which calls the 'test()' function.What is the best way to do this?I was thinking of using viewChild to get the values,but it returns undefined.Thanks in advance.
Component File
import { Component, OnInit, ViewChild,ElementRef, ViewChildren } from '#angular/core';
import { SharedserviceService } from "../services/sharedservice.service";
#Component({
selector: 'app-admin-paper',
templateUrl: './admin-paper.component.html',
styleUrls: ['./admin-paper.component.css']
})
export class AdminPaperComponent implements OnInit {
public paperID:any;
public noOfQuestions : number ;
public message : any;
public i : number ;
public questionSet = {};
public question0 : any;
#ViewChildren('testchild') testchild :ElementRef;
constructor(private shared : SharedserviceService) { }
ngOnInit() {
this.shared.currentMessage.subscribe((message)=>{
this.message = message;
});
this.paperID = this.message.paperID;
this.noOfQuestions = this.message.noOfQuestions;
for (this.i =0;this.i < this.noOfQuestions;this.i++){
const question = {
'paperID': this.paperID,
'questionID': this.i,
'question': '',
'answers': [],
'correctAnswer':''
};
this.questionSet[this.i] = question;
}
console.log(this.questionSet);
}
test(){
//console.log(this.testchild.nativeElement.value);
for (this.i =0;this.i < this.noOfQuestions;this.i++){
const question = {
'paperID': this.paperID,
'questionID': this.i,
'question': `question${this.i}');`,
'answers': [`question${this.i}answer0`,`question${this.i}answer1`,`question${this.i}answer2`,`question${this.i}answer3`],
'correctAnswer':'vghvhg'
};
console.log(question);
this.questionSet[this.i] = question;
}
console.log("clicked");
console.log(this.questionSet);
}
}
HTML File
<ng-container *ngIf="questionSet" >
<div class="panel panel-widget border-right" *ngFor="let question of questionSet | keyvalue; let i= index;" style="text-align: left; background-color: white; padding: 10px; border-radius: 10px;border-style: solid; border-width: 3px; border-color: #1aa3ff;">
<div class="container">
<div class="row">
<div class="form-group col-md-10">
<label> Question {{question.value.questionID+1}}</label>
<input type="text" class="form-control" #question{{i}} aria-describedby="emailHelp" placeholder="Enter question Here">
</div>
</div>
<div class= "row">
<div class="col-sm-2">
<div class="form-group">
<label>Answer 1</label>
<input type="email" class="form-control" id="question{{i}}answer0" aria-describedby="emailHelp" placeholder="Answer 1">
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label>Answer 2</label>
<input type="email" class="form-control" id="question{{i}}answer1" aria-describedby="emailHelp" placeholder="Answer 2">
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label>Answer 3</label>
<input type="email" class="form-control" id="question{{i}}answer2" aria-describedby="emailHelp" placeholder="Answer 3">
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label>Answer 4</label>
<input type="email" class="form-control" id="question{{i}}answer3" aria-describedby="emailHelp" placeholder="Answer 4">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label>Correct Answer</label>
<input type="text" class="form-control" aria-describedby="emailHelp" placeholder="Correct Answer">
</div>
</div>
<div class="col-sm-6">
<button type="submit" style="margin-top:6%" (click)="addQuestion($event,question,'new')" class="btn btn-primary mb-2">Add Question</button>
</div>
</div>
<br><br>
</div>
</ng-container>
<button type="button" class="btn btn-primary btn-lg btn-block" (click)="test()">Add Paper</button>

*ngIf="questionSet" always be true because an empty object is a truthy value in js. Convert your ngOnInit like this
ngOnInit() {
this.shared.currentMessage.subscribe((message)=>{
this.message = message;
this.paperID = this.message.paperID;
this.noOfQuestions = this.message.noOfQuestions;
for (let i =0; i < this.noOfQuestions; i++){
const question = {
'paperID': this.paperID,
'questionID': this.i,
'question': '',
'answers': [],
'correctAnswer':''
};
this.questionSet[this.i] = question;
}
console.log(this.questionSet);
});
}

Related

how to use checkbox in reactive angular form

I am new to angular, currently I am looking checkboxes in angular , I have three checkboxes and I have to show checked or unchecked checkboxes in UI.
I am getting enabled/disabled from json , I need to show if am getting enabled means checkbox should be checked and disabled means unchecked checkbox.
This is what am trying in html
<form [formGroup]="portFilterGroup">
<div class="form-group row">
<div class="col-md-4 text-left" id="email">
<label for="email"><input type="checkbox" (change)="onChecked($event)" formcontrolName="emailData" value="{{emailData}}" [checked]="isChecked" >
<b>Email(POP3, IMAP, SMTP)</b></label>
</div>
</div>
<div class="form-group row">
<div class="col-md-4 text-left" id="ftp">
<label for="ftp"><input type="checkbox" formcontrolName="ftpData" [checked]="isChecked" value="{{ftpData}}"> <b>FTP</b></label>
</div>
</div>
<div class="form-group row">
<div class="col-md-4 text-left" id="http">
<label for="http"><input type="checkbox" formcontrolName="httpData"
[checked]="isChecked"> <b>HTTP</b></label>
</div>
</div>
</form>
typescript file
portFilterForm(){
this.portFilterGroup = this.fb.group({
emailData: new FormControl(''),
ftpData: new FormControl(''),
httpData: new FormControl('')
})
}
onChecked(e){
console.log("e", e.target)
if (e.target == 'enabled'){
this.isChecked = true;
}
else{
this.isChecked = false;
}
}
gettingData(){
this.httpClient.get("assets/json/data.json").subscribe((data:any) =>{
console.log(data);
this.emailData = this.onChecked(data.email)
this.httpData = this.onChecked(data.http)
})
}
and the json file be
{
"email": "enabled",
"ftp": "disabled",
"http": "enabled"
}
this is the code am trying, but am not get the expecting output(enabled means checked and disabled means unchecked) can anyone help me to this?
Ok so you can use the angular way read here
html
<form [formGroup]="portFilterGroup">
<div class="form-group row">
<div class="col-md-4 text-left" id="email">
<label
><input
type="checkbox"
[formControl]="portFilterGroup.controls['emailData']"
/> <b>Email(POP3, IMAP, SMTP)</b></label
>
</div>
</div>
<div class="form-group row">
<div class="col-md-4 text-left" id="ftp">
<label
><input
type="checkbox"
[formControl]="portFilterGroup.controls['ftpData']"
/> <b>FTP</b></label
>
</div>
</div>
<div class="form-group row">
<div class="col-md-4 text-left" id="http">
<label
><input
type="checkbox"
[formControl]="portFilterGroup.controls['ftpData']"
/> <b>HTTP</b></label
>
</div>
</div>
</form>
{{ portFilterGroup.value | json }}
<button (click)="gettingData()">submit</button>
ts file
import { Component } from '#angular/core';
import { FormControl, FormGroup, FormBuilder, FormArray } from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
name = 'Angular 6';
portFilterGroup: FormGroup;
constructor(private fb: FormBuilder) {
this.portFilterForm();
}
portFilterForm() {
this.portFilterGroup = this.fb.group({
emailData: new FormControl(false),
ftpData: new FormControl(false),
httpData: new FormControl(false),
});
}
gettingData() {
console.log(this.portFilterGroup.value);
// this.httpClient.get('assets/json/data.json').subscribe((data: any) => {
// console.log(data);
// this.emailData = this.onChecked(data.email);
// this.httpData = this.onChecked(data.http);
// });
}
}
stackblitz

Object is possibly 'null' in typescript/angular

I have been learning angular and typescript for the past couple of days and I've hit an error I can't really fix when calling methods in the *ngIf text field on my member-form.component.html.
The member-component.ts is:
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { MemberService } from '../member.service';
import { Member } from '../member';
import { FormGroup, FormBuilder, Validators, FormControl } from "#angular/forms";
#Component({
selector: 'app-member-form',
templateUrl: './member-form.component.html',
styleUrls: ['./member-form.component.css']
})
export class MemberFormComponent implements OnInit {
registerForm: FormGroup
//submitted = false;
constructor(
private route: ActivatedRoute,
private router: Router,
private memberService: MemberService,
private formBuilder: FormBuilder) {
let formControls = {
surname: new FormControl('', [
Validators.required,
Validators.pattern("[A-Za-z .'-]+"),
]),
name: new FormControl('', [
Validators.required,
Validators.pattern("[A-Za-z .'-]+"),
]),
email: new FormControl('', [
Validators.required,
Validators.email
]),
password: new FormControl('', [
Validators.required
]),
password2: new FormControl('', [
Validators.required,
]),
phone: new FormControl('', [
Validators.required,
Validators.minLength(10),
Validators.maxLength(10),
Validators.pattern("[0-9]+")
]),
}
this.registerForm = this.formBuilder.group(formControls)
}
ngOnInit(): void {}
get name() { return this.registerForm.get('name') }
get surname() { return this.registerForm.get('surname') }
get phone() { return this.registerForm.get('phone') }
get email() { return this.registerForm.get('email') }
get password() { return this.registerForm.get('password') }
get password2() { return this.registerForm.get('password2') }
public onSubmit(): void {
this.memberService.registerMember(this.registerForm.value).subscribe(result => this.gotoMemberList());
}
public gotoMemberList() {
this.router.navigate(['/members']);
}
}
and the html file is:
<link rel="stylesheet" href="member-form.component.css">
<div class="card my-5">
<div class="card-body">
<form [formGroup]="registerForm"(ngSubmit)="onSubmit()"style="border: 2px solid #ccc">
<h1>Sign Up</h1>
<p>Please fill in this form to register</p>
<hr>
<div class="form-group">
<label for="surname"><b>Surname</b></label>
<input formControlName="surname"
id="surname"
type="text"
class="form-control"
placeholder="Enter your surname">
<div *ngIf="surname.touched && surname.invalid">
<small *ngIf="surname.errors.required" class="text-danger">Surname is required</small><br>
<small *ngIf="surname.errors.pattern" class="text-danger">Invalid Surname</small><br>
</div>
</div>
<div class="form-group">
<label for="name"><b>Name</b></label>
<input formControlName="name"
id="name"
type="text"
class="form-control"
placeholder="Enter your name">
<div *ngIf="name.touched && name.invalid">
<small *ngIf="name.errors.required" class="text-danger">Name is required</small><br>
<small *ngIf="name.errors.pattern" class="text-danger">Invalid Name</small><br>
</div>
</div>
<div class="form-group">
<label for="email"><b>Email</b></label>
<input formControlName="email"
id="email"
type="email"
class="form-control"
placeholder="Enter your email address">
<div *ngIf="email.touched && email.invalid">
<small *ngIf="email.errors.required" class="text-danger">Email is required</small><br>
<small *ngIf="email.errors.pattern" class="text-danger">Invalid Email</small><br>
</div>
</div>
<div class="form-group">
<label for="password" class="control-label"><b>Password</b></label>
<input formControlName="password"
id="password"
type="password"
class="form-control"
placeholder="Enter your password">
<div *ngIf="password.touched && password.invalid">
<small *ngIf="password.errors.required" class="text-danger">Password is required</small><br>
</div>
</div>
<div class="form-group">
<label for="password2"><b>Confirm password</b></label>
<input formControlName="password2"
id="password2"
type="password"
class="form-control"
placeholder="Enter your password again">
<div *ngIf="password2.touched && password2.invalid">
<small *ngIf="password2.errors.required" class="text-danger">Password is required</small><br>
</div>
<div *ngIf="password2.valid && password2.value != password.value" class="text-danger">
The passwords entered do not match
</div>
</div>
<div class="form-group">
<label for="phone"><b>Phone Number</b></label>
<input formControlName="phone"
id="phone"
type="tel"
class="form-control"
placeholder="Enter your phone number">
<div *ngIf="phone.touched && phone.invalid">
<small *ngIf="phone.errors.required" class="text-danger">Phone is required<br></small>
<small *ngIf="phone.errors.pattern" class="text-danger">Invalid Phone<br></small>
<small *ngIf="phone.errors.minlength" class="text-danger">Phone must be 10 characters </small>
<!-- <small *ngIf="phone.errors.maxlength" class="text-danger">Phone must contain a maximum of 13 characters</small>-->
</div>
</div>
<br>
<div class="form-group">
<button type="submit" class="btn btn-primary" [disabled]="registerForm.invalid || password.value != password2.value">Sign Up</button>
</div>
</form>
</div>
</div>
Basically, I'm getting an error saying "Object is possibly 'null' on every .errors, .pattern, .required, .invalid, .touched in the *ngIf fields of my html file.
Anyone knows what could be going wrong here?
The reason is a strictNullChecks which is turned on by default.
You can turn it off in tsconfig.json but that is not advised
"angularCompilerOptions": {
"strictNullChecks": false,
...
}
as #CherryDT commented you can add ?. to each reference
or add as first check the object itself in this case surname
<div *ngIf="surname && surname.touched && surname.invalid">
More info: https://blog.angular.io/angular-cli-strict-mode-c94ba5965f63
?. is called "optional chaining" and you can read more about it here
And as i know you can not use it like this "name.touched && name.invalid",
You need to call method of the your form.
check it out
demo angular reactive forms

How to verify validion of form inside form?

I'm trying to verify a form that's inside a form.
The idea is to create a user's html page with the option to create a contact list.
My goal is to verify both forms with one click on the 'Save User Profile' button.
My question is How to verify the validion of the inner form inside the main form?
NO BOOTSTRAP AND OTHERS.
Main form:
HTML:
<div class="container"
style="width: 60%;">
<h5>User Profile</h5>
<div>
<form (ngSubmit)="onSubmit()"
#f=ngForm>
<!-- Name -->
<div class="column">
<label for="name"
style="margin-left: 5px;">Name</label><br>
<input type="text"
[(ngModel)]="user.name"
name="name"
id="name"
required
minlength="2"
maxlength="30"
#n="ngModel">
<p *ngIf="!n.valid && n.touched"
style="color: red;"> Please insert a name with 2-30 chars</p>
</div>
<!-- Organization -->
<div class="column">
<label for="orga"
style="margin-left: 5px;">Organization</label><br>
<input type="text"
[(ngModel)]="user.organization"
name="orga"
id="orga">
</div>
<br><br><br><br><br>
<h5>Contact Information</h5>
<div class="box">
<app-user-card *ngFor="let c of contacts; let i = index"
[id]="i"
[user]="user"></app-user-card>
<br><br>
</div>
<button type="button"
class="btn-add"
(click)="addContact()">Add Contact</button>
<button class="btn-save"
type="submit"
[disabled]="!f.valid">Save User Profile
</button>
</form>
</div>
TS:
export class UsersListComponent implements OnInit {
users: User[] = []
user: User = {
name: '',
organization: '',
contacts: []
}
id: number
contacts: Contact[] = []
contact: Contact = {
id: 0,
type: '',
label: '',
contact: ''
}
constructor() { }
ngOnInit(): void {
this.user.contacts = this.contacts
}
addContact() {
this.contacts.push(new Contact(this.id, this.contact.type, this.contact.label, this.contact.contact))
}
onSubmit() {
/* Upgrade option: Check if a user exists on the system and view his contacts*/
this.users.push(new User(this.user.name, this.user.organization, this.contacts))
console.log(this.users);
}
}
inner form:
HTML:
<div class="card">
<form #f = "ngForm">
<div class="column">
<label for="contactType">Type of Contact</label><br>
<select id="contactType"
[(ngModel)]=contact.type
name="cotactType"
style="width: 95%;"
required>
<option value="email">Email</option>
<option value="phone">Phone</option>
</select>
</div>
<div class="column">
<label for="label">Contact Label</label><br>
<input type="text"
[(ngModel)]="contact.label"
id="label"
name="lable"
style="width: 95%;"
required
minlength="2"
maxlength="20"
#l>
<p *ngIf="!l.valid && l.touched"
style="color: red;">Label is required!</p>
</div>
<div>
<label for="contact"
style="margin-left: 5px;">Email/Phon No.</label><br>
<input type="text"
[(ngModel)]=contact.contact
required
id="contact"
name="contact"
style="width: 98%;"
#c>
<p *ngIf="!c.valid && c.touched"
style="color: red;">Email/Phon No is required!</p>
</div>
<button type="button"
class="btn-remove"
style="left: 69%;position: relative;">Remove</button>
</form>
TS:
#Component({
selector: 'app-user-card',
templateUrl: './user-card.component.html',
styleUrls: ['./user-card.component.css']
})
export class UserCardComponent implements OnInit {
contact: Contact = {
id: 0,
type: '',
label: '',
contact: ''
}
#ViewChild("f") contactDetails: NgForm
#Input() id: number
constructor() { }
ngOnInit(): void {}
}

Angular validations showing during the page load

We are working on the Angular 4 form and set some validations on the input field but the validation is showing when the page load's but we want the validation when the form is submitted or the field is not valid or filled.
Component.html
<div class="headerbutton-group row">
<i class="fa fa-save header-buttons" tooltip ="Save" tabindex="1" (click)="onSave($event)"></i>
<i class="fa fa-close header-buttons" tooltip ="Close" (click)="onCancel($event)"></i>
</div>
<form [formGroup]="editForm" class="col-md-12 ">
<div class="form-group row">
<div class="col-md-6 padding-Mini">
<label class="col-md-12 col-form-label padding-bottom-Mini" for="txtName">Name</label>
<div class="col-md-12">
<input type="text" id="txtName" name="txtName" class="form-control" placeholder="Name" formControlName="name" [class.is-invalid]="!editForm.controls.name.valid" [class.is-valid]="editForm.controls.name.valid" required>
<div class="invalid-feedback" [style.visibility]=
"editForm.controls.name.valid ? 'hidden':'visible'"> Name is required</div>
</div>
</div>
<div class="col-md-6 padding-Mini">
<label class="col-md-12 col-form-label padding-bottom-Mini" for="txtName">Description</label>
<div class="col-md-12">
<input type="text" id="txtDescription" name="txtDescription" class="form-control"
placeholder="Description" formControlName="description">
</div>
</div>
</div>
</form>
Component.ts
#Component({
selector: 'app-edit-form',
templateUrl: './component.html'
})
export class LoginFormComponent implements OnInit {
constructor(fb:FormBuilder) {
public editForm: FormGroup = new FormGroup({
name : new FormControl('', Validators.required),
description : new FormControl(''),
});
}
public onSave(e): void {
if (this.editForm.valid) {
e.preventDefault();
this.save.emit(this.editForm.value);
} else {
this.validateAllFormFields(this.editForm);
}
}
public onCancel(e): void {
e.preventDefault();
this.closeForm();
}
private validateAllFormFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
}
});
}
}
// Tried this too editForm.controls.name.pristine
We don't know what we are missing. Kindly help us, with useful documents/ Demo's.
try changing this
<div class="invalid-feedback" [style.visibility]="editForm.controls.name.valid ? 'hidden':'visible'">
Name is required
</div>
to this
<div class="invalid-feedback" *ngIf="!editForm.controls.name.valid && editForm.controls.name.touched">
Name is required
</div>
adding a test on "touched" will fix your problem !

Angular 6 file upload with other form data

I have enter data user details first_name,last_name,phone_number and profile_pic but file is not upload in other form data how can i upload file with other form data??
user-form.component.ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import { HttpClient } from '#angular/common/http';
import { UserService } from '../user.service';
import { FileUploader, FileSelectDirective } from 'ng2-file-upload/ng2-file-upload';
#Component({
selector: 'user-form',
templateUrl: './user-form.component.html',
styleUrls: ['./user-form.component.scss']
})
export class UserFormComponent {
angForm: FormGroup
router: Router;
constructor(private userservice: UserService, private fb: FormBuilder, private _route: Router) {
this.createForm();
this.router = _route;
}
createForm() {
this.angForm = this.fb.group({
first_name: ['', Validators.required],
last_name: ['', Validators.required],
// email: ['', Validators.required,Validators.email],
email: ['', Validators.compose([Validators.required, Validators.email])],
phone_number: ['', Validators.compose([Validators.required, Validators.maxLength(10)])],
profile_pic:[]
});
}
addUser(first_name, last_name, email, phone_number,profile_pic) {
var data = {
first_name: first_name,
last_name: last_name,
email: email,
phone_number: phone_number,
profile_pic: profile_pic,
}
console.log(data);
// this.uploader.onAfterAddingFile = (file) => { file.withCredentials = false; }
// public uploader : FileUploader;
// uploader.onAfterAddingFile = (file) => { file.withCredentials = false; }
this.userservice.addUser(data);
this.router.navigate(['/pages/users/list']); //Redirection path
}
}
user-form.component.html
<div class="row justify-content-center">
<div class="col-lg-8">
<nb-card>
<nb-card-header>Add User</nb-card-header>
<nb-card-body>
<!-- <div [formGroup]="form"> -->
<form [formGroup]="angForm" novalidate>
<div class="row full-name-inputs form-group">
<div class="col-sm-6 input-group">
<input type="text" placeholder="First Name" formControlName="first_name" class="form-control" #firstName/>
</div>
<div *ngIf="angForm.controls['first_name'].invalid && (angForm.controls['first_name'].dirty || angForm.controls['first_name'].touched)" class="alert alert-danger" >
<div *ngIf="angForm.controls['first_name'].errors.required">
First Name is required.
</div>
</div>
<div class="col-sm-6 input-group">
<input type="text" placeholder="Last Name" formControlName="last_name" class="form-control" #lastName/>
</div>
<div *ngIf="angForm.controls['last_name'].invalid && (angForm.controls['last_name'].dirty || angForm.controls['last_name'].touched)" class="alert alert-danger" >
<div *ngIf="angForm.controls['last_name'].errors.required">
Last Name is required.
</div>
</div>
</div>
<div class="form-group input-group">
<input type="email" placeholder="Email" formControlName="email" class="form-control" #email/>
</div>
<div *ngIf="angForm.controls['email'].invalid && (angForm.controls['email'].dirty || angForm.controls['email'].touched)" class="alert alert-danger" >
<div *ngIf="angForm.controls['email'].errors.required">
Email is required.
</div>
<div *ngIf="angForm.controls['email'].errors.email">
Enter valid email.
</div>
</div>
<div class="form-group input-group">
<input type="number" placeholder="Phone Number" formControlName="phone_number" class="form-control" #phoneNumber/>
</div>
<div *ngIf="angForm.controls['phone_number'].invalid && (angForm.controls['phone_number'].dirty || angForm.controls['phone_number'].touched)" class="alert alert-danger" >
<div *ngIf="angForm.controls['phone_number'].errors.required">
Phone Number is required.
</div>
<div *ngIf="angForm.controls['phone_number'].errors.maxLength">
Phone Number must be 10 digits
</div>
</div>
<div class="form-group input-group">
<input type="file" class="form-control file-data" formControlName="profile_pic" #profilePic />
</div>
<div class="input-group">
<!-- <input type="submit" class="btn btn-success btn-rectangle btn-demo ml-auto submit-btn" name="Submit" > -->
<button (click)="addUser(firstName.value, lastName.value,email.value,phoneNumber.value,profilePic.value);" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-success btn-rectangle btn-demo ml-auto submit-btn">Submit</button>
</div>
</form>
<!-- </div> -->
</nb-card-body>
</nb-card>
</div>
</div>
When using form-data to upload file with other form inputs
string and file upload to REST API by form-data. Can anyone please suggests for this? Thanks in advance.
try below code to post data with file upload.
ngOnInit() {
this.uploader.onBuildItemForm = (fileItem: any, form: any) => {
form.append('appNo', this.appNo); //note comma separating key and value
};
}