تایپاسکریپت - چگونه یک پنجره بازشو (مدال) ایجاد کنیم که با انگولار ۴ سازگار باشد
من میخواهم بتوانم یک پنجره پاپآپ ایجاد کنم که هنگام انتخاب یک دکمه رادیویی، یک کامپوننت مشخص از Angular 4 من را بارگذاری کند.
به نظر میرسد که روشهای ذکر شده در پاسخهای این سؤال تنها با انگولار ۲ سازگار هستند.
من مطمئن نیستم از کجا شروع کنم و از هر کمکی قدردانی میکنم!
پاسخ شماره ۱
پاسخ پذیرفته شده یک وابستگی بزرگ برای زدن یک مگس اضافه میکند. دیالوگهای مدال (و غیرمدال) عمدتاً نتیجه یک یا دو کلاس CSS هستند. این مثال «تغییر نام...» را امتحان کنید:
1) والد و کودک-مودال را طوری بنویسید که گویی کودک اصلاً مودال نیست، بلکه فقط یک فرم داخل خطی با *ngIf متصل است.
HTML والد که از فرزند <my-modal> استفاده میکند:
<div>
A div for {{name}}.
<button type="button" (click)="showModal()">Rename</button>
<my-modal *ngIf="showIt" [oldname]="name" (close)="closeModal($event)"></my-modal>
</div>
کلاس والد. دکوریتور @Component برای اختصار حذف شده است. (ویژگی name مربوط به کلاس والد است و حتی اگر فرمی برای تغییر آن نداشته باشیم، وجود خواهد داشت.)
export class AppComponent {
name = "old name";
showIt = false;
showModal() {
this.showIt = true;
}
closeModal(newName: string) {
this.showIt = false;
if (newName) this.name = newName;
}
}
کامپوننت فرزند که قرار است مدال باشد. @Component دکوریتور و واردات دوباره حذف شدند.
export class MyModalComponent {
@Input() oldname = "";
@Output() close = new EventEmitter<string>();
newname = "";
ngOnInit() {
// copy all inputs to avoid polluting them
this.newname = this.oldname;
}
ok() {
this.close.emit(this.newname);
}
cancel() {
this.close.emit(null);
}
}
HTML فرزند قبل از مدالسازی آن.
<div>
Rename {{oldname}}
<input type="text" (change)="newname = $event.target.value;" />
<button type="button" (click)="ok()">OK</button>
<button type="button" (click)="cancel()">Cancel</button>
</div>
۲) این CSS برای child است، اما میتوان آن را در یک stylesheet جهانی قرار داد تا در سراسر برنامه شما دوباره استفاده شود. این یک کلاس واحد به نام modal است و برای عنصر <div> طراحی شده است.
.modal {
/* detach from rest of the document */
position: fixed;
/* center */
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* ensure in front of rest of page -- increase as needed */
z-index: 1001;
/* visual illusion of being in front -- alter to taste */
box-shadow: rgba(0,0,0,0.4) 10px 10px 4px;
/* visual illusion of being a solid object -- alter to taste */
background-color: lightblue;
border: 5px solid darkblue;
/* visual preference of don't crowd the contents -- alter to taste */
padding: 10px;
}
اما کلاس CSS modal از تعامل با صفحه زیر آن جلوگیری نمیکند. (بنابراین از نظر فنی یک دیالوگ بدون مدل ایجاد میکند.) بنابراین ما یک overlay زیر مودال قرار میدهیم تا فعالیت ماوس را جذب و نادیده بگیرد. overlay نیز برای عنصر <div> در نظر گرفته شده است.
.overlay {
/* detach from document */
position: fixed;
/* ensure in front of rest of page except modal */
z-index: 1000;
/* fill screen to catch mice */
top: 0;
left: 0;
width: 9999px;
height: 9999px;
/* dim screen 20% -- alter to taste */
opacity: 0.2;
background-color: black;
}
۳) از modal و overlay در HTML فرزند استفاده کنید.
<div class="modal">
Rename {{oldname}}
<input type="text" (change)="newname = $event.target.value;" />
<button type="button" (click)="ok()">OK</button>
<button type="button" (click)="cancel()">Cancel</button>
</div>
<div class="overlay"></div>
و همین است. اساساً دو کلاس CSS و شما میتوانید هر کامپوننتی را به یک مدال تبدیل کنید. در واقع شما میتوانید یک کامپوننت را به صورت درون خطی یا به صورت مدال در زمان اجرا فقط با تغییر وجود کلاس CSS با ngClass یا [class.modal]="showAsModalBoolean" نمایش دهید.
شما می توانید این را تغییر دهید تا کودک منطق نمایش/پنهان کردن را کنترل کند. *ngIf، showIt و تابع show() را به فرزند ارسال کنید. در والد، @ViewChild(MyModalComponent) renameModal: MyModalComponent; را اضافه کنید و سپس والد میcتواند این this.renameModal.show(this.name); را اجباری فراخوانی کند و در صورت نیاز، دیویcهای حاوی را مجدداً مقداردهی کرده و مجدداً وصل کند.
مودال فرزند میتواند اطلاعات را همانطور که در بالا نشان داده شد به تابع والد بازگرداند، یا متد show() فرزند میتواند در عوض یک callback بپذیرد یا یک Promise بازگرداند، بسته به سلیقه.
دو چیز که باید بدانید:
this.renameModal.show(..); کار نخواهد کرد اگر روی <my-modal> از *ngIf استفاده شده باشد، چون در ابتدا وجود نخواهد داشت تا تابع را در دسترس قرار دهد. *ngIf کل کامپوننت را حذف میکند، شامل تابع show() و همه چیز، بنابراین اگر به هر دلیلی به این نیاز دارید، به جای آن از [hidden] استفاده کنید.
مدالها روی مدالها مشکلات z-index خواهند داشت زیرا همه آنها همان z-index را به اشتراک میگذارند. این مشکل را میتوان با [style.z-index]="calculatedValue" یا مشابه آن حل کرد.
پاسخ شماره ۲
گفتوگوی Angular Material را بررسی کنید، اینجا Plunker است
import {Component} from '@angular/core';
import {MdDialog, MdDialogRef} from '@angular/material';
@Component({
selector: 'dialog-result-example',
templateUrl: './dialog-result-example.html',
})
export class DialogResultExample {
selectedOption: string;
constructor(public dialog: MdDialog) {}
openDialog() {
let dialogRef = this.dialog.open(DialogResultExampleDialog);
dialogRef.afterClosed().subscribe(result => {
this.selectedOption = result;
});
}
}
@Component({
selector: 'dialog-result-example-dialog',
templateUrl: './dialog-result-example-dialog.html',
})
export class DialogResultExampleDialog {
constructor(public dialogRef: MdDialogRef<DialogResultExampleDialog>) {}
}
