Cannot read property 'form' of undefined angular 5 - html

I have the following html form in angular
<form (ngSubmit)="signin()" #signinform="ngForm">
<div class="form-group row">
<label for="signinemail" class="col-sm-2 col-form-label">Email:</label>
<div class="col-sm-10">
<input type="email"
class="form-control"
id="signinemail"
name="signinemail"
ngModel
placeholder="Email">
</div>
</div>
<div class="form-group row">
<label for="signinpassword" class="col-sm-2 col-form-label">Password:</label>
<div class="col-sm-10">
<input type="password"
class="form-control"
id="signinpassword"
name="signinpassword"
ngModel
placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input ml-0"
type="checkbox"
id="gridCheck"
name="remembercheckbox"
ngModel>
<label class="form-check-label" for="gridCheck">
Remember Me
</label>
</div>
<small class="form-text text-muted">Forget Password?</small>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Sign In</button>
<button type="button" class="btn btn-outline-dark" (click)="c('Close click')">Close</button>
</div>
</form>
and the following typescript for the form:
import {NgForm} from "#angular/forms";
#ViewChild('signinform') signinform: NgForm;
signin() {
let payload = {
email: this.signinform.form.value.signinemail,
password: this.signinform.form.value.signinpassword,
localstorage: this.signinform.form.value.remembercheckbox
};
this.userservice.gettoken(payload);
this.signedin = true;
}
I have compared this to other forms I have built and yet there is no difference. What could be causing this?
the form element is on the dom when I call. The submit button is within the form. The #ViewChild element syntax is correct and properly imported. I truly don't understand and I am ready to punch a baby.

The code looks fine...You could just try not using view child, and instead do:
<form (ngSubmit)="signin(signinform)" #signinform="ngForm">
signin(form: NgForm) {
console.log(form);
}
I'd definitely try that console though, to make sure the form is being submitted properly.

Related

Angular Material 8 formControlName error - getting conflicting messages

I am attempting to work with Angular Material (8) Reactive Forms. I am working on a Registration Form. I am getting errors that seem to contradict each other.
**
When I do it this way (file: register.component.html):
**
<!-- Form -->
<form [formGroup]="registerForm" class="text-center" style="color: #757575;">
<div class="form-col">
<div class="col">
<!-- First name -->
<div class="md-form">
<input required type="text" id="materialRegisterFormFirstName" class="form-control"
mdbInput [(ngModel)]="user.firstname"/>
<label for="materialRegisterFormFirstName">First name</label>
</div>
</div>
[... snip ...]
**
I get this error:
**
ERROR Error:
ngModel cannot be used to register form controls with a parent formGroup directive. Try using
formGroup's partner directive "formControlName" instead.
So, I follow the instructions. When I use this approach (adding in formControlName="firstname"),
<div class="form-col">
<div class="col">
<!-- First name -->
<div class="md-form">
<input required type="text" id="materialRegisterFormFirstName" class="form-control"
mdbInput formControlName="firstname" [(ngModel)]="user.firstname"/>
<label for="materialRegisterFormFirstName">First name</label>
</div>
</div>
[... snip ...]
**
I get the following error:
**
forms.js:2312
It looks like you're using ngModel on the same form field as formControlName.
Support for using the ngModel input property and ngModelChange event with
reactive form directives has been deprecated in Angular v6 and will be removed
in Angular v7.
For more information on this, see our API docs here:
https://angular.io/api/forms/FormControlName#use-with-ngmodel
When looking up the problem, I come across this in an old thread:
REFERENCE: ngModel on the same form field as formControlName
From Angular 7 and onward you can't use both formControlName and ngModel together. If you want to use template-driven forms you can go with ngModel and if you want to use reactive forms you can't go with ngModel. (Simple)
**
It sounds like it is saying to remove the formControlName reference. How can this problem be resolved?
**
TIA
That is because you are using template-driven and reactive form at the same time. You need to use it one of them, you cant use both at same time.
Syntax of template driven form is as below.
.html file
<div class="row">
<div class="col-xs-12">
<form (ngSubmit)="onSubmit()">
<div class="row">
<div class="col-sm-5 form-group">
<label for="courseName">Course Name</label>
<input
type="text"
id="courseName"
class="form-control"
name="courseName"
ngModel>
</div>
<div class="col-sm-2 form-group">
<label for="courseDesc">Course Description</label>
<input
type="text"
id="courseDesc"
class="form-control"
name="courseDesc"
ngModel>
</div>
<div class="col-sm-2 form-group">
<label for="courseAmount">Course Amount</label>
<input
type="number"
id="courseAmount"
class="form-control"
name="courseAmount"
ngModel>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<button
class="btn btn-success"
type="submit">Add</button>
<button
class="btn btn-danger"
type="button">Delete</button>
<button class="btn btn-primary" type="button">Clear</button>
</div>
</div>
</form>
</div>
</div>
.ts file
onSubmit(form: NgForm) {
console.log("Course Name is : " + form.value.courseName);
console.log("Course Desc is : " + form.value.courseDesc);
console.log("Course Amount is : " + form.value.courseAmount);
}
Syntax for Reactive Form as below
.html file.
<div class="row">
<div class="col-xs-12">
<form [formGroup]="courseForm" (ngSubmit)="onSubmit()">
<div class="row">
<div class="col-sm-5 form-group">
<label for="courseName">Course Name</label>
<input
type="text"
id="courseName"
class="form-control"
formControlName="courseName">
</div>
<div class="col-sm-2 form-group">
<label for="courseDesc">Course Description</label>
<input
type="text"
id="courseDesc"
class="form-control"
formControlName="courseDesc">
</div>
<div class="col-sm-2 form-group">
<label for="courseAmount">Course Amount</label>
<input
type="number"
id="courseAmount"
class="form-control"
formControlName="courseAmount">
</div>
</div>
<div class="row">
<div class="col-xs-12">
<button
class="btn btn-success"
type="submit">Add</button>
<button
class="btn btn-danger"
type="button">Delete</button>
<button class="btn btn-primary" type="button">Clear</button>
</div>
</div>
</form>
</div>
</div>
.ts file
this.courseForm = new FormGroup({
'courseName': new FormControl(null, Validators.required),
'courseDesc': new FormControl([Validators.required, Validators.minLength(100)]),
'courseAmount': new FormControl(null)
});
for more reference visit
You Cannot use both ngModel and FormControlName or ngModel and formGroup together. Because ngModel is a template forms driven whereas FormControlName and FormGroup are reactive forms driven.
If you want to use both together you are increasing the complexity of the application. If you want to access the value through formControlName then use it like
<form [formGroup]="registerForm" class="text-center" style="color: #757575;">
<div class="form-col">
<div class="col">
<div class="md-form">
<input formControlName="firstName" type="text" id="materialRegisterFormFirstName" class="form-control" mdbInput/>
<label for="materialRegisterFormFirstName">First name</label>
</div>
</div>
</div>
</form>
In component.ts file write like
registerForm = new FormGroup({
firstName: new FormControl([Validator.required]),
});
or else you can build formgroup using formbuilder, fb is an instance of formBuilder
this.registerForm = fb.group({
'fullname': ['', Validators.required],
});
and you can read value like this
this.user.firstName = this.registerForm.get('firstName').value;
Use [ngModelOptions]="{ standalone: true }" on the input element
since you are using reactive forms , no need to use ngModelin your input fields use formControlName insted. ngModel is used in template driven froms
<div class="md-form">
<input required type="text" id="materialRegisterFormFirstName" class="form-control"
mdbInput formControlName="firstname"/>
<label for="materialRegisterFormFirstName">First name</label>
</div>
here you can find better examples https://v8.angular.io/guide/reactive-forms

Why the form disappear using ngFor directive

When I am using ngFor directive in the form tag, the entire form will disappear. Can anyone guide me on how I can fix this issue?
<form #myforms="ngForm" *ngFor="let i of editaddress">
<div class="p-3 p-lg-5 border">
<div class="form-group row">
<div class="col-md-12">
<label for="c_fname" class="text-black">Save this address as<span class="text-danger">*</span></label>
<input type="text" class="form-control c_fname" value="{{i.title}}" name="title" [(ngModel)]="location.title" #title=ngModel>
</div>
<div class="col-md-6">
<label for="c_fname" class="text-black">First Name<span class="text-danger">*</span></label>
<input type="text" class="form-control c_fname" value="{{i.first_name}}" name="fname" [(ngModel)]="location.first_name" #fname=ngModel>
</div>
<div class="col-md-6">
<label for="c_lname" class="text-black">Last Name<span class="text-danger">*</span></label>
<input type="text" class="form-control c_lname" value="{{i.last_name}}" name="lname" [(ngModel)]="location.last_name" #lname=ngModel>
</div>
</div>
</div>
<div class="col-lg-12">
<input type="submit" class="btn btn-primary btn-lg btn-block" value="Save" (click)="saveAddress(location)">
</div>
</div>
</div>
Since you did not show any part of the underlying controller, the only thing I can do is inform you that the property editaddress would be an empty array. Therefore it would not render anything.
If it flashes and disappears, it means that through your life cycle the array may have content, but at some point the array is set to [] which updates the the markup accordingly.

ngSubmit "myFunction is not a function" typescript, angular

I have an address management app, and I'm trying to save changes on ngSubmit. However, it says that my function is not a function.
my HTML:
<div class="form">
<h4>{{title}}</h4>
<div class="form-container">
<form (ngSubmit)="addFriend()">
<div class="form-group">
<label for="id">Id</label>
<input type="text" name="id" [(ngModel)]="friend.id"
[disabled]="friend.id" class="form-control" required />
</div>
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" [(ngModel)]="friend.name"
class="form-control" required />
</div>
<div class="form-group">
<label for="address">Address</label>
<input type="text" name="address" [(ngModel)]="friend.address"
class="form-control" required />
</div>
<div class="form-group">
<label for="phone">Phone</label>
<input type="text" name="phone" [(ngModel)]="friend.phone"
class="form-control" required />
</div>
<div class="form-group">
<a class="btn btn-default" routerLink="">Cancel</a>
<button class="btn btn-primary" >Save</button>
</div>
</form>
</div>
</div>
am I doing something wrong in the html, or would the problem be elsewhere?
The addFriend function is defined in my service.ts file.
You have to define addFriend in your component ts file like
addFriend(){
//some work here
}
Your component template does not have access to your service, but only to your component class methods.
So you need to
1/ inject your service into your component
2/ define in your component a method that calls the service methods
for example in your component :
constructor(private friendsService: FriendsService) {}
....
addFriend(){
return this.friendsService.addFriend();
}

HTML Form Post handling

I have a form as detailed below. It uses a post method to send data to getUsername.php. This file echoes some JSON results from mysql db.
Am wondering how do I grab this data? When I hit submit it navigates to the file and displays the JSON. I want to grab the JSON and stay on the same page or move to a different one!
I have kept the php file simple because the data is also used for returning data to my android app.
<div class="well bs-component">
<form id ='formLogin' action="http://localhost/getUsername.php" method="post" class="form-horizontal">
<fieldset>
<legend>Sign In</legend>
<div class="form-group">
<label for="inputEmail" class="col-lg-2 control-label">Email</label>
<div class="col-lg-10">
<input name='email' type="text" class="form-control" id="inputEmail" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Password</label>
<div class="col-lg-10">
<input name='password' type="password" class="form-control" id="inputPassword" placeholder="Password">
<div class="checkbox">
<label>
<input type="checkbox"> Checkbox
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button type="reset" class="btn btn-default">Cancel</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</fieldset>
</form>
I believe this cannot be done from a form. I instead used jquery post function to return data

HTML, making a button submit data to another url?

The following is my HTML:
<form class="form-horizontal" method="post">
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Email">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input type="password" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox"> Remember me
</label>
<button type="submit" class="btn btn-success">Sign in</button>
<button class="btn btn-primary"> Make a new account </button>
</div>
</div>
</form>
Note: Just in case someone is wondering, it is utilizing the bootstrap
library.
I have the form and it POSTs to login.php but I want the button Make a new account post the same data to register.php.
Is that possible? If so, how?
Set action attribute of your form tag to the URL of the page to send the data to.
Try the following:
In HTML add an onclick event handler for Make a new account button:
<form class="form-horizontal" method="post" id="myform">
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Email">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input type="password" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox"> Remember me
</label>
<button type="submit" class="btn btn-success">Sign in</button>
<button class="btn btn-primary" onclick="javascript:register()"> Make a new account </button>
</div>
</div>
</form>
In JavaScript:
function register() {
this.action = 'register.php';
return true;
}
If this does not work, you may try:
function register() {
var frm = document.getElementById("myform");
frm.action = 'register.php';
return true;
}
One or both of the above mentioned solution should work for you. Prefer the first approach as it is cleaner.
Please take this as a starting point not a copy-paste solution and follow the best practices for development.
I have the form and it POSTs to login.php but I want the button Make a new account post the same data to register.php.
Is that possible?
In HTML5 it is, using the formaction attribute on the submit button.
But browser support is probably not so good yet. Could be resolved using a Polyfil that attaches click handlers to such buttons automatically and changes the action attribute of the form dynamically, though.
<form class="form-horizontal" method="post" action="register.php">