How to make a html form to angular form - html

I have created an component called login. I have created a html form login.component.html then I wanted to make this form as Angular form. So I added <form #loginform="ngForm"> in login.component.html and import import {NgForm} from '#angular/forms' in login.component.ts. Can you help me where is the issue?
So when I run the server I get an error said:
ERROR in src/app/login/login.component.html:2:23 - error NG8003: No directive found with exportAs 'ngForm'.
2 <form #loginform="ngForm">
~~~~~~
src/app/login/login.component.ts:6:16
6 templateUrl: './login.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component LoginComponent.
login.component.ts:
import { Component, OnInit } from '#angular/core';
import {NgForm} from '#angular/forms';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
login.component.html:
<div class="container">
<form #loginform="ngForm">
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" name="email">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd" placeholder="Enter password" name="pwd">
</div>
<div class="checkbox">
<label><input type="checkbox" name="remember"> Remember me</label>
</div>
<button type="submit" class="btn btn-default">Login</button>
</form>
</div>

Maybe if you add the FormsModule to the your Module, your problem will be solved or you can create login component by Command ng g c login

Do not use ngForm. Use angular reactive forms it is better and easier to create and manage.
https://angular.io/guide/reactive-forms
but if you want to continue with the current setup please check this answer
TypeScript-'s Angular Framework Error - "There is no directive with exportAs set to ngForm"

Related

Object is possibly 'null' in Reactive Forms Angular

I need your help!I am newbie in Angular Reactive Forms and I am trying to make simple form with validation using Angular's Reactive Forms. But I get an error in this part of my code (ngIf directive, property 'invalid'):
<div class="container">
<form class="card" [formGroup]="form" (ngSubmit)="submit()">
<h1>Angular Forms</h1>
<div class="form-control">
<label>Email</label>
<input type="text" placeholder="Email" formControlName="email">
<div
*ngIf="form.get('email').invalid"
class="validation">
</div>
</div>
<div class="form-control">
<label>Пароль</label>
<input type="password" placeholder="Пароль" formControlName="password">
<div class="validation"></div>
</div>
<div class="card">
<h2>Адрес</h2>
<div class="form-control">
<label>Страна</label>
<select>
<option value="ru">Россия</option>
<option value="ua">Украина</option>
<option value="by">Беларусь</option>
</select>
</div>
<div class="form-control">
<input type="text">
</div>
<button class="btn" type="button">Выбрать столицу</button>
</div>
<div class="card">
<h2>Ваши навыки</h2>
<button class="btn" type="button">Добавить умение</button>
<div class="form-control">
<label></label>
<input type="text">
</div>
</div>
<button class="btn" type="submit" [disabled]="form.invalid">Отправить</button>
</form>
</div>
TypeScript code:
import { Component, OnInit } from '#angular/core';
import { FormControl, FormGroup, Validators } from '#angular/forms';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less']
})
export class AppComponent implements OnInit {
title = 'forms';
form!: FormGroup;
ngOnInit() {
this.form = new FormGroup({
email: new FormControl('',
[Validators.email,
Validators.required]),
password: new FormControl(null,
[Validators.required,
Validators.minLength(8)])
})
}
submit() {
console.log('Form submitted', this.form);
const formData = { ...this.form.value };
console.log('Form Data:', formData);
}
}
I use Angular 12 and I followed guide on Udemy, so this is very strange, because my mentor's code works correct. I created FromGroup and FormControls, gave them names, so I am really confused about this error. Do you have any ideas how can I fix it?
The Object is possibly 'null' error can happen due to strict type checking and can be solved in 2 ways:
Either assert that you are absolutely sure that can never be null, by using the ! (not null assertion operator)
Use the ? (optional chaining operator) to stop an eventual error from happening in case the object is indeed null
So you can replace the if statement with form.get('email')?.invalid and it should work. A similar question has been asked here.

Pass value from Typescript to HTML. Error; [object HTMLInputElement]

I try to pass array values from a .ts file to a html file in a Angular Project.
The HTML file is:
<body>
<section id="login" class="d-flex justify-content-center flex-column align-items-center">
<form>
<div class="form-group">
<label>Firmware</label>
<input #firmware class="form-control" type="text" value= {{firmware}} readonly>
</div>
<div class="form-group">
<label>Bootloader</label>
<input #bootloader class="form-control" type="text" value= {{bootloader}} readonly>
</div>
</form>
</section>
</body>
and the .ts file is:
import { Component, OnInit } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Router, ActivatedRoute, ParamMap } from '#angular/router';
#Component({
selector: 'app-dual',
templateUrl: './dual.component.html',
styleUrls: ['./dual.component.scss']
})
export class DualComponent implements OnInit {
title = "";
constructor(private router: Router, private httpClient : HttpClient) { }
ngOnInit(): void {
var resultArray:number[] = [235,23]
var firmware = resultArray[0];
var bootloader = resultArray[1];
console.log("firmware",firmware);
console.log("bootloader",bootloader);
}
}
If i show the values via console.log they are shown right but if i try to show them in the HTML file the value in the textbox is "[object HTMLInputElement]"
Note: Im new in Angular and try to learn :)
Any tips?
Thank you!
Solution:
HTML:
<div class="form-group">
<label>Firmware</label>
<input class="form-control" type="text" value= {{firmware}} readonly>
</div>
<div class="form-group">
<label>Bootloader</label>
<input class="form-control" type="text" value= {{bootloader}} readonly>
</div>
TypeScript:
var resultArray:number[] = [235,23]
this.firmware = resultArray[0].toString();
this.bootloader = resultArray[1].toString();
console.log("firmware",this.firmware);
console.log("bootloader",this.bootloader);
I deleted my old answer, because I totally missed what was wrong. When you do this:
<input #firmware class="form-control" type="text" value= {{firmware}} readonly>
The #firmware creates a new local variable named firmware, which is equal to the HTML element it's contained in. It's that new local variable that is being displayed inside the curly braces, not the variable firmware which is defined in your DualComponent class.
Make sure you don't duplicate variable names like this, and the problem will go away.

What is the problem in my ngModel when I want to define a variable?

I want to use ngModel, but I have a problem.
This code is not running and it gives me an error.
This is my code:
contact-form.component.html:
<div class="container">
<form>
<div class="form-group">
<label for="firstName">First name</label>
<input ngModel #firstName="firstName" (change)="log(firstName)" id="firstName" type="text" class="form-control"/>
</div>
<div class="form-group">
<label for="comment">comment</label>
<textarea id="comment" rows="3" class="form-control"></textarea>
</div>
<button class="btn btn-primary">Enter</button>
</form>
</div>
contact-form.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-contact-form',
templateUrl: './contact-form.component.html',
styleUrls: ['./contact-form.component.css']
})
export class ContactFormComponent implements OnInit {
constructor() { }
ngOnInit() {
}
log(f) {
console.log(f);
}
}
and this error display in console:
Error: Template parse errors:
There is no directive with "exportAs" set to "firstName" (" <div class="form-group">
<label for="firstName">First name</label>
<input ngModel [ERROR ->]#firstName="firstName" (change)="log(firstName)" id="firstName" type="text" class="form-control"/>
"): ng:///AppModule/ContactFormComponent.html#4:23
What can I do?
modify your input tag in the form like the following :
<input #firstName="ngModel" (change)="log(firstName)"
type="text" class="form-control"/>
Note: if you you want to have Two-way data binding ( [(ngModel)]="propName" ):
<input #firstName="ngModel" (change)="log(firstName)" [(ngModel)]="firstName"
type="text" class="form-control"/>
You can try this:
<div class="form-group">
<label for="firstName">First name</label>
<input [(ngModel)]="firstName" #firstName (change)="log(firstName)" id="firstName" type="text" class="form-control"/>
</div>
for your input tag use this. this will breaking down Two-Way data binding.
<input #firstName (change)="log(firstName)" type="text">
- and to display its content use it as interpolation syntax in your template.
{{firstName.value}}
- after you done text input press enter and results will be in interpolation.
Second way of doing this is like..
in this case you need to define your property name in your component class too.
private firstName;
and in your template file
<input [ngModel]="firstName" (ngModelChange)="firstName = $event" >
{{ firstName }}
make sure you import FormsModule in main app module of your project.
import { FormsModule } from '#angular/forms';
If you want to access template reference variable in your component.ts file then your have to use #ViewChild () directives. and result of this available only in ngAfterViewInit() life cycle method.
#ViewChild ('firstName', { static: false} ) inputRefElm : ElementRef;
ngAfterViewInit(){
console.log(this.inputRefElm.nativeElement.value);
}

Getting the same values 2 times in console,angular2

When i am seeing the data that comes from form in console it get two times
My template
<div class="login jumbotron center-block">
<h1>Login</h1>
<form #form ="ngForm" (ngSubmit)="onSubmit(form.value)">
<div class="form-group">
<label for="username">Username</label>
<input type="text" ngControl ="email" class="form-control" id="emailh" placeholder="Username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" ngControl ="phone" class="form-control" id="phoneh" placeholder="Password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
<a [routerLink]="['/signup']">Click here to Signup</a>
</form>
</div>
My component,
import { Component } from '#angular/core';
import { Router, ROUTER_DIRECTIVES } from '#angular/router';
import { CORE_DIRECTIVES, FORM_DIRECTIVES } from '#angular/common';
import { Http, Headers } from '#angular/http';
import { contentHeaders } from '../headers/headers';
import {Control,FormBuilder,ControlGroup,Validators} from '#angular/common';
#Component({
directives: [ ROUTER_DIRECTIVES, CORE_DIRECTIVES, FORM_DIRECTIVES ],
templateUrl : "./components/login/login.html",
})
export class Login {
constructor(public router: Router, public http: Http) {
}
onSubmit(form:any) {
console.log(form);
}
}
my console,
Object {email: "andrew#gmail.com", phone: "getiyt"}
Object {email: "andrew#gmail.com", phone: "getiyt"}
When i am seeing the data that comes from form in console it get two times,therefor i am not sure that why it comes like that as a result my db also get filled with single record 2 times.Can someone find where i am wrong.
In your main.ts you have to set:
import {disableDeprecatedForms, provideForms} from '#angular/forms';
bootstrap(AppComponent, [disableDeprecatedForms(), provideForms()]);
This solve the problem. See this plunker: http://plnkr.co/edit/uiYZkEWMyXWOkglHZu6N
See also the official documentation: https://angular.io/docs/ts/latest/guide/forms.html
Credit: Roberto Simonetti's answer here.

Can't wrap my head around capturing form data (Angular)

I am simply trying to create a mockup of a login page, and need to get the username and password values entered into the form, and use those values to validate whether the user should be authenticated. I've looked at a dozen tutorials and can't seem to understand it fully. Here is what I have:
login.component.html
<form #f="ngForm" (ngSubmit)="loginUser()">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username"
[(ngModel)]="model.username" #username="ngModel"
class="form-control" required>
<label for="password">Password</label>
<input type="password" id="password" name="password"
[(ngModel)]="model.password" #password="ngModel"
class="form-control" required>
<div style="padding-top:20px">
<button type=submit class="button">Login</button>
</div>
</div>
</form>
login.component.ts (I'm going wrong here somewhere, but I tried. The "if" statement is definitely wrong)
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { NgForm, FormControl, FormGroup, ReactiveFormsModule } from '#angular/forms'
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
myForm: FormGroup
constructor(private router: Router) {
}
ngOnInit() {
}
loginUser(f: NgForm) {
if (f.value == "admin" && f.value == "admin"){
this.router.navigate(['mockup']);
}
}
}
There are a few issues:
1- Model is not defined anywhere. Therefore, model.username is not valid. Just make it username or define model somewhere in your calss.
2-You don't need the variables (#username="ngModel") if you are not going to use them in the template. For example, you could do:
<input #myUsernameInput="ngModel">
{{ myUsernameInput.valid }} // true/false
{{ myUsernameInput.value }} the value
and various other checks. But you aren't performing these checks anywhere, so there's no need to have the variables defined.
3- myForm should not be defined in your class, as formGroups are used for reactive forms, not template driven forms. If you want to pass the values to the method, an easy way is like this:
<form (submit)="loginUser(username, password)">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username"
[(ngModel)]="username" class="form-control" required>
<label for="password">Password</label>
<input type="password" id="password" name="password"
[(ngModel)]="password" class="form-control" required>
<div style="padding-top:20px">
<button type=submit class="button">Login</button>
</div>
</div>
</form>
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { NgForm, FormControl, FormGroup, ReactiveFormsModule } from '#angular/forms'
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(private router: Router) {
}
ngOnInit() {
}
loginUser(username: string, password: string) {
if (username === "admin" && password === "admin"){
this.router.navigate(['mockup']);
}
}
}
The easiest way to to explain template driven forms means that all the work (meaning the building of the form, the validation, etc.) takes place in the template (the html). This is limited because you can't do everything that you could with reactive driven forms. However, reactive driven forms are a bit more complex. Which to choose depends on the situation and the preference, but in this scenario, template driven forms are perfectly valid to use. I'd recommend reading this guide, it's super helpful. https://angular.io/guide/forms