How to save text from input to variable in angular? - html

I'm trying to take text from one of my component.html files and save the input to a variable in a method in one of my .ts files. Can you help?
home.component.html file:
Username: <input ng-model="username"><br>
Password: <input ng-model="pass">
<button (click)="login()">Login</button>
home.component.ts file:
export class HomeComponent implements OnInit {
login()
{
const usr= {{username}};
const password={{pass}};
print("user is"+usr " Password is"+password);
}
}

If you are using angular it should be
ngModel instead of ng-model
Username: <input [(ngModel)]="username"><br>
Password: <input [(ngModel)]="pass">
and in component.ts
export class HomeComponent implements OnInit {
username : string;
password : string;
login()
{
const usr= this.username;
const password= this.password;
console.log("user is"+usr " Password is"+password);
}
}

you need to change ng-model to ngModel
ng-model :- angularjs
ngModel :- Angular 2 or greater
Html
Username: <input [(ngModel)]="username"><br>
Password: <input [(ngModel)]="pass">
<button (click)="login()">Login</button>
Component
export class HomeComponent implements OnInit {
public username: String;
public pass: String;
public function login() {
console.log('User Name: ' + this.username);
console.log('Password: ' + this.pass);
}
}

Related

Create common input field in Angular

I have created common input field which can be usable across app and it will work with or without reactive form.
For e.g.: I have created common input angular component but it works with reactive form only as it has formGroup and formControlName.
input.html:
<div class="form-control" *ngIf="isRequired" [formGroup]="parentForm">
<label class="label">
{{labelText}}
</label>
<input [type]="inputType" class="input" [control]="control" [formControlName]="formControlNameText" [placeholder]="placeholderText">
</div>
input.ts:
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss'],
})
export class InputComponent implements OnInit {
#Input() parentForm: any;
#Input() labelText: string;
#Input() inputType: string = "text";
#Input() formControlNameText: string;
#Input() placeholderText: string;
#Input() isRequired: boolean = false;
#Input() requiredMsg: string;
#Input() maxlengthMsg: string;
#Input() control: any;
#Input() type: string;
constructor() { }
ngOnInit() { }
}
Call from one of my form Page:
<app-input parentForm="surveyResponseForm" labelText="test" inputType="text" placeholderText="placeholder"
formControlNameText="authorName" control="" isRequired=true id="authorName">
</app-input>
How do I use this common input if I want to use this without form?
I mean how do I use this selector: app-input in a component which doesn't have any form.
You could add an #Input() property to your component, for example useInForm: boolean, and check its value in your template. If useInForm is true, you would use the [formGroup] and formControlName properties, otherwise you would use a regular element without those properties example in the withoutFormTemplate.
<div class="form-control" *ngIf="isRequired && useInForm; else withoutFormTemplate" [formGroup]="parentForm">
<label class="label">
{{labelText}}
</label>
<input [type]="inputType" class="input" [control]="control" [formControlName]="formControlNameText" [placeholder]="placeholderText">
</div>
<ng-template #withoutFormTemplate>
<input [(ngModel)]="control" [type]="inputType" class="input" [placeholder]="placeholderText">
<ng-template>
I solve more or less same problem by creating a FormGroup. It's not easiest solution, but that working on multiple scenarios.
If not, maybe that give you some clues how to solve your problem...
Form component ts
// Reactive Forms
form: FormGroup;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
// Form structure and validators
this.form = this.formBuilder.group({
'user' : this.formBuilder.group({
'username' : ['', Validators.required],
'email' : ['', [Validators.required, Validators.email]]
}),
'identity' : this.formBuilder.group({
'firstname' : ['', Validators.required],
'lastname' : ['', Validators.required],
'address' : this.formBuilder.group({
'street' : ['', Validators.required],
'city' : ['', Validators.required],
})
})
});
}
onSubmit() {
// Get object with same structure as form but only with values
console.log(this.form.value);
alert('Form is ' + (this.form.invalid ? 'invalid' : 'valid'));
}
Form component html
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<form-text [formGroupParent]="form.get(['user'])"
[formGroupControlName]="'username'">
</form-text>
<form-text [formGroupParent]="form.get(['user'])"
[formGroupControlName]="'email'">
</form-text>
<hr>
<form-text [formGroupParent]="form.get(['identity'])"
[formGroupControlName]="'firstname'">
</form-text>
<form-text [formGroupParent]="form.get(['identity'])"
[formGroupControlName]="'lastname'">
</form-text>
<hr>
<form-text [formGroupParent]="form.get(['identity','address'])"
[formGroupControlName]="'street'">
</form-text>
<form-text [formGroupParent]="form.get(['identity','address'])"
[formGroupControlName]="'city'">
</form-text>
<button type="submit">Submit</button>
</form>
Custom input component ts (form-text)
// Needed to bind formControlName
#Input() formGroupParent: FormGroup;
#Input() formGroupControlName: string;
// FormControl store validators
control: FormControl;
ngOnInit() {
// Fetch Form control (validator) from FormGroup parent
this.control = <FormControl>this.formGroupParent.get(this.formGroupControlName);
}
Custom input component html (form-text)
<ng-container [formGroup]="formGroupParent">
<label>{{formGroupControlName}}</label>
<input type="text" formControlName="{{formGroupControlName}}">
</ng-container

How to put Variable in Statement [Angular, TypeScript]

This is in Angular,
I want to use variable to change my conditional statement so I don't need to modify every variable and type again
This is a code in input tag HTML
.
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
.
public form: FormGroup;
private formBuilder: FormBuilder
.
get f() { return this.form.controls; }
.
this.form = this.formBuilder.group({
id: ['00000000-0000-0000-0000-000000000000'],
name: ['', Validators.required],
email: ['', [Validators.required, Validators.pattern("^[a-z0-9._%+-]+#[a-z0-9.-]+\\.[a-z]{2,4}$")]],
oraganize: ['', Validators.required],
});
.
<input
...
[ngClass]="{'is-invalid': f.name.invalid && (f.name.dirty || f.name.touched)}"
>
So my code will change every time when there is a new input such as name, email, oraganize, etc
I want to build a function that I can pass some string and make it super nice not to modify all the time with the long line.
ex:
public checkCondition(attribute: string): boolean{
return (`this.f.${attribute}.invalid && (this.f.${attribute}.dirty || this.f.${attribute}.touched)`);
}
so I can use as...
<input
...
[ngClass]="{'is-invalid': checkCondition("name")}"
>
Please, So can I do it this way or not? or does it just works with only the string, not the condition?
it looks like you where very close. this should work.
public checkCondition(key: string): boolean{
return this.f[key].invalid && (this.f[key].dirty || this.f[key].touched);
}
or you can further simplify it
public checkCondition(key: string): boolean{
return {
'is-invalid': this.f[key].invalid && (this.f[key].dirty || this.f[key].touched)
};
}
and you html
<input [ngClass]="checkCondition('name')" />
Here is what it would look like all together
import { Component } from '#angular/core';
import { FormBuilder, Validators } from '#angular/forms';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
form = this.formBuilder.group({
id: ['00000000-0000-0000-0000-000000000000'],
name: ['', Validators.required],
email: ['', [Validators.required, Validators.pattern("^[a-z0-9._%+-]+#[a-z0-9.-]+\\.[a-z]{2,4}$")]],
oraganize: ['', Validators.required],
});
constructor(private formBuilder: FormBuilder) {}
checkCondition(key: string) {
const control = this.form.get(key);
if (!control) {
return;
}
return {
'is-invalid': control.invalid && (control.dirty || control.touched)
};
}
}
<form [formGroup]="form">
<input formControlName="id" [ngClass]="checkCondition('id')" />
<input formControlName="name" [ngClass]="checkCondition('name')" />
<input formControlName="email" [ngClass]="checkCondition('email')" />
<input formControlName="oraganize" [ngClass]="checkCondition('oraganize')" />
</form>
Here is a working stackBlitz
https://stackblitz.com/edit/angular-ivy-cvwmis?file=src%2Fapp%2Fapp.component.html

Angular error "Cannot read property 'firstName' of undefined"

Hi i am working on a search service to look for usernames in a elasticsearch database but i got the following error when i want to display the f.e. firstName of the user: Cannot read property 'firstName' of undefined.
I am working with Angular and Elasticsearch
service:
export class SearchService {
getElastic = 'http://34.62.28.281:9200/users/_doc/_search?q=';
private handleError: HandleError;
constructor(
private http: HttpClient,
httpErrorHandler: HttpErrorHandler) {
this.handleError = httpErrorHandler.createHandleError('TimelineService');
}
/** GET elasticsearch result */
getElasticResult( text: string ): Observable<User> {
this.http.get<User>(this.getElastic + text).subscribe(res => console.log(res));
return this.http.get<User>(this.getElastic + text, {responseType: 'json'});
}
EDIT:
The new HTML form:
<form [formGroup]="angForm2" *ngIf="user != null" (ngSubmit)="getUser()" class="form-inline my-5 my-lg-0">
<input id="searchText" name="searchText" class="form-control" type="string" placeholder="Search for user" aria-label="Post"
formControlName="searchText" required>
<p>{{user?.firstName}}</p>
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
the new component:
export class SearchServiceComponent implements OnInit {
user: User;
angForm2 = this.fb.group({
searchText: ['', Validators.required]
});
ngOnInit() {
this.getUser();
this.getObject();
}
constructor(private searchservice: SearchService, private fb: FormBuilder) { }
getUser() {
const userName = this.angForm2.value.searchText;
console.log(this.angForm2.value, userName);
this.searchservice.getElasticResult(userName).subscribe(user => (this.user = user));
}
getObject() {
return this.user;
}
}
Output of user and this.user:
User interface:
export interface User {
$oid: string;
firstName: string;
lastName: string;
username: string;
password: string;
follows: User[];
}
I guess getObject() is getting called when you load the form, by the time user is undefined so you are getting that error. why dont you just use user?.firstName since you already have the variable defined ?
<p>{{user?.firstName}}</p>
In your html you need to do something like this
<p>{{usersFirstName}}</p>
In your ts code, once you get the response from the server set this usersFirstName.
usersFirstName : string;
getUser() {
const userName = this.angForm2.value.searchText;
console.log(this.angForm2.value, userName);
this.searchservice.getElasticResult(userName).subscribe(user => (this.user = user)
this.usersFirstName = user.name;
);
}
1.SearchServiceComponent should implement OnInit class and implement its ngOnInit method
2. Call both the methods inside ngOnInit method sequentially
3. Check if this.user is not equal to null or undefined and handle it using ngIf condition
Answered by Sajitharan
Example for OnInit
TS
#Component({selector: 'my-cmp', template: `...`})
class MyComponent implements OnInit {
ngOnInit() {
this.getUser();
this.getObject()
}
getUser() {
const userName = this.angForm2.value.searchText;
console.log(this.angForm2.value, userName);
this.searchservice.getElasticResult(userName).subscribe(user => (this.user = user.hits.hits[0]._source));
}
getObject(){}
}

Angular TypeError: Cannot read property '0' of undefined when using event.target.file[0]

I'm currently trying to take a file input from a user and store it to Firebase Storage using AngularFire. Since it's undefined, I'm convinced that whatever file they're looking at, it's NULL, but my UI clearly shows that I'm successfully inputting a file, but the error gets caught as soon as I select the file. Am I misunderstanding how the input sends information to my TypeScript file?
Here's my TS file:
import { AngularFirestore } from '#angular/fire/firestore';
import { Component, OnInit, Input, ChangeDetectorRef } from '#angular/core';
import { finalize, tap, map } from 'rxjs/operators';
import { FormBuilder, FormGroup, FormArray, Validators } from '#angular/forms';
import { SubmitPostService } from './submit-post.service';
import { Post } from '../post.model';
import { Observable } from 'rxjs';
#Component({
selector: 'app-post-creation',
templateUrl: './post-creation.component.html',
styleUrls: ['./post-creation.component.scss']
})
export class PostCreationComponent implements OnInit {
private uuidv4 = require('uuid/v4');
// Main task
task: AngularFireUploadTask;
// Progress Monitoring
percentage: Observable<number>;
// Download URL
downloadURL: Observable<string>;
myForm: FormGroup;
post: Post;
ref: AngularFireStorageReference;
files: Observable<any>;
constructor(
private formBuilder: FormBuilder,
private postService: SubmitPostService,
private storage: AngularFireStorage,
) { }
ngOnInit() {
this.myForm = this.formBuilder.group({
title: ['', [Validators.required]],
artists: ['', [Validators.required]],
description: '',
medium: ''
});
this.myForm.valueChanges.subscribe(console.log);
}
onSubmit() {
this.post = new Post(
this.uuidv4(),
this.myForm.get('artists').value,
this.myForm.get('title').value,
new Date(),
new Date(),
`images/${Date.now()}_${this.myForm.get('title').value}`,
this.myForm.get('description').value,
this.myForm.get('medium').value
);
this.postService.submitPost(this.post);
}
upload(event: any) {
console.log('Upload successful');
try {
const file = event.target.file[0];
// The storage path
const path = `images/${Date.now()}_${file.name}`;
// Reference to storage bucket
this.ref = this.storage.ref(path);
// Main Task
this.task = this.ref.put(file);
// Tracks progress
this.percentage = this.task.percentageChanges();
this.percentage = this.task.snapshotChanges()
.pipe(map(s => (s.bytesTransferred / s.totalBytes) * 100));
this.downloadURL = this.ref.getDownloadURL();
} catch (err) { console.log(err); }
}
}
Here's my HTML:
<div>
<div class="progress">
<progress max="100" [value]="(percentage | async)"></progress>
</div>
<h1>Post Creation</h1>
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput placeholder="Title" formControlName="title">
</mat-form-field>
<br>
<mat-form-field>
<input matInput placeholder="Artists" formControlName="artists">
</mat-form-field>
<br>
<mat-form-field>
<input matInput placeholder="Description" formControlName="description">
</mat-form-field>
<br>
<mat-form-field>
<input matInput placeholder="Medium" formControlName="medium">
</mat-form-field>
<br>
<input type="file" (change)="upload($event)" accept=".png,.jpg">
<br>
<br>
<button mat-raised-button [disabled]="myForm.invalid" color="primary">Submit Post</button>
</form>
</div>
</body>
I've successfully created the Post objects in the Firestore, so it's not an issue of my firebase configs aren't correctly initialize.
In your upload method, in the const file = event.target.file[0]; statement, the file property should be plural

Angular 2 dialog popup with text field input

I have a simple popup that shows a message with OK button to release it, what I want is to add to this popup a text field that the user will need to type something in it and click OK to submit his answer.
currently it looks like this:
#Component({
selector: 'dialog-component',
template: `<h2>{{title}}</h2>
<p>{{message}}</p>
<button md-button (click)="dialog.close()">OK</button>`
})
export class DialogComponent {
public title: string;
public message: string;
constructor( public dialog: MdDialogRef<DialogComponent>) { }
}
and im using it like:
public showDialog(message: MessageBoxMessage) {
if (typeof message !== 'undefined') {
let dialogRef: MdDialogRef<DialogComponent> = this._dialog.open(DialogComponent);
dialogRef.componentInstance.title = message.title;
dialogRef.componentInstance.message = message.content;
}
}
how can I change it to have a popup with text-field and ok button tht pass me the value of the text-field?
You can create EventEmitter in your dialog:
#Component({
selector: 'dialog-component',
template: `<h2>{{title}}</h2>
<p>{{message}}</p>
<mat-form-field class="example-full-width">
<input matInput placeholder="Favorite food" #input>
</mat-form-field>
<button mat-button (click)="onOk.emit(input.value); dialog.close()">OK</button>`
})
export class DialogComponent {
public title: string;
public message: string;
onOk = new EventEmitter();
constructor( public dialog: MatDialogRef<ErrorDialogComponent>) { }
}
then subscribe to it in parent component
dialogRef.componentInstance.onOk.subscribe(result => {
this.resultFromDialog = result;
})
Plunker Example
Another way is passing value to MatDialog.close method
(click)="dialog.close(input.value)"
....
dialogRef.afterClosed().subscribe(result => {
this.resultFromDialog = result;
});
Plunker Example
You can bind the answer to a model like this :
#Component({
selector: 'dialog-component',
template: `<h2>{{title}}</h2>
<p>{{message}}</p>
<input type="text" name="data" [(ngModel)]="data">
<button md-button (click)="dialog.close()">OK</button>`
})
export class DialogComponent {
public title: string;
public message: string;
data: string;
constructor( public dialog: MdDialogRef<ErrorDialogComponent>) { }
}
And then bind the (click) to a function that sends your data.