I have a problem with dialog from angular material, when i press button to open it, it does, but not rly. Dialog does not show up but console prints 'open' and 'close', no errors
Dialog component
import {Component, Inject} from '#angular/core';
import {RssFeed} from "../model/rssFeed";
import {MAT_DIALOG_DATA, MatDialogRef} from "#angular/material";
import {AppService} from "../service/app.service";
#Component({
selector: 'app-new-feed-dialog',
templateUrl: './new-feed-dialog.component.html',
styleUrls: ['./new-feed-dialog.component.css']
})
export class NewFeedDialogComponent {
rssFeed: RssFeed = new RssFeed();
constructor(private service: AppService,
public dialogRef: MatDialogRef<NewFeedDialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: any) {
}
onSaveClick(): void {
this.service.saveRssFeed(this.rssFeed)
this.dialogRef.close(this.rssFeed);
}
onCancelClick(): void {
this.dialogRef.close();
}
}
html
<h2 mat-dialog-title>
<mat-icon>library_add</mat-icon>
New Feed
</h2>
<mat-dialog-content>
<form>
<mat-form-field class="full-width">
<input matInput placeholder="Feed Name" name="name" [(ngModel)]="rssFeed.name">
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="Feed Url" name="url" [(ngModel)]="rssFeed.url">
</mat-form-field>
</form>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button (click)="onCancelClick()">Cancel</button>
<button mat-button (click)="onSaveClick()">Save</button>
</mat-dialog-actions>
I'm opening it from another component
onAddRssFeedClick(): void{
let dialogRef = this.dialog.open(NewFeedDialogComponent)
dialogRef.afterOpen().subscribe( ()=> {
console.log('open')
})
dialogRef.afterClosed().subscribe(() => {
console.log('close')
});
}
In your app.component.html, there is the button that triggers your modal <a class="nav-link" (click)="onAddRssFeedClick()" href="#">Add Feed</a>
Remove the href="#" and you're good!
Related
I'am new to angular 8.
I'am currently doing a small assignment for college but with this all Covid 19 thing happening communication with the lecture is limited and because of this is slowing my down.
I googled the error for ages and cant seem to find whats wrong.
Thanks.
<button (click)="show = !show">{{show ? 'Hide' : 'Add a car'}}</button>
<div *ngIf="show">
<form>
<label>Make</label>
<input type="text" name="make" placeholder="Enter Make" #make>
<label>Model</label>
<input type="text" name="model" placeholder="Enter Model" #model>
<label>Year</label>
<input type="text" name="year" placeholder="Enter Year" #year>
<button type="submit" (click)="addTheCar(make.value,
model.value,year.value)">Add the Car</button>
</form>
</div>
<div class="container">
<app-car *ngFor="let carData of carsData" [carData]="carData"></app-car>
</div>
This is the carlist.component.html(where the error sends me)
import { Component, OnInit } from '#angular/core';
import { ICar, Car } from '../interfaces/car';
import { CarApiService } from '../services/car-api.service';
#Component({
selector: 'app-carlist',
templateUrl: './carlist.component.html',
styleUrls: ['./carlist.component.css'],
providers: [CarApiService]
})
export class CarlistComponent implements OnInit {
carsData: ICar[];
constructor(private _carAPIService:CarApiService) { }
ngOnInit(): void{
this._carAPIService.getCarData().subscribe(carsData =>
{this.carsData = carsData});
}
addTheCar(make:string, model:string, year:string):boolean{
let tempCar:ICar;
tempCar= new Car(make,model,year);
this._carAPIService.addCarData(tempCar);
return false;
}
}
You have to define show in CarlistComponent.ts
export class CarlistComponent implements OnInit {
show:boolean;
It is what it says: there is no show property on your component. Add show = false; under your carsData line and it should go away.
try this
import { Component, OnInit } from '#angular/core';
import { ICar, Car } from '../interfaces/car';
import { CarApiService } from '../services/car-api.service';
#Component({
selector: 'app-carlist',
templateUrl: './carlist.component.html',
styleUrls: ['./carlist.component.css'],
providers: [CarApiService]
})
export class CarlistComponent implements OnInit {
carsData: ICar[];
show:boolean;
constructor(private _carAPIService:CarApiService) { }
ngOnInit(): void{
this._carAPIService.getCarData().subscribe(carsData =>
{this.carsData = carsData});
}
addTheCar(make:string, model:string, year:string):boolean{
let tempCar:ICar;
tempCar= new Car(make,model,year);
this._carAPIService.addCarData(tempCar);
return false;
}
}
specify a boolean value for show
export class CarlistComponent implements OnInit {
public show = true;
Only when show = true this div will get executed
<div *ngIf="show">
<form>
<label>Make</label>
<input type="text" name="make" placeholder="Enter Make" #make>
<label>Model</label>
<input type="text" name="model" placeholder="Enter Model" #model>
<label>Year</label>
<input type="text" name="year" placeholder="Enter Year" #year>
<button type="submit" (click)="addTheCar(make.value,
model.value,year.value)">Add the Car</button>
</form>
</div>
I have been trying to make a form for blog posting, and I want to have selectable category icons next to the title.
I made a form with selectable font awesome icons, but when I select a category I can't select another one to change the icon again. It only changes if I "reset" it with the "None" option in-between each selection.
However, when I change the code to use the icon name as a string, instead of as an icon input it changes with every selection, as I want it to. I just don't understand how it can update the text regularly but not the icon.
This is my actual code:
[create.component.html]
...
<div class="blog-container">
<mat-card class="blog-card">
<section>
<h2>Create blog post</h2>
</section>
<form [formGroup]="createForm" class="width-1">
<div class="width-1">
<mat-form-field class="blog-title" appearance="outline">
<mat-label>Post Title*</mat-label>
<input matInput formControlName="newTitle" #newTitle>
<mat-icon matSuffix *ngIf="category" [fontSet]="category.set" [fontIcon]="category.icon"></mat-icon>
<mat-hint>the first two fields are required</mat-hint>
</mat-form-field>
</div>
<div class="width-1">
<mat-form-field class="blog-text" appearance="outline">
<mat-label>Bread Text*</mat-label>
<textarea matInput rows="2" formControlName="newText" #newText></textarea>
</mat-form-field>
</div>
<div class="width-1 blog-row">
<mat-form-field class="blog-author" appearance="fill">
<mat-label>Author</mat-label>
<input matInput formControlName="newAuthor" #newAuthor>
</mat-form-field>
<mat-form-field class="blog-category" appearance="fill">
<mat-label>Category</mat-label>
<mat-select [(value)]="category" formControlName="newCategory" #newCategory>
<mat-select-trigger *ngIf="category">
<span>{{category.name}}</span>
</mat-select-trigger>
<mat-option [value]="null">
<span>None</span>
</mat-option>
<mat-option *ngFor="let category of categories" [value]="category">
<mat-icon [fontSet]="category.set" [fontIcon]="category.icon"></mat-icon>
<span>{{category.name}}</span>
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="width-1 center">
<button mat-raised-button color="primary" routerLink="/archive">BACK</button>
<button type="submit" (click)="addPost(title.value, text.value, author.value, category.value)" [disabled]="createForm.pristine || createForm.invalid" mat-raised-button color="primary">POST</button>
</div>
</form>
</mat-card>
</div>
...
[create.component.ts]
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import { PostService } from '../../post.service';
#Component({
selector: 'app-create',
templateUrl: './create.component.html',
styleUrls: ['./create.component.scss']
})
export class CreateComponent implements OnInit {
createForm: FormGroup;
category: CategoryDTO = null;
categories: CategoryDTO[] = [
new CategoryDTO({name: 'Programming', set: 'fas', icon: 'fa-laptop-code'}),
new CategoryDTO({name: 'Croshetting', set: 'fas', icon: 'fa-cut'}),
new CategoryDTO({name: 'Arts/Crafts', set: 'fas', icon: 'fa-tools'})
];
constructor(private postService: PostService, private fb: FormBuilder, private router: Router) {
this.createForm = this.fb.group({
newTitle: ['', Validators.required],
newText: ['', Validators.required],
newAuthor: '',
newCategory: ''
});
}
addPost(newTitle, newText, newAuthor, newCategory){
this.postService.addPost(newTitle, newText, newAuthor, newCategory).subscribe(() => {
this.router.navigate(['/archive']);
});
}
ngOnInit() {
}
}
class CategoryDTO {
name: string;
set: string;
icon: string;
constructor(category?: any) {
this.name = category && category.name || null;
this.set = category && category.set || null;
this.icon = category && category.icon || null;
}
}
Since I can't load the Font Awesome CSS in StackBlitz (as far as I know), this is the closest I could come to reproducing a manageable code there.
I am new to Angular.
I imported FormsModule and CommonModule (FontAwesomeModule was already there) in my create.component.ts file, and I re-added node_modules/#fortawesome/fontawesome-free/css/all.min.css in "styles: [...]" in angular.json, and that did the trick!
As far as I can tell, having import { faCut, faCode, faTools } from '#fortawesome/free-solid-svg-icons'; in create.component.ts makes no difference.
Thanks to "Allabakash" for pointing me in the right direction. :)
I am using angular stepper to display all my data and take input for some of the text boxes, but I want to add my custom validations when user clicks on Next button.
stackblitz - material-stepper-custom-validation
html:
<mat-horizontal-stepper #stepper>
<mat-step>
<div class="m-10">
<input type="text" id="fname" placeholder="First Name" >
</div>
<div class="m-10">
<input type="text" id="lname" placeholder="Last Name" >
</div>
<div>
<button mat-button (click)="checkData()" matStepperNext>Next</button>
</div>
</mat-step>
<mat-step [stepControl]="secondFormGroup" [optional]="isOptional">
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</mat-step>
<mat-step>
<ng-template matStepLabel>Done</ng-template>
You are now done.
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-horizontal-stepper>
Here, first name and last name should be validated before go to next stepper, but not using formGroup.
ts:
import {Component, OnInit} from '#angular/core';
import {FormBuilder, FormGroup, Validators} from '#angular/forms';
#Component({
selector: 'stepper-optional-example',
templateUrl: 'stepper-optional-example.html',
styleUrls: ['stepper-optional-example.css']
})
export class StepperOptionalExample implements OnInit {
constructor() {}
ngOnInit() { }
checkData() {
let lname = (<HTMLInputElement>document.getElementById("fname")).value;
if(lname == '') {
alert('error');
}
return false;
}
}
How? - If first name is empty then don't allow them to go Next stepper.
Because you use the template driven approach, you will need to map all input fields into an ngModel somehow. Here is an example for it:
HTML:
<input type="text" required [(ngModel)]="model.name" name="name">
TS:
#Component({
selector: 'stepper-optional-example',
templateUrl: 'stepper-optional-example.html',
styleUrls: ['stepper-optional-example.css']
})
export class StepperOptionalExample implements OnInit {
#ViewChild('stepper') stepper;
model = {
name: 'Initial Value'
}
constructor() {}
ngOnInit() { }
}
Using that you can then, check the attribute onClick. You need to remove the matStepperNext and add the (click) event listener instead like so:
HTML:
<button mat-button (click)="onNext()">Next</button>
TS:
onNext() {
// Validate your value in the function
if (this.model.name !== 'Henry') {
this.stepper.next();
}
}
Other than that I also recommend to take a look on the official guide showing how to implement the template driven approach: https://angular.io/guide/forms
Placing a child component with inputs in a parent form and submitting with invalidation will not show the errors in the child component only in the parent. The mat-error in the child will only show when clicked on the inputs.
To replicate the error with this parent Form
#Component({
selector: 'lyx-parent-form',
template: `
<form novalidate autocomplete="off" role="form" [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-form-field>
<input type="password" formControlName="currentPassword" matInput placeholder="current password">
<mat-error *ngIf="form.get('currentPassword').hasError('required')">current required</mat-error>
</mat-form-field>
<lyx-child [form]="form"></lyx-child>
<button type="submit">submit</button>
</form>`
})
export class ParentFormComponent {
form: FormGroup;
constructor(fb: FormBuilder) {
this.form = fb.group({'currentPassword': ['', [Validators.required]]});
}
onSubmit() {}
}
The child component
#Component({
selector: 'lyx-child',
template: `
<div [formGroup]="form">
<mat-form-field>
<input type="password" formControlName="newPassword" matInput placeholder="password">
<mat-error *ngIf="form.get('newPassword').hasError('required')">Password Required</mat-error>
</mat-form-field>
</div> `
})
export class ChildComponent implements OnInit {
#Input() form: FormGroup;
ngOnInit(): void {
const newPassword = new FormControl('', Validators.compose([Validators.required]));
this.form.addControl('newPassword', newPassword);
}
}
Here is a workaround before I'm able to better understand the way the parent/child form interact.
When submitting the parent form manually set the child "newPassword" control as "touched"
onSubmit(): void {
this.form.controls.newPassowrd.markAsTouched({onlySelf: true});
}
I came up with the following solution that works for any number of nested forms. To use this directive, simply add formSubmittedSync to any child form group, e.g., <div [formGroup]="childForm" formSubmittedSync>
import { Directive, SkipSelf } from "#angular/core";
import { FormGroupDirective, ControlContainer } from "#angular/forms";
#Directive({
selector: '[formSubmittedSync]'
})
export class FormSubmittedSyncDirective {
constructor(
#SkipSelf() private parentFormGroupDirective: FormGroupDirective,
private formGroupDirective: FormGroupDirective) {
this.parentFormGroupDirective.ngSubmit.asObservable().subscribe(() => {
(this.formGroupDirective as any).submitted = true;
this.formGroupDirective.ngSubmit.emit();
});
}
}
I am new in angular and I want to know how to change property disabled in a button, with get-response recaptcha in angular 4 form.component
I try with this but not working:
<div class="login-page">
<div class="form">
<form class="login-form">
<input type="text" placeholder="Usuario" required/>
<input type="password" placeholder="Contraseña" required/>
<div >
<re-captcha class="g-recaptcha" (resolved)="resolved($event)"
siteKey="6LcOuyYTAAAAAHTjFuqhA52fmfJ_j5iFk5PsfXaU">
</re-captcha>
</div>
<button id="entrarbtn" onclick="captcha;" (click)="submit()" type="submit"
disabled>Entrar</button>
<p class="message">No se ha registrado? <a href="/registrar">Cree una
cuenta</a>
</p>
<script>
var captcha = function ()
{var response = grecaptcha.getResponse();
if(response.length == 0)
{return false;}
else
{$("#entarbtn").prop("disable"), false;
return true;
}};
</script>
</form>
</div>
</div>
in login.component.ts
import { Component, OnInit } from '#angular/core';
import {Router} from "#angular/router";
export interface FormModel {
captcha?: string;}
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
public submit(): void {this.router.navigate(['/pagina']);}
constructor(private router: Router)
{ }
ngOnInit() {}
}