Mat error is not working in the Angular following code? - html

I want to know why Mat error is not working in the Angular following code?
<div class="form-group">
<mat-form-field class="row-styling">
<mat-label for="aplctnName">
Application Name <span class="text-danger font-weight-bold">*</span>
</mat-label>
<input
matInput
type="text"
placeholder="Enter Application Name here"
alphabetOnly
maxlength="40"
formControlName="aplctnName"
[ngClass]="{ 'is-invalid': submitted && fields.aplctnName.errors }"
/>
<mat-error *ngIf="fields.aplctnName.errors.required"
>Application Name is required</mat-error
>
error>
</mat-form-field>
</div>
In the following code, mat-error is not working whenever I am pressing the next button.
can anyone please help in resolving this issue ?

You can check my solution.
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { MatFormFieldModule } from '#angular/material/form-field';
import { MatInputModule } from '#angular/material/input';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
#NgModule({
imports: [ BrowserModule, FormsModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, BrowserAnimationsModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
styles.scss
/* Add application styles & imports to this file! */
#import "#angular/material/prebuilt-themes/deeppurple-amber.css";
app.component.ts
import { Component, VERSION, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
form: FormGroup;
submitted: boolean = false;
ngOnInit() {
this.form = new FormGroup({
aplctnName: new FormControl('', Validators.required)
});
console.log(this.form)
}
onSubmit(event) {
}
}
app.component.html
<form [formGroup]="form" (ngSubmit)="onSubmit($event)">
<div class="form-group">
<mat-form-field class="row-styling">
<mat-label for="aplctnName">
Application Name <span class="text-danger font-weight-bold">*</span>
</mat-label>
<input
matInput
type="text"
placeholder="Enter Application Name here"
alphabetOnly
maxlength="40"
formControlName="aplctnName"
[ngClass]="{ 'is-invalid': submitted && form.get('aplctnName').errors }"
/>
<mat-error *ngIf="form.get('aplctnName').errors?.required"
>Application Name is required</mat-error
>
</mat-form-field>
<button type="submit">submit</button>
</div>
</form>
you can check working demo here
Let me know if you still face any issue.

Related

Argument of type '(fg: FormGroup) => { notmatched: boolean; }' is not assignable to parameter of type

I'm getting error like that (as u see in title). I have been working on this project for 2 days.
HTML Code:
<div class="container pt-5">
<h2 style="text-align: center;">Reactive Forms</h2>
<div class="row justify-content-sm-center pt-5">
<div class="col-sm-6 shadow round pb-3">
<h1 class="text-center pt-3 text-secondary">Example Form</h1>
<form [formGroup]='exform'>
<div class="form-group">
<label class="col-form-label">Email:</label>
<input formControlName="email" type="text" class="form-control" >
<small *ngIf="email.invalid && email.touched" class="text-danger">Email is Required</small>
</div>
<div class="form-group" >
<label class="col-form-label">Şifre:</label>
<input formControlName="password" type="password" class="form-control">
<small *ngIf="password.invalid && password.touched" class="text-danger">Parola Gerekli</small>
</div>
<div class="form-group">
<label class="col-form-label">Şifre Tekrarı:</label>
<input formControlName="password2" type="password" class="form-control" >
<small *ngIf="password2.invalid && password2.touched" class="text-danger">Parola Tekrarı Gerekli</small>
<small *ngIf="password2.invalid && password2.touched" class="text-danger">Parola Uyuşmuyor</small>
</div>
<button [disabled]="exform.invalid" type="button" class="btn btn-primary">Send message</button>
</form>
</div>
</div>
</div>
app.components.ts Code: (problem line: this.passwordMatchValidator);
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
import { AbstractControl } from '#angular/forms';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
exform!: FormGroup;
message!: string;
ngOnInit(){
this.exform= new FormGroup({
email: new FormControl(null, [Validators.required, Validators.minLength(4), Validators.email]),
password: new FormControl(null, [Validators.minLength(8), Validators.required]),
password2: new FormControl(null,[Validators.required, Validators.minLength(8)])
}, this.passwordMatchValidator);
console.log('Im here')
}
passwordMatchValidator(fg: FormGroup){
return fg.get('password')?.value===fg.get('password2')?.value ? null : {notmatched: true}
}
clickSub()
{
console.log("clicked");
this.exform.reset();
}
get email(){
return this.exform.get('email');
}
get password(){
return this.exform.get('password');
}
get password2(){
return this.exform.get('password2');
}
}
app.modelu.ts Code:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing-module';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing-module.ts Code:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Error: src/app/app.component.ts:27:11 - error TS2345: Argument of type '(fg: FormGroup) => { notmatched: boolean; }' is not assignable to parameter of type 'ValidatorFn | ValidatorFn[] | AbstractControlOptions'.
Type '(fg: FormGroup) => { notmatched: boolean; }' is not assignable to type 'ValidatorFn'.
Types of parameters 'fg' and 'control' are incompatible.
Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.
27 }, this.passwordMatchValidator);
Where is the problem?
Just change the type of the input.
passwordMatchValidator(fg: AbstractControl){
return fg.get('password')?.value === fg.get('password2')?.value ? null : {notmatched: true}
}
Please read the error correctly, it is written very clearly.
Try disabling strictFunctionTypes in the "tsconfig" file:
"compilerOptions": {
"baseUrl": "src",
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"strictFunctionTypes": false,
"strictNullChecks": false,
Check if the requested field is a required field
Validators.required

Angular materials working in one component but not another

I've been working in Angular for the first time for a school-related project. I'm trying to make my pages look a bit better by using materials for form inputs instead of the stock HTML forms, and to great success in most of my components. However, one component in particular isn't recognizing the material tags as valid even though they work fine in the others with no discernible (to me) differences in either the .HTML file implementation or the .ts file declarations and imports.
They work in my sign in component, as shown below.
sign-in.component.html
<form [formGroup]="signInForm" (ngSubmit)="onSubmit(signInForm.value)">
<mat-form-field>
<mat-label>Employee ID:</mat-label>
<input matInput type="number" formControlName="employeeId">
</mat-form-field>
<br>
<mat-form-field>
<mat-label>Password:</mat-label>
<input matInput type="password" formControlName="password">
</mat-form-field>
<br>
<button mat-raised-button type="submit">Sign In</button>
<br>
</form>
The relevant .ts file is here. This isn't all of it, just the imports and declarations.
sign-in.component.ts
import { Component, OnInit} from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { FormGroup, FormControl } from '#angular/forms';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { environment } from '../../../environments/environment';
import { EmployeeService } from 'src/app/employee/employee.service';
import { Employee } from 'src/app/employee/employee';
#Component({
selector: 'sign-in',
templateUrl: './signin.component.html',
styleUrls: ['./signin.component.css']
})
export class SigninComponent implements OnInit{
private apiUrl = environment.baseUrl + "/api/auth";
signInForm = new FormGroup({
employeeId: new FormControl(''),
password: new FormControl(''),
});
errorMsg = null
constructor(
private employeeService: EmployeeService,
private activatedRoute: ActivatedRoute,
private router: Router,
private http: HttpClient
){}
}
When I try to implement almost the exact same code in my other component, it isn't recognizing the labels.
product-detail.component.html
<h1><b>PRODUCT DETAILS</b></h1>
<form [formGroup]="productDetailsForm" (ngSubmit)="onSubmit(productDetailsForm.value)">
<div>
<mat-form-field>
<mat-label for="name">Name</mat-label>
<input matInput id="name" type="text" formControlName="name">
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-label for="price">Price</mat-label>
<input matInput id="price" type="number" formControlName="price">
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-label for="lookupCode">Name</mat-label>
<input matInput id="lookupCode" type="text" formControlName="lookupCode">
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-label for="count">Price</mat-label>
<input matInput id="count" type="number" formControlName="count">
</mat-form-field>
</div>
<button *ngIf="isManager" class="button" type="submit">Save</button>
</form>
<button mat-raised-button *ngIf="isManager" class="button" (click)="deleteClicked()">Delete</button>
The relevant .ts file is below.
product-detail.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '#angular/forms';
import { Product } from '../product';
import { ProductService } from '../product.service';
import { ActivatedRoute, Router } from '#angular/router';
import { UserService } from '../../services/user.service';
import { MatFormFieldModule } from '#angular/material/form-field';
#Component({
selector: 'product-detail-t',
templateUrl: './product-detail.component.html',
styleUrls: ['./product-detail.component.css'],
providers: [ProductService, UserService]
})
export class ProductDetailComponent implements OnInit {
#Input() id: string;
productDetailsForm: FormGroup;
isManager: boolean;
constructor(
private productService: ProductService,
private userService: UserService,
private formBuilder: FormBuilder,
private activatedRoute: ActivatedRoute,
private router: Router
) {
this.id = this.activatedRoute.snapshot.paramMap.get("id");
this.productDetailsForm = this.formBuilder.group({
lookupCode: new FormControl({value: '', disabled: true}),
price: new FormControl({value: '', disabled: true}),
name: new FormControl({value: '', disabled: true}),
count: new FormControl({value: '', disabled: true})
});
this.userService.isManager()
.then((isManager: boolean) => {
this.isManager = isManager;
if(isManager) {
this.productDetailsForm.controls["name"].enable();
this.productDetailsForm.controls["lookupCode"].enable();
this.productDetailsForm.controls["count"].enable();
this.productDetailsForm.controls["price"].enable();
}
});
}
}
Below is my app.module.ts file, if that helps.
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NgModule } from '#angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { ReactiveFormsModule } from '#angular/forms';
import { MatButtonModule } from '#angular/material/button';
import { MatCardModule } from '#angular/material/card';
import { MatInputModule } from '#angular/material/input';
import { MatFormFieldModule } from '#angular/material/form-field';
import { MatToolbarModule } from '#angular/material/toolbar';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { EmployeeModule } from './employee/employee.module';
import { ProductModule } from './product/product.module';
import { TransactionModule } from './transaction/transaction.module';
import { SigninComponent } from './components/signin/signin.component';
import { MainMenuComponent } from './components/main-menu/main-menu.component';
import { PageHeaderComponent } from './components/page-header/page-header.component';
import { HttpRequestInterceptor } from './HttpInterceptor';
import { TransactionPageComponent } from './transaction/transaction-page/transaction-page.component';
#NgModule({
declarations: [
AppComponent,
SigninComponent,
MainMenuComponent,
SigninComponent,
PageHeaderComponent,
TransactionPageComponent
],
imports: [
BrowserModule,
ReactiveFormsModule,
HttpClientModule,
EmployeeModule,
AppRoutingModule,
BrowserModule,
BrowserAnimationsModule,
ProductModule,
MatButtonModule,
MatCardModule,
MatInputModule,
MatFormFieldModule
],
exports: [
MatButtonModule,
MatCardModule,
MatInputModule,
MatFormFieldModule
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: HttpRequestInterceptor, multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
I should mention that the form in the sign-in component was created by one of my group members, but he can't seem to find the problem with my code either.
Any help at all would be greatly appreciated!
You're getting that error probably because you have not imported the MatInputModule or any other Angular Material modules in the ProductModule where I believe your ProductDetailComponent is declared.

Why is my code for 'mat-form-field' not working?

I'm totaly new to angular, and i was practicing using material and adding form fields. I followed all the guides, downloaded all the packages and my code is just copy-pased from a guide but it's still not displaying on my browser.
My console initialy showed
"Unexpected directive 'MatFormField' imported by the module 'AppModule'. Please add a #NgModule annotation."
and after googling it I was told to replace it with "MatFormFieldModule" but after i did i got this error
"NullInjectorError: StaticInjectorError(AppModule)[CdkObserveContent -> ElementRef]:
StaticInjectorError(Platform: core)[CdkObserveContent -> ElementRef]:
NullInjectorError: No provider for ElementRef!"
My code:
app.component.html
<p>works</p>
<form class = "tp-form">
<mat-form-field class = "tp-full-width">
<input matInput placeholder = "Favorite Food" value = "Pasta">
</mat-form-field>
<mat-form-field class = "tp-full-width">
<textarea matInput placeholder = "Enter your comment"></textarea>
</mat-form-field>
<mat-form-field class = "tp-full-width">
<input matInput placeholder = "Email" [formControl] =
"emailFormControl">
<mat-error *ngIf = "emailFormControl.hasError('email')
&& !emailFormControl.hasError('required')">
Please enter a valid email address
</mat-error>
<mat-error *ngIf = "emailFormControl.hasError('required')">
Email is <strong>required</strong>
</mat-error>
</mat-form-field>
</form>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CourseComponent } from './course/course.component';
import {BrowserAnimationsModule} from '#angular/platform-
browser/animations';
import {MatInputModule, MatFormField, MatFormFieldModule} from
'#angular/material'
import {FormsModule, ReactiveFormsModule} from '#angular/forms';
import { CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
const modules = [
BrowserAnimationsModule,
MatInputModule,
FormsModule,
ReactiveFormsModule,
MatFormFieldModule
]
#NgModule({
declarations: [
AppComponent,
CourseComponent
],
imports: [
BrowserModule,
AppRoutingModule,
...modules
],
exports:[
...modules
],
providers: [],
bootstrap: [AppComponent]
,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }
app.component.ts
import { Component } from '#angular/core';
import { FormControl } from "#angular/forms";
import { Validators } from '#angular/forms';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'materialApp';
emailFormControl = new FormControl('', [
Validators.required,
Validators.email,
]);
}
Currently my browser is only showing "works".
emailFormControl should be define with ViewChild annotation, like this:
import { Component, ElementRef, ViewChild } from '#angular/core'
...
#ViewChild('emailFormControl') emailFormControl: ElementRef
In short, ViewChild allows us to query elements (from the docs: https://angular.io/api/core/ViewChild)
In this example we used the query target our emailFormControl an get a valid reference

FormControl is not provided by any applicable directives

FormControl is having difficulties with directives...
I am trying to implement an autocomplete into my input field. I am using the following angular-material guide to the point that I have verbatim copy and pasted their typescript and html to test it out: https://material.angular.io/components/autocomplete/overview.
I keep receiving an error on FormControl in the HTML that reads: "Property FormControl is not provided by any applicable directives nor by input element. Inspection info: Reports undefined property, event or structural directive bindings on elements."
HTML CODE:
<form class="example-form">
<mat-form-field class="example-full-width">
<input type="text" placeholder="Pick one" aria-label="Number" matInput [FormControl]="myControl" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{option}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
TS CODE:
import {Component, OnInit} from '#angular/core';
import {FormControl} from '#angular/forms';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';
#Component({
selector: 'mySelector',
templateUrl: 'myTemplate.html',
styleUrls: ['myCSS.css'],
})
export class myExportClass implements OnInit {
myControl = new FormControl();
options: string[] = ['One', 'Two', 'Three'];
filteredOptions: Observable<string[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith(''),
map(value => this._filter(value))
);
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.options.filter(option =>
option.toLowerCase().includes(filterValue));
}
}
As stated in the docs: "For this example, be sure to import ReactiveFormsModule from #angular/forms into your NgModule"
So ensure that your app.module contains the module e.g.:
import {FormsModule, ReactiveFormsModule} from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent,
],
imports: [
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

How to send FormData with another FormControl using Reactive form in angular 6?

I make a form with some fields like email user name and avatar using reactive form of angular 6. I know i need form data to upload image, but i dont know how to using it with reactive form in angular 6. Anyone can help ?
Try this:
<form [formGroup]="yourForm" (ngSubmit)="onSubmit()">
<input type="text" formControlName="email"> <br>
<input (change)="uploadDocument($event)" type="file" accept=".png, .pdf, .jpg, .jpeg"> <br>
<input (change)="onSubmit()" type="submit" value="Send file">
</form>
in your app.component.html, then:
import { Component } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
yourForm: FormGroup;
constructor(private fb: FormBuilder, private http: HttpClient) {
this.yourForm = this.fb.group({
email: [''],
file: ['']
});
}
uploadDocument(event: any) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.onload = () => {
this.yourForm.get('file').setValue(event.target.files[0]);
};
reader.readAsDataURL(event.target.files[0]);
}
}
onSubmit(): void {
const uploadData = new FormData();
uploadData.append('email', this.yourForm.get('email').value);
uploadData.append('file', this.yourForm.get('file').value);
this.http.post('your-route', uploadData);
}
}
in your app.component.ts, and:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { HttpClientModule } from '#angular/common/http';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule
],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
in your app.module.ts file.
Also, don't forget to configure the route in line this.http.post('your-route', uploadData);.