I am using Angular 8 to get the data out of a radio input. When I send that data to Node then to Mongodb database, it is not register, and it appear like this in the db collection:
"__v" : 0
The output of the data that is being sent from Angular is: { type: administrator }, what I want to register in the db is only the word adminstrator. The Node console shows an error because of the object that is passed to the db when it expects a string value.
The Angular template is this:
<br>
<div class="w3-panel w3-border w3-margin" style="width: 500px; height: 550px">
<label class="w3-text-blue"><h2>New User</h2></label>
<label class="w3-text-blue"><b>Name and Last Name</b></label><br>
<input type="text" class="w3-input w3-border" [(ngModel)]="name" ><br>
<label class="w3-text-blue"><b>User</b></label><br>
<input type="text" class="w3-input w3-border" [(ngModel)]="user"><br>
<label class="w3-text-blue"><b>Password</b></label><br>
<input type="password" class="w3-input w3-border" [(ngModel)]="password"><br>
<label class="w3-text-blue"><b>Confirm Password</b></label><br>
<input type="password" class="w3-input w3-border" [(ngModel)]="confirm"><br>
<label class="w3-text-blue"><b>Type of User</b></label><br>
<form #myForm="ngForm" (submit)="sendRadio(myForm.value)" >
<input id="administrator" type="radio" name="type" class="w3-radio" value="administrator" ngModel>
<label for="administrador">Administrador</label> <br>
<input id="normal" type="radio" name="type" class="w3-radio" value="normal" ngModel>
<label for="normal">Moderador</label>
<br><br>
<button type="submit" (click)="createUser(user, password, name)" class="w3-button w3-round-xxlarge w3-green">Create</button>
<button class="w3-button w3-round-xxlarge w3-red">Clean Fields</button>
</form>
</div>
The component's typescript file:
import { Component, OnInit } from '#angular/core';
import { PersonService } from '../_services/person.service';
#Component({
selector: 'app-create-user',
templateUrl: './create-user.component.html',
styleUrls: ['./create-user.component.css']
})
export class CreateUserComponent implements OnInit {
user: any;
password: any;
confirm: any;
name: any;
type: string;
constructor(private ps: PersonService) { }
ngOnInit() {
}
sendRadio(value: any) {
this.type = value;
console.log(this.type); // <--- this outputs { type: administrator }
}
createUser(userU, userPassword, userName) {
if (this.password === this.confirm) {
if (this.password.length > 0 && this.confirm.length > 0) {
this.ps.createUser(userU, userPassword, userName, this.type);
} else {
console.log('Password has to match and be completed');
}
}else {
console.log('Password does not match');
}
}
}
The service to send the data (PersonService):
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class PersonService {
uri = 'http://localhost:3000';
constructor(private http: HttpClient) { }
createUser(userU, userPassword, userName, userType: string) {
const obj = {
user: userU,
password: userPassword,
name: userName,
type: userType
};
this.http.post(`${this.uri}/createUser`, obj)
.subscribe(res => console.log('User has been created'));
}
Just pass in
console.log(this.type.type);
because you need the value of the key for type. This prints out 'administrator' and you can pass that to your backend node.
Related
Been trying to access form instance values bt they are all null..It worked fine in tempalate driven forms. I have imported ReactiveFormsModule. I have played around with the attr but I cant find what am missing??
The form is invalid the moment I use Validators.required meaning its empty
.component.html
<form [formGroup] ="tryForm" (ngSubmit)="onSubmit()" >
<div class="form-group">
<label>Name</label><br>
<input type="text" FormControlName ="name">
<span *ngIf="tryForm.invalid">Name required</span>
</div>
<!-- <div *ngIf="name.invalid" class="alert alert-danger"></div> -->
<div class="form-group">
<label>Email</label><br>
<input type="text" FormControlName ="email">
</div>
<div class="form-group">
<label>Message</label><br>
<input type="text" FormControlName ="message">
</div>
<button type = "submit" >Submit</button>
</form>
.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormControl,FormGroup,Validators} from '#angular/forms';
import { Router} from '#angular/router'
#Component({
selector: 'app-log-in',
templateUrl: './log-in.component.html',
styleUrls: ['./log-in.component.css']
})
export class LogInComponent implements OnInit {
tryForm = this.fb.group({
name : [''],
email: [''],
message: [''],
});
constructor(private fb:FormBuilder,
private router: Router) { }
onSubmit(){
if (this.tryForm.status == "VALID"){
alert("Form Submitted Successfully.")
alert(this.tryForm.get("name")?.value);
this.tryForm.reset();
first you need to change the html FormControlName to formControlName. you can read the full explanation here.
HTML
<form [formGroup]="tryForm" (ngSubmit)="onSubmit(tryForm.value)">
<div class="form-group">
<label>Name</label><br />
<input type="text" formControlName="name" />
<span *ngIf="tryForm.invalid">Name required</span>
</div>
<div class="form-group">
<label>Email</label><br />
<input type="text" formControlName="email" />
</div>
<div class="form-group">
<label>Message</label><br />
<input type="text" formControlName="message" />
</div>
<button type="submit">Submit</button>
</form>
after that change your ts like bellow, make sure you initialize the form on ngOnInit.
TS
export class LogInComponent implements OnInit {
tryForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.createForm();
}
createForm() {
this.tryForm = this.fb.group({
name : [''],
email : [''],
message: [''],
});
}
onSubmit(data) {
console.log(data);
}
}
I replicate your code here
change this <input type="text" FormControlName ="email"> to this;
<input type="text" formControlName="email">
and build your form on ngOnInit,
ngOnInit(){
this.tryForm = this.fb.group({
name : [''],
email: [''],
message: [''],
});
}
I made an input box for an IP Address with Port. This input box is made of 5 inputs box within a div. This is a basic example.
<div class="form-inline" style="display: inline-block">
<input required name="block1" class="form-control" #block1="ngModel" type="text" [(ngModel)]="ipBlock1">.
<input required name="block2" class="form-control" #block2="ngModel" type="text" [(ngModel)]="ipBlock2">.
<input required name="block3" class="form-control" #block3="ngModel" type="text" [(ngModel)]="ipBlock3">.
<input required name="block4" class="form-control" #block4="ngModel" type="text" [(ngModel)]="ipBlock4">:
<input required name="block5" class="form-control" #block5="ngModel" type="text" [(ngModel)]="ipBlock5">
</div>
In ip-address-input.component.ts file I have:
#Input() ipProtocol
#Output() ipAddressCreated: EventEmitter<any> = new EventEmitter<{ipAddress: string}>();
ipBlock1: string;
ipBlock2: string;
//some logic like string concatenation (ipBlock1 + '.' + ipBlock2 + '.' + ...)
In app.component.html:
<ip-address-input [ipProtocol]="dhcpRangeStart"></ip-address-input>
<ip-address-input [ipProtocol]="dhcpRangeStop"></ip-address-input>
But when I check for example for the first IP it returns the last entered IP. How I can make this component reusable (make multiple instances of it)
Image with the actual IP Input box:
I've built a few controls similar to yours by leveraging ControlValueAccessor and NG_VALUE_ACCESSOR from angular forms. Basically, these provide you with a pattern to build your own custom and reusable form controls.
Below is an example code but you can also follow this tutorial to get your component built.
Component:
import { Component, OnInit, forwardRef } from '#angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl } from '#angular/forms';
const IP_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => IpInputComponent),
multi: true
};
#Component({
selector: 'ip-address-input',
providers: [IP_VALUE_ACCESSOR],
templateUrl: './ip-input.component.html',
styleUrls: ['./ip-input.component.css']
})
export class IpInputComponent implements OnInit, ControlValueAccessor {
ipBlock1: string;
ipBlock2: string;
ipBlock3: string;
ipBlock4: string;
ipBlock5: string;
disabled: boolean;
onChange: Function;
onTouched: Function;
get value(): string {
return ipBlock1 + '.' + ipBlock2 + '.' + ipBlock3 + '.' + ipBlock4 + ':' + ipBlock5;
}
constructor() {
this.onChange = (_: any) => {};
this.onTouched = () => {};
this.disabled = false;
}
ngOnInit() {
}
writeValue(obj: any): void {
if(obj) {
let arr = obj.split('.');
this.ipBlock1 = arr[0];
this.ipBlock2 = arr[1];
this.ipBlock3 = arr[2];
this.ipBlock4 = arr[3].split(':')[0];
this.ipBlock5 = arr[3].split(':')[1];
}
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
Template:
<div class="form-inline" style="display: inline-block">
<input required class="form-control" type="number" [ngModel]="ipBlock1" />.
<input required class="form-control" type="number" [ngModel]="ipBlock2" />.
<input required class="form-control" type="number" [ngModel]="ipBlock3" />.
<input required class="form-control" type="number" [ngModel]="ipBlock4" />:
<input required class="form-control" type="number" [ngModel]="ipBlock5" />
</div>
Usage:
<ip-address-input formControlName="ipAddress" (value)="ipAddress.value"></ip-address-input>
HTH
Im start my first time with firebase and angular.
I following step to step from Angular 6 CRUD Operations With Firebase in YouTube, when I press submit then error popup in Google chrome console and cant set value into firebase realtime database.
YouTube link: https://www.youtube.com/watch?v=9wxEwE8UFr0
OrganizationComponent.html
<div class="row">
<div class="col-md-5">
<form [formGroup]="this.organizationService.form" (ngSubmit)="onSubmit()">
<input type="hidden" formControlName="$key">
<div class="form-group">
<label>Full Name</label>
<input formControlName="fullname" class="form-control" [ngClass]="{'is-invalid':submitted && formControls.fullname.errors}">
<div class="invalid-feedback" *ngIf="submitted && formControls.fullname.errors">
This field is required.</div>
</div>
<div class="form-group">
<label>Email</label>
<input formControlName="email" class="form-control" [ngClass]="{'is-invalid':submitted && formControls.email.errors}">
<div class="invalid-feedback" *ngIf="submitted && formControls.email.errors">
Invalid email address.</div>
</div>
<div class="form-group">
<label>Mobile</label>
<input formControlName="mobile" class="form-control" [ngClass]="{'is-invalid':submitted && formControls.mobile.errors}">
<div class="invalid-feedback" *ngIf="submitted && formControls.mobile.errors">
<label *ngIf="formControls.mobile.errors.required">This field is required.</label>
<label *ngIf="formControls.mobile.errors.minlength">Atleast 8 numbers.</label>
</div>
</div>
<div class="form-group">
<label>Location</label>
<input formControlName="location" class="form-control">
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Submit">
</div>
</form>
<div class="alert alert-info" *ngIf="showSuccessMessage">
Submitted successfully.
</div>
</div>
<div class="col-md-7">
<app-organization-list></app-organization-list>
</div>
</div>
Organization.component.ts
import { Component, OnInit } from '#angular/core';
import { OrganzationService } from '../shared/organization.service';
#Component({
selector: 'app-organization',
templateUrl: './organization.component.html',
styleUrls: ['./organization.component.css']
})
export class OrganizationComponent implements OnInit {
constructor(private organizationService: OrganzationService) { }
submitted: boolean;
showSuccessMessage: boolean;
formControls = this.organizationService.form.controls;
ngOnInit() {
}
onSubmit(){
this.submitted = true;
if(this.organizationService.form.valid){
if(this.organizationService.form.get('$key').valid == null)
this.organizationService.insertOrganization(this.organizationService.form.value);
else
this.organizationService.updateOrganization(this.organizationService.form.value);
this.showSuccessMessage = true;
setTimeout(() => this.showSuccessMessage = false,3000);
this.submitted = false;
this.organizationService.form.reset();
this.organizationService.form.setValue({
$key: null,
fullname: '',
email: '',
mobile: '',
location: ''
})
}
}
}
OrganizationService.ts
import { Injectable } from '#angular/core';
import {FormControl,FormGroup,Validators} from "#angular/forms";
import {AngularFireDatabase,AngularFireList} from 'angularfire2/database';
#Injectable({
providedIn: 'root'
})
export class OrganzationService {
constructor(private firebase: AngularFireDatabase) { }
organizationList: AngularFireList<any>;
form = new FormGroup({
$key: new FormControl(null),
fullname: new FormControl('',Validators.required),
email: new FormControl('',Validators.email),
mobile: new FormControl('',[Validators.required,Validators.minLength(8)]),
location: new FormControl('')
});
getOrganizations() {
this.organizationList = this.firebase.list('organizations');
return this.organizationList.snapshotChanges();
}
insertOrganization(organization) {
this.organizationList.push({
fullname: organization.fullname,
email: organization.email,
mobile: organization.mobile,
location: organization.location
});
}
populateForm(organization) {
this.form.setValue(organization);
}
updateOrganization(organization) {
this.organizationList.update(organization.$key,
{
fullname: organization.fullname,
email: organization.email,
mobile: organization.mobile,
location: organization.location
});
deleteOrganization($key: string) {
this.organizationList.remove($key);
}
}
I have this template-driven form:
<form #form="ngForm" (submit)="submitForm()" novalidate>
<div class="form-group" [class.has-error]="linkName.invalid">
<label class="control-label" for="name">Name</label>
<input #linkName="ngModel" type="text" class="form-control" name="name" id="name" [(ngModel)]="finalData.name" required />
<div *ngIf="linkName.invalid" class="alert alert-danger">Name is required</div>
</div>
<div class="form-group">
<label for="url">Url</label>
<input type="text" class="form-control" id="url" name="url" [(ngModel)]="finalData.url" readonly/>
</div>
<div class="checkbox" *ngFor="let tag of finalData.tags; index as i" [attr.data-index]="i">
<label><input type="checkbox" name="{{ 'checkbox' + tag }}" id="{{ 'checkbox' + tag }}" (ngModel)="finalData.tags[i]"/>{{ tag }}</label>
</div>
<button type="submit" [disabled]="form.invalid" class="btn btn-primary btn-success">Save</button>
</form>
I want to POST value from checkboxes based on whether they checked or not.
This way with one-way binding (ngModel) it will POST all tags whether they checked or not. If I use two-way binding [(ngModel)] it will POST boolean values and it will change name and id based on boolean value, which I don't want.
Example:
If i check this I want POST foo instead of true
<label><input type="checkbox" name="footag" id="footag" value="foo" [(ngModel)]="finalData.tags[i]"/>foo</label>
This is component used for data binding:
import { Component, OnInit, Injectable } from "#angular/core";
import { DataService } from "../shared/dataService";
import { FinalFormData } from "../shared/finalFormData";
import { ActivatedRoute, Router } from '#angular/router';
import { Observable } from "rxjs/Observable";
import { NgForm } from "#angular/forms";
#Component({
selector: "final-form",
templateUrl: "finalForm.component.html"
})
export class FinalFormComponent implements OnInit{
constructor(private data: DataService, private route: ActivatedRoute, private router: Router) {
}
public finalData: FinalFormData;
public errorMessage = "";
public isBusy = true;
submitForm() {
this.data.postData(this.finalData)
.subscribe(data => {
this.finalData = data;
this.router.navigate(["/"]);
}, err => console.log(err));
}
ngOnInit(): void {
//let url = encodeURIComponent(this.route.snapshot.queryParams['url']);
//this.data.loadData(url)
// .subscribe(finalData => {
// this.finalData = finalData;
// });
this.finalData = this.route.snapshot.data['finalData'];
}
}
FinalFormData class:
export class FinalFormData {
name: string;
url: string;
dateCreated: Date;
tags: any[];
}
you can use the ngModelChange method to pass the value and set it to any variable you want. Refer sample code snippet below:
<label><input type="checkbox" name="footag" id="footag" value="foo" [ngModel]="finalData.tags[i]" (ngModelChange)="CheckBoxValueChange('foo',finalData)"/>foo</label>
in the component.ts file, you can access the value and set it to any variable you want:
CheckBoxValueChange(checkboxValue:string,finalData:any){
finalData.checkboxText=checkboxValue;
alert(checkboxValue);
}
I am trying to setup the login for users on our website. Users can sign up and the db collects their email and password, but I cannot verify the login email or password. More details below..
Here is the login component:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { Store } from '#ngrx/store';
import * as fromApp from '../../../reducers';
import * as app from '../../../core/store/app.actions';
import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
#Component({
selector: 'app-client-login',
templateUrl: './client-login.component.html',
styleUrls: ['./client-login.component.css']
})
export class ClientLoginComponent {
client: FormGroup;
constructor(
private _fb: FormBuilder,
private _afAuth: AngularFireAuth,
private _afDb: AngularFireDatabase,
private _appStore: Store<fromApp.State>
) {
this.buildForm();
// this._appStore.dispatch(new app.DisplayLoading());
}
ngOnInit() {}
buildForm(): void {
this.client = this._fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['',Validators.required],
});
}
login(email: string, password: string) {
return this._afAuth.auth.signInWithEmailAndPassword(email,
password)
}
}
Here is the html
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-sm-12 col-md-6">
<form [formGroup]="client">
<h2 class="form-signin-heading">Please login</h2>
<div class="form-group">
<input type="text" formControlName="email" id="email"
class="form-control" name="username" placeholder="Email Address"
required="" autofocus="" />
<input type="password" formControlName="password" id="password"
class="form-control" name="password" placeholder="Password"
required=""/>
<label class="checkbox">
<input type="checkbox" value="remember-me" id="rememberMe"
name="rememberMe"> Remember me
</label>
</div>
<button (click)="login()" class="btn btn-primary"
type="submit">Login</button>
</form>
</div>
</div>
</div>
Here is the error message:
{code: "auth/argument-error", message: "signInWithEmailAndPassword failed: First argument "email" must be a valid string.", ngDebugContext: DebugContext_, ngErrorLogger: ƒ}
Please let me know if you need more information. If you would like to view the project in our GitHub directory, please follow this link.
https://github.com/htobolka/nile-delivery
We are always looking for help!
The issue is your event handler (i.e., login()) has no parameters specified, but login requires the email and password passed in as parameters. In this case, the email and password are passed as undefined to signInWithEmailAndPassword(), resulting in the runtime error you observed.
To solve the issue, you could either update your template to pass in the email and password values:
<button (click)="login(client.get('email').value, client.get('password').value)" class="btn btn-primary" type="submit">Login</button>
Or you could update login to read the form values imperatively:
login() {
const email = this.client.get('email').value;
const password = this.client.get('password').value;
return this._afAuth.auth.signInWithEmailAndPassword(email, password);
}