import {Component, Inject} from '#angular/core';
import {MdDialog, MdDialogRef, MD_DIALOG_DATA} from '#angular/material';
/**
* #title Dialog Overview
*/
#Component({
selector: 'dialog-overview-example',
templateUrl: 'dialog-overview-example.html'
})
export class DialogOverviewExample {
animal: string;
name: string;
constructor(public dialog: MdDialog) {}
openDialog(): void {
let dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
width: '250px',
data: { name: this.name, animal: this.animal }
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
this.animal = result;
});
}
}
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MdDialogRef<DialogOverviewExampleDialog>,
#Inject(MD_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close();
}
}
Let's say i have the code as above. And the result shown below:
Based on this picture, how can i determine if the user clicked OK or No thanks. I want to create a function for each event. tried dialogRefAfterClose but it runs no matter what button i click.
In your dialog html, dialog-overview-example-dialog.html, You can just add (click) event in your both button.
<div mat-dialog-actions>
<button mat-button (click)="clickOK()" tabindex="2">Ok</button>
<button mat-button (click)="clickNo()" tabindex="-1">No Thanks</button>
</div>
and you can close the dialog programmaticly:
clickNo() {
console.log('No button clicked');
this.dialogRef.close();
}
clickOk() {
console.log('Ok button clicked');
this.dialogRef.close();
}
Hi I noticed that you are using the exact same example from angular.material.
The option you asked for need to be handled by Yourself according to your purpose. As seen in the example there.
my example
In here the onNoClick() and the onOkClick() does the Job
Add the functions in compontent ts and bind it in the component html
Dialog Component TS
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
#Inject(MAT_DIALOG_DATA) public data: any) { }
onNoClick(): void {
alert("You clicked no.")
this.dialogRef.close();
}
onOkClick():void{
alert("You clicked Ok");
}
}
Dialog Component HTML
<h1 mat-dialog-title>Hi {{data.name}}</h1>
<div mat-dialog-content>
<p>What's your favorite animal?</p>
<mat-form-field>
<input matInput tabindex="1" [(ngModel)]="data.animal">
</mat-form-field>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onOkClick()" [mat-dialog-close]="data.animal" tabindex="2">Ok</button>
<button mat-button (click)="onNoClick()" tabindex="-1">No Thanks</button>
</div>
You can do that with single function, no need to add functions for more buttons
Like this :
<div mat-dialog-actions>
<button mat-button (click)="clickBtn(true)" tabindex="2">Ok</button>
<button mat-button (click)="clickBtn(false)" tabindex="-1">No Thanks</button>
</div>
clickBtn(status) {
if(status)
console.log('Ok button clicked');
else
console.log('No button clicked');
this.dialogRef.close();
}
<button mat-button (click)="onNoClick()" [mat-dialog-close]="data.SelectedBtn">No Thanks</button>
<button mat-button (click)="onOkClick()" [mat-dialog-close]="data.SelectedBtn" cdkFocusInitial>Ok</button>
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: './dialog.html',
})
export class DialogComponent {
constructor(
public dialogRef: MatDialogRef<DialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) { }
onNoClick(): void {
this.data.SelectedBtn = false;
this.dialogRef.close(this.data.SelectedBtn);
}
onOkClick(): void {
this.data.SelectedBtn = true;
this.dialogRef.close(this.data.SelectedBtn);
}
}
Related
I have a template like the one below:
card.component.html
<mat-card class="mat-elevation-z4">
<img mat-card-image src="{{ item.media_url }}" />
<mat-card-content class="custom">
<p>{{ item.caption }}</p>
</mat-card-content>
</mat-card>
It is a Material Card used inside a parent View that creates a grid with cards, each having a specific item.media_url and item.caption
events.component.ts
<div class="content">
<div fxLayout="row wrap" fxLayoutGap="16px grid">
<div
fxFlex="25%"
fxFlex.md="33%"
fxFlex.sm="50%"
fxFlex.xs="100%"
*ngFor="let item of events"
>
<app-card [item]="item" #myCard></app-card>
<button mat-button (click)="openDialog(myCard)">SCOPRI DI PIU'</button>
</div>
</div>
</div>
As you can see, inside the ngFor loop, below each card, there's a button that is supposed to open a dialog showing only one card at a time (the one above the clicked button in the grid).
I would like to put very the same card with its item.media_url and item.caption in this dialog, so I thought to use the data property of MatDialog to do this.
card.component.ts
import { Component, OnInit, Input, Inject, Optional } from '#angular/core';
import { MAT_DIALOG_DATA } from '#angular/material/dialog';
#Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.css']
})
export class CardComponent implements OnInit {
#Input() item : any;
constructor(#Optional() #Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit(): void {
}
}
events.component.ts
import { Component, OnInit } from '#angular/core';
import { EventsService } from '../../shared/services/events.service';
import { MatDialog } from '#angular/material/dialog';
import { CardComponent } from 'src/app/shared/card/card.component';
#Component({
selector: 'app-events',
templateUrl: './events.component.html',
styleUrls: ['./events.component.css'],
})
export class EventsComponent implements OnInit {
events: any[];
constructor(private eventsService: EventsService, public dialog: MatDialog) {}
ngOnInit(): void {
this.getEvents();
}
getEvents(): void {
this.eventsService.getEvents().subscribe((response: any) => {
this.events = response.data;
console.log(this.events);
});
}
openDialog(card: any) {
this.dialog.open(CardComponent, {
data: {
item: card,
},
});
}
}
However, when I do this, I need to pass data to this.dialog.open(), not item, nor card.
Right now I am getting the error ERROR TypeError: ctx.item is undefined (which I perfectly understand why I am getting).
Is there a way I can somehow "alias" data as item, or maybe a better way to do this?
To make it work we did the following:
openDialog(card: CardComponent) { <-- strongly type
console.log(card.item); <-- access item
this.dialog.open(CardComponent, {
data: {
item: card.item <-- pass it as param
}
});
}
next in card.component.ts set the 'item` property.
constructor(#Optional() #Inject(MAT_DIALOG_DATA) public data: any) {
if (data) { <-- only if data is injected
this.item = data.item; <-- set item
}
}
Working Stackblitz
Robert's coment under your question answers the template / component part.
As for the data alias question, the answer is no. data is a property of the MatDialogConfig class, as shown here and to the best of my knowledge, you can't change it.
I created a class named alert, and I use it to display alerts whenever new post is created or deleted or changed.
but there is one issue, when I put the setAlert inside a DELETE/POST/PUT function, if the latter is located inside a service component, it gives me an error saying: ERROR
but when I move the function into its component.ts file, it works properly without any issues. So why is that happening and what can I do to make it work in a service?
Here is my Alert.ts:
export class alert{
"status" : boolean;
"text": string;
constructor(){
this.status=false;
this.text="";
}
public setAlert(text){
this.status = true;
this.text = text;
}
public close(){
this.status = false;
}
}
Here is my html file:
<div class="forms container">
<form #postForm="ngForm">
<div class="form-group">
<label for="title">Title</label>
<input [(ngModel)]="formService.form.title"
name="title"
id="title"
type="text"
class="form-control"
>
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea [(ngModel)]="formService.form.body"
name= "body"
id="body"
cols="30"
rows="10"
class="form-control"
></textarea>
</div>
<button class="btn btn-success" (click) = "formService.editForm()">Save</button>
<button class="btn btn-danger pull-right" (click) = "formService.deleteForm()">Delete</button>
<div class="container mt-4">
<div class="row">
<div class="col">
<div *ngIf = "alert.status" class="alert alert-success
alert-dismissible fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"
(click) = "alert.close()">
<span aria-hidden="true">×</span>
</button>
{{alert.text}}
</div>
</div>
</div>
</div>
</form>
</div>
Here is component.ts file:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { FormService } from './forms.service';
import { HttpClient } from '#angular/common/http';
import { alert } from './alert';
#Component({
selector: 'app-forms',
templateUrl: './forms.component.html',
styleUrls: ['./forms.component.css']
})
export class FormsComponent implements OnInit {
alert: alert;
id: any;
posts: any;
constructor(public formService: FormService ,private route: ActivatedRoute,
private router: Router, private http: HttpClient) { }
ngOnInit() {
this.id=this.route.snapshot.params['id'];
this.alert = new alert();
this.posts = this.formService.getForms(this.id).subscribe(
(forms: any) => {
this.formService.form = forms[0];
}
);
}
}
And here is service.ts file:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { form } from './form-interface';
import { alert } from './alert';
#Injectable({
providedIn: 'root'
})
export class FormService {
formsUrl = "https://jsonplaceholder.typicode.com/posts";
form: form = {
id: 0,
userId: 0,
title: '',
body: ''
};
alert: alert;
constructor(private http: HttpClient) { }
ngOnInit() {
this.alert = new alert();
}
getForms(id) {
return this.http.get('https://jsonplaceholder.typicode.com/posts'
+ "?id=" + id)
}
editForm() {
fetch(this.formsUrl + "/" + this.form.id, {
method: 'PUT',
body: JSON.stringify(this.form),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
this.alert.setAlert("Post has been successfully saved !");
}
deleteForm() {
this.http.delete(this.formsUrl + "/" + this.form.id)
.subscribe(
data => {
console.log("DELETE Request is successful ", data);
this.alert.setAlert("Post has been successfully deleted !");
},
error => {
console.log("Error", error);
}
);
}
}
Services don't have ngOnInit life cycle, change your code from ngOnInit to constructor.
constructor(private http: HttpClient) {
this.alert = new alert();
}
Only components and directives have life cycle hooks:
A Component has a lifecycle managed by Angular itself. Angular creates it, >renders it, creates and renders its children, checks it when its data-bound >properties change and destroy it before removing it from the DOM.
Directive and component instances have a lifecycle as Angular creates, updates, >and destroys them.
I have a page in which I have a Run button.If I click on Run button a dialog box appears with two options Yes and No.If a user clicks Yes I want to display a mat-progress bar.
I am confused as to where to write the html code of mat-progress bar and where to call it from.
HTML Code:
<mat-toolbar>
<div class="col-md-offset-11">
<button
mat-raised-button
mat-hint="Execute Query on Whole DataSet"
color="primary"
(click)="executeOnFullData()"
>
Run
</button>
</div>
</mat-toolbar>
TypeScript Code:
executeOnFullData() {
const dialogRef = this.dialog.open(ConfirmJobRunComponent, {
});
dialogRef.afterClosed()
}
HTML Code for dialogBox:
<div class="card">
<div class="card-header"><h5 class="title">Confirm</h5></div>
<div class="content">
<h3 mat-dialog-title>
Are you sure you want to run Recommendation Settings on the entire
Dataset?
</h3>
<div mat-dialog-actions>
<button
mat-button
[mat-dialog-close]="true"
(click)="confirmSelection()"
>
Yes
</button>
<button mat-button (click)="onNoClick()">
Cancel
</button>
</div>
</div>
Typescript Code for DialogComponent
import { MAT_DIALOG_DATA, MatDialogRef } from "#angular/material";
import { Component, Inject } from "#angular/core";
import { RecommendationService } from "../../recommendation-
service.service";
#Component({
selector: "app-confirm-job-run",
templateUrl: "./confirm-job-run.component.html",
styleUrls: ["./confirm-job-run.component.scss"]
})
export class ConfirmJobRunComponent {
constructor(
public dialogRef: MatDialogRef<ConfirmJobRunComponent>,
#Inject(MAT_DIALOG_DATA) public data: any,
public dataService: RecommendationService
) {}
onNoClick(): void {
this.dialogRef.close();
}
confirmSelection(): void {}
}
You can just subscribe to afterClosed of your dialogRef and based on the result you get back from your dialog (clicking Yes returns true, clicking No returns false) you can then show a mat-progress and execute your business logic.
Here
is a stackblitz showing how this could look like. The mat-progress
is currently indeterminate and not waiting for something to complete,
that is up to you.
Template (in your component where the button is located)
<mat-progress-bar *ngIf="showMatProgress" mode="indeterminate"></mat-progress-bar>
Component for above template
showMatProgress: boolean = false;
executeOnFullData() {
const dialogRef = this.dialog.open(ConfirmJobRunComponent, {});
dialogRef.afterClosed().subscribe((result) => {
this.showMatProgress = result;
});
}
An in your dialog component
onNoClick(): void {
this.dialogRef.close(false);
}
confirmSelection(): void {
this.dialogRef.close(true);
}
I recently learned Angular2. Currently, I have got a material modal after some searching. However,I can't find how I return the data that the user can input.
In the modal I currently have, there is one input field and one checkbox. When close the console logs "de dialog closed" and "true".
This is my modal HTML:
<h2 mat-dialog-title>Add Group</h2>
<mat-dialog-content>
<div>
<mat-form-field>
<input matInput placeholder="Groupname">
</mat-form-field>
<mat-form-field>
<mat-checkbox >Private group?</mat-checkbox>
</mat-form-field>
<mat-form-field>
<button mat-raised-button color="primary">img</button>
</mat-form-field>
</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-dialog-close>cancel</button>
<!-- The mat-dialog-close directive optionally accepts a value as a result for the dialog. -->
<button mat-button [mat-dialog-close]="true" >save</button>
</mat-dialog-actions>
TS code:
import { Component, OnInit, Inject } from '#angular/core';
import { GroupsService} from '../../../services/Groups.service';
import { Groups } from '../../../models/groupModel'
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
#Component({
selector: 'app-groups',
templateUrl: './groups.component.html',
styleUrls: ['./groups.component.scss'],
})
export class GroupsComponent implements OnInit {
animal: string;
name: string;
groups: Groups[];
constructor(
private groupsService: GroupsService,
public dialog: MatDialog
){}
ngOnInit() {
this.groupsService.getMyGroups()
.then(group =>{
this.groups = group;
console.log(this.groups)
}).catch(error=>{
console.log(error);
});
}
openDialog(): void {
let dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
height: '300px',
width: '300px',
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
console.log(result);
this.animal = result;
});
}
testgroup(id){
console.log(id)
}
acceptGroup(){
console.log('accept')
}
declineGroup(){
console.log('decline');
}
createGroup(){
console.log("sample");
}
}
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: './model.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
#Inject(MAT_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close();
}
}
This part of your code inside HTML template is currently responsible for what you're passing back from the model: [mat-dialog-close]="true". As you see you're just passing true and nothing else. Simplest way to achieve what you want is to create form inside the dialog and pass its value.
<h2 mat-dialog-title>Add Group</h2>
<mat-dialog-content>
<form #modalForm="ngForm">
<div>
<mat-form-field>
<input matInput name="groupName" placeholder="Groupname" ngModel>
</mat-form-field>
<mat-form-field>
<mat-checkbox name="privateGroup" ngModel>Private group?</mat-checkbox>
</mat-form-field>
<mat-form-field>
<button mat-raised-button color="primary">img</button>
</mat-form-field>
</div>
</form>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-dialog-close>cancel</button>
<button mat-button [mat-dialog-close]="modalForm.value">save</button>
</mat-dialog-actions>
You can also pass form value on submit (using (ngSubmit)="mySubmitFunction(modalForm.value)" on form tag ) to the mySubmitFunction defined in DialogOverviewExampleDialog. And then, after some kind of validation for example, pass data by using: this.dialogRef.close(someVariableContainingValues).
use this code i think it will be work:
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
console.log(result);
//this.animal = result;
}).()=>{
this.animal = result;
};
I have been trying to hide my form and making it appear only when user click on the button. but for some reason, the function I have created never work is there something wrong with my code? and I saw quite a few example that uses angular.module and I tried it but I always get an error message.
transfer.component.html
<form [formGroup]="AddRiciverForm" id="AddRiciverForm" (ngSubmit)="addRiciverFunc()" *ngIf="show">
<div class="container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><input type="email" id="emailTo" formControlName="emailTo" placeholder="Reciver Email" [(ngModel)]="this.AddRiciverForm.value.emailTo" required></p>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><button class="btn btn-primary" type="submit" [disabled]="!transferForm.form.valid">Add</button> </p>
</div>
</div>
</div>
</form>
<button ng-click="AddEmailFunc()">add user</button>
transfer.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../auth.service';
import { FormBuilder, FormGroup } from '#angular/forms';
import { Router } from '#angular/router';
import { Http } from '#angular/http';
import { PostsService } from '../posts.service';
#Component({
selector: 'app-transfer',
templateUrl: './transfer.component.html',
styleUrls: ['./transfer.component.css']
})
export class TransferComponent implements OnInit {
constructor(private fb: FormBuilder, private http: Http, private router: Router, private auth: AuthService,private postsService: PostsService) { }
transfer = {};
addRiciver = {};
recivers: any;
AddRiciverForm: FormGroup;
transferForm: FormGroup;
public userEmail: string;
show=false;
ngOnInit() {
this.transferForm = this.fb.group({
emailTo: '',
amount: ''
});
this.AddRiciverForm = this.fb.group({
emailTo: ''
});
this.auth.currentEmail.subscribe(email => this.userEmail = email);
this.postsService.getAllReciver().subscribe(reciver => {
this.recivers = reciver;
});
}
transFunds(){
}
addRiciverFunc(){
this.addRiciver={
emailFrom: this.userEmail,
emailTo: this.AddRiciverForm.value.emailTo
}
this.http.post('/transfer', this.addRiciver)
.subscribe(res => {
let id = res['_id'];
}, (err) => {
console.log(err);
}
);
}
AddEmailFunc(){
if(!this.show){
this.show = true;
}
}
}
You must try adding [hidden]="AddEmailFunc()" on your form.
please see my sample code
import { Component } from '#angular/core';
#Component({
selector: 'Sandbox',
template: `<form [hidden]="isDisplayed">
<label>Sample: </label>
<input type="text">
</form>
<button (click)="showMe()">Click</button>`
})
export class SandboxComponent{
isDisplayed = true;
showMe()
{
if(this.isDisplayed)
{
this.isDisplayed = false;
}else{
this.isDisplayed = true;
}
}
}
Hope it helps. :) cheers!
You are mixing angularjs (1.x) and angular (>2)
the ng-click in Angular should be:
<button (click)="AddEmailFunc()">add user</button>
If this does not solve your issue please post the full component.
you can use *ngIf in and (model) binded to event click of button.
<button (click)="changeView()">add user</button>
and clickEvent
changeView(){
this.showForm = !this.showForm;
}