I want to insert the value inserted into an input in the database using Angular as the frontend and php as the backend but I'm not able to insert the input value into the method along with the user.id.
The input is for the reason of moderation when clicking on disapprove it is necessary to pass the reason but it is not entering.
import { Component, OnInit, TemplateRef } from '#angular/core';
import { FormGroup } from '#angular/forms';
import { observerMixin } from '#rodrigowba/observer-component';
import { ResponseData, DefaultResponse } from '#rodrigowba/http-common';
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
import { ToastrService } from 'ngx-toastr';
import { Observable } from 'rxjs';
import { ActionPayload } from '~/ngrx';
import {
HotsiteUser,
HotsiteUsersFacade,
HotsiteUsersFormService,
RegistrationStatusTypes,
UpdateHotsiteUserRequest,
HotsitePointsPrebase,
} from '~/admin/users';
import {
updateHotsiteUser,
hotsiteUserUpdated,
hotsiteUserUpdateFailed,
hotsiteUserRegistrationModerated,
hotsiteUserModerateRegistrationFailed
} from '~/admin/users/state';
import { distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
#Component({
templateUrl: './view.component.html',
})
export class ViewComponent extends observerMixin() implements OnInit {
user$: Observable<HotsiteUser>;
pointsPrebase$: Observable<HotsitePointsPrebase[]>;
customFields$: Observable<{
field: string,
value: string
}[]>;
registrationStatusTypes = RegistrationStatusTypes;
form: FormGroup;
modalRef: BsModalRef;
submiting = false;
constructor(
private hotsiteUsersFacade: HotsiteUsersFacade,
private hotsiteUsersFormService: HotsiteUsersFormService,
private modalService: BsModalService,
private toastr: ToastrService
) {
super();
this.form = this.hotsiteUsersFormService.updateForm();
}
ngOnInit() {
this.user$ = this.hotsiteUsersFacade.selectCurrentHotsiteUser();
this.customFields$ = this.user$.pipe(
map(user => Object.values(user.custom_fields)),
map(customFields => customFields.map(customField => {
let value = customField.value;
if (Array.isArray(value)) {
value = value.join(', ');
}
return {
field: customField.field,
value
};
}))
);
this.pointsPrebase$ = this.user$.pipe(
map(user => user.id),
distinctUntilChanged(),
tap(id => {
this.hotsiteUsersFacade.fetchHotsitePointsPrebase(id);
}),
switchMap(id => this.hotsiteUsersFacade.selectHotsitePointsPrebaseByHotsiteUser(id))
);
this.observe(this.user$).subscribe(user => {
this.form.patchValue(user);
});
this.observe(
this.hotsiteUsersFacade.ofType(updateHotsiteUser)
).subscribe(() => {
this.submiting = true;
});
this.observe(
this.hotsiteUsersFacade.ofType<ActionPayload<ResponseData<HotsiteUser>>>(
hotsiteUserUpdated,
hotsiteUserRegistrationModerated
)
).subscribe(action => {
const { message, data } = action.payload;
this.submiting = false;
this.toastr.success(message);
});
this.observe(
this.hotsiteUsersFacade.ofType<ActionPayload<DefaultResponse>>(
hotsiteUserUpdateFailed,
hotsiteUserModerateRegistrationFailed
)
).subscribe(action => {
const { message } = action.payload;
this.submiting = false;
this.toastr.error(message);
});
}
onSubmit(id: string, data: UpdateHotsiteUserRequest) {
this.hotsiteUsersFacade.updateHotsiteUser(id, data);
}
openModal(template: TemplateRef<any>, size = 'modal-md') {
this.modalRef = this.modalService.show(template, { class: size });
}
approveRegistration(id: string,reason: string) {
this.hotsiteUsersFacade.moderateRegistrationHotsiteUser(id, { approved: true,reason });
}
rejectRegistration(id: string,reason: string) {
this.hotsiteUsersFacade.moderateRegistrationHotsiteUser(id, { approved: false,reason });
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<form [formGroup]="form" (ngSubmit)="onSubmit(user.id, form.value)" >
<form [formGroup]="form" (ngSubmit)="onSubmit(user.id, form.value)" >
<div class="row mb-3">
<div class="col-12">
<div class="form-group">
<label>Name</label>
<input type="text" [value]="user.name" class="form-control" readonly />
</div>
</div>
<div class="col-12 col-lg-6">
<div class="form-group">
<label>E-mail</label>
<input type="text" [value]="user.email" class="form-control" readonly />
</div>
</div>
<div class="col-12 col-lg-6">
<div class="form-group">
<label>Document</label>
<input type="text" [value]="user.document" class="form-control" readonly />
</div>
</div>
<div class="col-12" *ngFor="let customField of customFields$ | async">
<div class="form-group">
<label>{{ customField.field }}</label>
<input type="text" [value]="customField.value" class="form-control" readonly />
</div>
</div>
<div class="col-auto">
<div class="form-group">
<mat-slide-toggle formControlName="admin" color="primary" ></mat-slide-toggle>
<label class="ml-2">Admin</label>
</div>
</div>
<div class="col-auto">
<div class="form-group">
<mat-slide-toggle formControlName="active" color="primary" ></mat-slide-toggle>
<label class="ml-2">Active</label>
</div>
</div>
</div>
<ng-container *ngIf="pointsPrebase$ | async as pointsPrebase">
<div class="row mb-3" *ngIf="pointsPrebase.length > 0">
<div class="col-12">
<h4 class="font-16 font-weight-bold">Points</h4>
</div>
<div class="col-12 col-lg-6">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>Chave</th>
<th class="text-center">Points</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let points of pointsPrebase">
<td>{{ points.value }}</td>
<td class="text-center">{{ points.points }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</ng-container>
<div class="form-row">
<ng-container *ngIf="user.registration_status === registrationStatusTypes.AwaitingModeration">
<div class="col-auto">
<label>Reason</label>
<input type="text" name="reason" placeholder="Reason of moderation..." class="form-control"/>
</div>
<div class="col-auto">
<button
type="button"
class="btn btn-success"
(click)="approveRegistration(user.id,form.reason)"
>
<app-loading-label [loading]="submiting">Approved </app-loading-label>
</button>
</div>
<div class="col-auto">
<button
type="button"
class="btn btn-danger"
(click)="rejectRegistration(user.id,form.reason)"
>
<app-loading-label [loading]="submiting">Repproved </app-loading-label>
</button>
</div>
</ng-container>
<div class="col text-right">
<button
type="submit"
class="btn btn-orange"
[disabled]="form.invalid || submiting"
>
<app-loading-label [loading]="submiting">Salvar</app-loading-label>
</button>
</div>
</div>
</form>
Error:
Property 'reason' does not exist on type 'formGroup'
As user776686 suggested, there is a formControlName missing linked to "reason" field.
To get the field value in HTML you should access to the FormGroup controls:
(click)="approveRegistration(user.id, form.controls.reason.value)"
Also you can create a "get" property in TS code and then access to it in HTML:
get reason() {
return this.form.controls.reason.value;
}
(click)="approveRegistration(user.id, reason)"
BTW, a field can be accessed too through the "get" method of a FormGroup:
get reason() {
return this.form.get('reason').value;
}
It expects a control with the attribute formControlName="reason" which is not present here:
<input type="text" name="reason" placeholder="Reason of moderation..." class="form-control"/>
This might be a reason.
If that doesn't help, you my also want to look into the *ngIf condition here:
<ng-container *ngIf="user.registration_status === registrationStatusTypes.AwaitingModeration">
Related
I'm working on an angular project and I want to develop a form, validate it, and save data in my database with php and mysql. I tried to do this but it doesn't work. I got these errors.
Property 'dataService' does not exist on type 'AppComponent'.
'data' is declared but its value is never read.
Parameter 'data' implicitly has an 'any' type.
Property 'router' does not exist on type 'AppComponent'.
'error' is declared but its value is never read.
Parameter 'error' implicitly has an 'any' type.
register.component.html
<h2 class="text-center">Registration</h2>
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6 col-md-offset-3">
<div class="jumbotron">
<form [formGroup]="angForm" autocomplete="off" >
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" formControlName="name" autocomplete="off" class="form-control input-sm" required minlength="1" maxlength="250" placeholder="Name"
[class.is-invalid]="name.invalid && (name.dirty || name.touched)">
<div *ngIf="name.invalid && (name.dirty || name.touched)" class="invalid-feedback">
<div *ngIf="name.errors?.['required']">
This field is required.
</div>
</div></div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" formControlName="email" autocomplete="off" required minlength="1" maxlength="250" class="form-control input-sm" placeholder="Email"
[class.is-invalid]="email.invalid && (email.dirty || email.touched)">
<div *ngIf="email.invalid && (email.dirty || email.touched)" class="invalid-feedback">
<div *ngIf="email.errors?.['required']">
This field is required.
</div>
<div *ngIf="!email.errors?.['required'] && email.errors?.['emailValidator']">
Invalid email format.
</div>
</div></div>
<div class="form-group">
<label for="Password">Password</label>
<input type="password" name="Password" formControlName="password" required minlength="15" autocomplete="off" class="form-control input-sm" placeholder="Password"
[class.is-invalid]="password.invalid && (password.dirty || password.touched)">
<button type="button" class="btn btn-outline-secondary" (click)="user.showPassword = !user.showPassword">
<i class="bi" [ngClass]="{'bi-eye-fill': !user.showPassword, 'bi-eye-slash-fill': user.showPassword}"></i>
</button>
<div *ngIf="password.invalid && (password.dirty || password.touched)" class="invalid-feedback">
<div *ngIf="password.errors?.['required']">
This field is required.
</div>
<div *ngIf="password.errors?.['minlength']">
This field must have at least 8 characters.
</div>
</div></div>
<button type="submit" class="btn btn-success" (click)="validate(angForm1)">Register</button>
</form>
</div>
</div>
<div class="col-md-3">
</div>
</div>
register.component.ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, FormBuilder, Validators, NgForm, AbstractControl} from
'#angular/forms';
import { first } from 'rxjs/operators';
import { Router } from '#angular/router';
import { ApiService } from '../api.service';
import { emailValidator } from './email-validator.directive';
interface IUser {
name: string;
email: string;
password: string;
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
angForm!: FormGroup;
user: IUser;
constructor() {
this.user = {} as IUser;
}
ngOnInit(): void {
this.angForm = new FormGroup({
name: new FormControl(this.user.name, [
Validators.required
]),
email: new FormControl(this.user.email, [
Validators.required,
EmailValidator,
]),
password: new FormControl(this.user.password, [
Validators.required,
Validators.minLength(8),
]),
});
}
get name() {
return this.angForm.get('name')!;
}
get email() {
return this.angForm.get('email')!;
}
get password() {
return this.angForm.get('password')!;
}
public validate(angForm1:any): void {
if (this.angForm.invalid) {
for (const control of Object.keys(this.angForm.controls)) {
this.angForm.controls[control].markAsTouched();
}
return;
}
else{ this.dataService. userregistration(angForm1.value.name,angForm1.value.email,
angForm1.value.password).pipe(first()).subscribe(
data => {
this.router.navigate(['login']);
},
error => {
});
}
this.user = this.angForm.value;
console.info('Name:', this.user.name);
console.info('Email:', this.user.email);
console.info('Password:', this.user.password);
}
}
register.php
<?php
include_once "database.php";
$postdata = file_get_contents("php://input");
if (isset($postdata) && !empty($postdata)) {
$request = json_decode($postdata);
$name = trim($request->name);
$pwd = mysqli_real_escape_string($mysqli, trim($request->pwd));
$email = mysqli_real_escape_string($mysqli, trim($request->email));
$sql = "INSERT INTO users(name,password,email) VALUES ('$name','$pwd','$email')";
if ($mysqli->query($sql) === true) {
$authdata = [
"name" => $name,
"pwd" => "",
"email" => $email,
"Id" => mysqli_insert_id($mysqli),
];
echo json_encode($authdata);
}
}
?>
api.service.ts
import {
Injectable,
Output,
EventEmitter
}
from '#angular/core';
import {
map
}
from 'rxjs/operators';
import {
HttpClient
}
from '#angular/common/http';
import {
Users
}
from './users';
#Injectable({
providedIn: 'root'
})
export class ApiService {
redirectUrl: string;
baseUrl: string = "http://localhost/angular_admin/php";
#Output() getLoggedInName: EventEmitter < any > = new EventEmitter();
constructor(private httpClient: HttpClient) {}
public userlogin(username: any, password: any) {
alert(username)
return this.httpClient.post < any > (this.baseUrl + '/login.php', {
username,
password
})
.pipe(map(Users => {
this.setToken(Users[0].name);
this.getLoggedInName.emit(true);
return Users;
}));
}
public userregistration(name: any, email: any, pwd: any) {
return this.httpClient.post < any > (this.baseUrl + '/register.php', {
name,
email,
pwd
})
.pipe(map(Users => {
return Users;
}));
}
//token
setToken(token: string) {
localStorage.setItem('token', token);
}
getToken() {
return localStorage.getItem('token');
}
deleteToken() {
localStorage.removeItem('token');
}
isLoggedIn() {
const usertoken = this.getToken();
if (usertoken != null) {
return true
}
return false;
}
}
In your constructor in your ts:
constructor(private router: Router,private apiservice: ApiService) {
this.user = {} as IUser;
}
public validate(angForm1:any): void {
if (this.angForm.invalid) {
for (const control of Object.keys(this.angForm.controls)) {
this.angForm.controls[control].markAsTouched();
}
return;
}
else{ this.apiservice. userregistration(angForm1.value.name,angForm1.value.email,
angForm1.value.password).pipe(first()).subscribe(
(data: any) => {
this.router.navigate(['login']);
},
error => {
});
}
this.user = this.angForm.value;
console.info('Name:', this.user.name);
console.info('Email:', this.user.email);
console.info('Password:', this.user.password);
}
In your html:
<h2 class="text-center">Registration</h2>
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6 col-md-offset-3">
<div class="jumbotron">
<form [formGroup]="angForm" autocomplete="off" >
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" formControlName="name" autocomplete="off" class="form-control input-sm" required minlength="1" maxlength="250" placeholder="Name"
[class.is-invalid]="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)">
<div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)" class="invalid-feedback">
<div *ngIf="angForm.controls['name'].errors?.required">
This field is required.
</div>
</div></div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" formControlName="email" autocomplete="off" required minlength="1" maxlength="250" class="form-control input-sm" placeholder="Email"
[class.is-invalid]="angForm.controls['email'].invalid && (angForm.controls['email'].dirty || angForm.controls['email'].touched)">
<div *ngIf="angForm.controls['email'].invalid && (angForm.controls['email'].dirty || angForm.controls['email'].touched)" class="invalid-feedback">
<div *ngIf="angForm.controls['email'].errors.required">
This field is required.
</div>
<div *ngIf="!email.errors?.['required'] && email.errors?.['emailValidator']">
Invalid email format.
</div>
</div></div>
<div class="form-group">
<label for="Password">Password</label>
<input type="password" name="Password" formControlName="password" required minlength="15" autocomplete="off" class="form-control input-sm" placeholder="Password"
[class.is-invalid]="angForm.controls['password'].invalid && (angForm.controls['password'].dirty || angForm.controls['password'].touched)">
<button type="button" class="btn btn-outline-secondary" (click)="user.showPassword = !user.showPassword">
<i class="bi" [ngClass]="{'bi-eye-fill': !user.showPassword, 'bi-eye-slash-fill': user.showPassword}"></i>
</button>
<div *ngIf="angForm.controls['password'].invalid && (angForm.controls['password'].dirty || angForm.controls['password'].touched)" class="invalid-feedback">
<div *ngIf="angForm.controls['password'].errors.required">
This field is required.
</div>
<div *ngIf="angForm.controls['password'].errors.minlength">
This field must have at least 8 characters.
</div>
</div></div>
<button type="submit" class="btn btn-success" (click)="validate(angForm1)">Register</button>
</form>
</div>
</div>
<div class="col-md-3">
</div>
</div>
I have a product form with different fields like product name, description etc.. also array of images.
Product Form
product name product description
product purity product commodity
Images (Add)
checkbox 1 Image 1
checkbox 2 Image 2
checkbox 3 Image 3.
....
I can able to save in my database product name and product description and other fields but don't how to upload those images. Because images are created on clicking the add button and it may have one or as many images based on requirement.I have created the form using Form builder. Given my code below.
Template :
<form class="kt-form kt-form--group-seperator-dashed" [formGroup]="mmgForm">
<div class="kt-form__section kt-form__section--first">
<div class="kt-form__group">
<div class="row">
<label class="col-lg-2 col-form-label">Product Name:</label>
<div class="col-lg-4">
<mat-form-field class="example-full-width">
<input formControlName="prod_name" matInput placeholder="Enter product name" [ngClass]="{ 'is-invalid': submitted && mmgForm.controls['prod_name'].errors }">
<div *ngIf="submitted && mmgForm.controls['prod_name'].errors" class="invalid-feedback cls-formErr">
<div *ngIf="mmgForm.controls['prod_name'].errors.required">Product name is required</div>
</div>
</mat-form-field>
</div>
<label class="col-lg-2 col-form-label">Product description:</label>
<div class="col-lg-4">
<mat-form-field class="example-full-width">
<textarea formControlName="prod_description" matInput placeholder="Enter product description" rows="5" [ngClass]="{ 'is-invalid': submitted && mmgForm.controls['prod_description'].errors }"></textarea>
<div *ngIf="submitted && mmgForm.controls['prod_description'].errors" class="invalid-feedback cls-formErr">
<div *ngIf="mmgForm.controls['prod_description'].errors.required">Product description is required</div>
</div>
</mat-form-field>
</div>
</div>
</div>
<div class="product_images">
<div class="imageHeading">
<p>
Images (<button mat-icon-button color="primary" matTooltip="Add product" (click) = addImage()><mat-icon>add_circle</mat-icon></button>)
</p>
</div>
<div class="kt-form__group">
<div class="row">
<div class="col-lg-1 imageLabel">#</div>
<div class="col-lg-2 imageLabel">Main Image</div>
<div class="col-lg-3 imageLabel">Choose Image</div>
<div class="col-lg-2 imageLabel">Image</div>
<div class="col-lg-2 imageLabel">Actions</div>
</div>
</div>
<div class="imagesContainer">
<div class="kt-form__group image-container container-1" *ngFor="let image of images; index as i">
<div class="row">
<div class="col-lg-1">{{ i+1 }}</div>
<div class="col-lg-2"><input type="checkbox" /></div>
<div class="col-lg-3"><input type="file" accept="image/*" (change)="imagePreview($event, image)" /></div>
<div class="col-lg-2"><img [src]="image.url.imgUrl" class="prod_image" /></div>
<div class="col-lg-2">
<button mat-icon-button color="warn" matTooltip="Delete Product" type="button" (click)="deleteImage(i)">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
Ts File :
// Angular
import { Component, OnInit, ElementRef, ViewChild, ChangeDetectionStrategy, OnDestroy, ChangeDetectorRef } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
// Material
import { SelectionModel } from '#angular/cdk/collections';
import { MatPaginator, MatSort, MatSnackBar, MatDialog, MatRadioButton } from '#angular/material';
import { ProductManagementService } from '../../../../../core/e-commerce/_services/product-management.service';
import { ToastrService } from 'ngx-toastr';
#Component({
selector: 'kt-product-edit',
templateUrl: './product-edit.component.html',
styleUrls: ['./product-edit.component.scss'],
})
export class ProductEditComponent implements OnInit {
mmgForm : any;
fileData: File = null;
previewUrl : any = "/assets/media/images/noimage.jpg";
images : any = [];
constructor(
private products: ProductManagementService,
private router: Router,
private route: ActivatedRoute,
private toastr: ToastrService,
private cdr: ChangeDetectorRef,
private FB: FormBuilder,
) {
}
ngOnInit() {
this.createForm();
this.addImage();
}
createForm() {
this.mmgForm = this.FB.group({
prod_name: ['', Validators.required],
prod_description: ['', Validators.required]
});
}
/**
* Form Submit
*/
submit() {
if (this.mmgForm.invalid) {
console.log(this.mmgForm);
return;
}
const controls = this.mmgForm.controls;
var form_values = {
prod_name: controls.prod_name.value,
prod_description: controls.prod_description.value,
}
this.products
.createProduct(JSON.stringify(form_values)).subscribe( //Calling Service
(data) => {
console.log(data);
},
error => {
}
);
}
imagePreview(fileInput: any, image) {
this.fileData = <File>fileInput.target.files[0];
// Show preview
var mimeType = this.fileData.type;
if (mimeType.match(/image\/*/) == null) {
return;
}
var reader = new FileReader();
reader.readAsDataURL(this.fileData);
reader.onload = (_event) => {
image.url.imgUrl = reader.result;
this.cdr.markForCheck();
}
}
addImage(){
let url = {imgUrl : this.previewUrl}
this.images.push({url});
}
deleteImage(index: number) {
this.images.splice(index, 1)
}
}
I would suggest to create a FileUploadService for that.
The Service method:
uploadFiles(Array<File> files): Observable<FileUploadResponse> {
const url = `your-upload-url`;
const formData: FormData = new FormData();
for(File file in files) {
formData.append('file', file, file.name);
}
return this.http.post<FileUploadResponse>(url, formData /*{headers if necessary}*/);
}
Your component.ts:
//[..]
Array<File> files = [];
onFileInputEvent(event: any) {
for(let i = 0; i < event.srcElement.files.length; i++) {
this.fileName = event.srcElement.files[0].name;
this.files.push(event.srcElement.files[0]);
}
}
uploadFiles(){
this.fileUploadService.uploadFile(this.file).subscribe(res => { // do something}, err =>{});
}
Your component.html:
<!-- [..] -->
<input id="fileInput" placeholder="Images" type="file" (change)="onFileInputEvent($event)" accept=".jpg">
Edit with a more beautiful input
<div class="file-input">
<input id="fileInput" placeholder="CSV-Datei" type="file" class="hidden" (change)="onFileInputEvent($event)" accept=".csv">
<label for="fileInput" class="mat-raised-button">Add images</label>
<mat-chip-list *ngIf="fileName">
<mat-chip [removable]="true" (removed)="remove()">
{{fileName}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
register.component.html (the form input component)
<div class="card-content">
<form #registerForm="ngForm" (ngSubmit)="onSubmit(Name.value, Email.value)">
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">account_circle</i>
<input type="text" name="Name"
#Name
ngModel required>
<label for="Name">Name</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">mail_outline</i>
<input type="text" name="Email"
#Email
ngModel
required
[pattern]="emailPattern">
<label for="Email">Email</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<button class="btn-large btn-submit"
type="submit"
[disabled]='!registerForm.valid'>Start</button>
</div>
</div>
</form>
</div>
register.component.ts
........................................................................................
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { QuizService } from '../shared/quiz.service';
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
emailPattern = '^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$';
constructor(private route: Router, private quiz: QuizService) { }
user = {
username: '',
email: ''
};
ngOnInit() {
}
onSubmit(name, email) {
this.user.username = name;
this.user.email = email;
this.route.navigate(['quiz']);
console.log(this.user.username, this.user.email); // log works!!
}
}
quiz.component.html (here i want to display the data which user entered in register component)
.........................................................
<div class="row">
<div class="col s6 offset-s3">
<h3>Welcome to quiz</h3>
<b>Your Name is: </b>
<br>
<b>Your Email is: </b>
</div>
</div>
this.route.navigate(['quiz',{username:username,...}])
and in your quiz component receive data
this.route.params.subscribe(params=>{ console.log(params.username)})
don't forget inject the ActivatedRoute in your quiz
constructor(private route:ActivatedRoute)
There are many way to accomplish this but I would suggest looking at NgRX Store, if you want a simpler solution then you can use a service:
#Injectable({
provideIn: ‘root’
})
export class SomeService {
userSubject = new BehaviorSubject<User>({});
user$: Observable<User> = this.userSubject;
}
In your RegisterComponent submit event you will call someService.userSubject.next(this.user); and in your QuizComponent subscribe to someService.user$ to pick up the data
I'm try to make custom Validators that give user message when he/she leave a space on text but i received this error.
1-Cannot read property 'removeSpaceFromUserName' of undefined
2-Cannot read property 'required' of null
at Object.eval [as updateDirectives]
Here's the html of the component
<form [formGroup]='form'>
<div class="form-group">
<label for="username">Username</label>
<input
formControlName='username'
id="username"
type="text"
class="form-control">
<div *ngIf="username.touched && username.touched" class="alert alert-danger">
<div *ngIf="username.errors.required"> You need to enter user name</div>
<div *ngIf="username.errors.minlength"> Min Length is
{{ username.errors.minLength.requiredLength}}
</div>
<div *ngIf="UserNameValiditors.removeSpaceFromUserName">
removeSpaceFromUserName </div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
formControlName='password'
id="password"
type="text"
class="form-control">
</div>
<button class="btn btn-primary" type="submit">Sign Up</button>
</form>
Here's the custom validator class
import { AbstractControl, ValidationErrors } from "#angular/forms";
export class UserNameValiditors {
static removeSpaceFromUserName(control: AbstractControl): ValidationErrors | null {
if ((control.value as string).indexOf(' ') >= 0) {
return {
removeSpaceFromUserName: true
};
}
else {
return null;
}
}
}
import { Component } from '#angular/core';
import { FormControl , FormGroup , Validators } from "#angular/forms";
import { UserNameValiditors } from './UserNameValditors';
#Component({
selector: 'signup-form',
templateUrl: './signup-form.component.html',
styleUrls: ['./signup-form.component.css']
})
export class SignupFormComponent {
form= new FormGroup(
{
username : new FormControl('',
[
Validators.required,
Validators.minLength(3) ,
UserNameValiditors.removeSpaceFromUserName
]) ,
password : new FormControl('',Validators.required)
});
get username()
{
return this.form.get('username');
}
}
You can try with this solution.
I have create a demo on Stackblitz
app.component.ts
myForms: FormGroup;
constructor(fb: FormBuilder) {
this.myForms = fb.group({
username: [null, Validators.compose([
Validators.required, Validators.minLength(3), usernameValidator])],
password: [null, [
Validators.required]]
});
}
app.component.html
<form [formGroup]="myForms">
<label>User Name :
<input type="text" formControlName="username">
</label><br>
<div class="errors" *ngIf="myForms.get('username').invalid && (myForms.get('username').touched || myForms.get('username').dirty)">
<div *ngIf="myForms.get('username').hasError('required')">
username is required
</div>
<div *ngIf="myForms.get('username').errors.minlength">
username must be at least 3 characters
</div>
<div class="error-text" *ngIf="myForms.get('username').hasError('removeSpaceFromUserName')">
removeSpaceFromUserName
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
formControlName='password'
id="password"
type="text"
class="form-control">
</div>
<button class="btn btn-primary" type="submit">Sign Up</button>
</form>
Use hasError() to check if certain error is present on the form.
html code
<div *ngIf="username.hasError('required')"> You need to enter user name</div>
<div *ngIf="username.hasError('minlength')"> Min Length is {{ username.hasError('minLength')}}
</div>f
<div *ngIf="username.hasError('removeSpaceFromUserName')">
removeSpaceFromUserName </div>
</div>
Your working code is here
I've been battling with these block of codes for some days, and even when i try initializing it as an object i get errors.
this is my restaurantForm.ts file
import { Component, OnInit } from '#angular/core';
import {RestaurantService} from '../../restaurant.service';
import {ProductService} from '../../product.service';
import {ActivatedRoute, Router} from '#angular/router';
import 'rxjs/add/operator/take';
import {Product} from '../../model/product';
#Component({
selector: 'app-product-form',
templateUrl: './restaurant-form.component.html',
styleUrls: ['./restaurant-form.component.css']
})
export class RestaurantFormComponent implements OnInit {
restaurants$;
id;
product: Product;
constructor(private restaurantService: RestaurantService,
private productService: ProductService,
private route: ActivatedRoute,
private router: Router) {
this.restaurants$ = this.restaurantService.getAll();
this.id = this.route.snapshot.paramMap.get('id');
if (this.id) {
this.productService.get(this.id).take(1).subscribe(p => this.product = p);
}
this.product = new Product();
}
save(product) {
if (this.id) {
this.productService.update(this.id, product);
} else {
this.productService.create(product);
}
this.router.navigate(['/admin/restaurants']);
}
delete() {
if (!confirm('Are you sure you want to delete this product?')) { return ; }
this.productService.delete(this.id);
this.router.navigate(['/admin/restaurants']);
}
ngOnInit() {
}
}
this is my product model
export interface Product {
$key: string;
title: string;
price: number;
restaurant: string;
imageUrl: string;
}
My restaurantForm.html
<div class="container">
<div class="row">
<div class="col-md-6">
<form #f="ngForm" (ngSubmit)="save(f)">
<div class="form-group">
<label for="title">Title</label>
<input #title="ngModel" [(ngModel)]="product.title" name="title" id="title" type="text" class="form-control" required>
<div class="alert-danger alert" *ngIf="title.touched && title.invalid">
Title is required.
</div>
</div>
<div class="form-group">
<label for="price">Delivery Price</label>
<div class="input-group">
<span class="input-group-addon">₦</span>
<input #price="ngModel" [(ngModel)]="product.price" name="price" id="price"
type="number" class="form-control" required [min]="0">
</div>
<div class="alert alert-danger" *ngIf="price.touched && price.invalid">
<div *ngIf="price.errors.required">
Delivery Price is required
</div>
<div *ngIf="price.errors.min">
Delivery Price should be 0 or higher.
</div>
</div>
</div>
<div class="form-group">
<label for="restaurant">Restaurant</label>
<select #restaurant="ngModel" [(ngModel)]="product.restaurant" name="restaurant" id="restaurant" class="form-control" required>
<option value=""></option>
<option *ngFor="let r of restaurants$ | async" [value]="r.$key">
{{ r.name }}
</option>
</select>
<div class="alert alert-danger" *ngIf="restaurant.touched && restaurant.invalid">
Please select a restaurant.
</div>
</div>
<div class="form-group">
<label for="imageUrl">Image Url</label>
<input #imageUrl="ngModel" [(ngModel)]="product.imageUrl" name="imageUrl"
id="imageUrl" type="text" class="form-control" required url>
<div class="alert alert-danger" *ngIf="imageUrl.touched && imageUrl.invalid">
<div *ngIf="imageUrl.errors.required">Image Url is required.</div>
<div *ngIf="imageUrl.errors.url">Please enter a valid Url.</div>
</div>
</div>
<button class="btn btn-primary">Save</button>
<button type="button" (click)="delete()" class="btn btn-danger">Delete</button>
</form>
</div>
<div class="col-md-6">
<app-product-card [product]="product" [showActions]="false"></app-product-card>
</div>
</div>
</div>
I get the same errors with price, $key, restaurant and imageUrl.
thanks in advance. Although Ive looked up some solutions saying i should use elvis Operator e.g 'product?.title' this method isnt still working.
Because product is undefined, you need to declare and initialize it with empty object inside the constructor or ngOninit.
EDIT:
You need to have the Product declared in the component as,
const product : Produce = { $key: "", title: "",price:0,restuarant :"" ,imageurl:"" };
When the template get initialized, the product is undefined and it continues until the response return from API. Add a check for the template where you bind the object properties.Do the same for price etc.
<input *ngIf="product.title" #title="ngModel" [(ngModel)]="product.title" name="title" id="title" type="text" class="form-control" required>