我使用了一种通用方法,在添加食品时,将打开一个带有表单的模式,让用户添加他的详细信息。但是,为了检查后端是否有重复项目,我只能在 API 调用完成后检索它。
问题是,如果出现错误,我不希望模式关闭,因为用户必须再次填写所有详细信息。
这是我的代码。我已经使用了第三方库来实现模态和吐司。
food.component.ts:
addFood(data: any){
this.api.request('foodItem', 'POST', data).subscribe({
next: (response: any) => {
if (response.message == 'Added Successfully.') {
this._toastService.showSuccess('Food added.');
} else {
this._toastService.showError(response.message);
}
},
complete: () => this.getFood(),
error: (error: any) => this._toastService.showError(error.message)
});
}
食物组件.html
<app-custom-table [tableData]="tableData" [form]="formData" [columnArray]="columnArray" (onAdd)="addFood($event)" (onEdit)="editFood($event)"></app-custom-
table>
自定义 - table.component.html
<button type = "button" class="btn btn-link"(click) = "openModal()"[disabled] = "isRowSelected"><span>Add</span></button>
<button type="button" class="btn btn-link"(click) = "openModal(selectedRow)"[disabled] = "isRowNotSelected"></i><span>Edit</span></button>
自定义-table.component.ts:
openModal(rowData: any = null) {
const config: Partial<DynamicFormComponent> = {
form: this.form,
data: rowData
};
const options: NgbModalOptions = { size: 'sm', centered: true };
const modalRef = this.ModalService.show((DynamicFormComponent), config, options).
modalRef.componentInstance.submitSubject.subscribe((result: any) => { //here getting error Property CoponentInstance does not exist in type Observable<ModalResult<unknown>>
if (result.Success == true && result.Data) {
if (rowData) {
const updatedRowData = { ...rowData, ...result.Data };
// If rowData is provided, it's an edit operation
this.onEdit.emit(updatedRowData);
} else { //add
this.onAdd.emit(result.Data);
}
}
});
}
动态表单.html
@Output() submitSub: Subject<any> = new Subject<any>();
constructor(
private activeModal: NgbActiveModal
){
}
onSubmit(){
if(this.dynamicFormGroup.valid){
this.submitSubject.next(this.dynamicFormGroup.value)
this.activeModal.close(this.dynamicFodmGroup.value) --not sure here
}
}
如何解决这个问题?
您可以根据自己的情况取消
hide.bs.modal
活动
$("#exampleModal").on("hide.bs.modal", function(event) {
if (!document.querySelector("#defaultCheck1").checked) {
event.preventDefault();
}
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="defaultCheck1">
<label class="form-check-label" for="defaultCheck1">
Allow Closing
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
不使用“关闭”。在模态组件中添加主题,并在打开时订阅。是打开弹窗的组件还是关闭弹窗的组件
//in your component in a popup
@Input() form: FormGroup;
submit:Subject<any>=new Subject<any>()
//in .html
<div class="modal-header">
<h4 class="modal-title">Hi there!</h4>
<button type="button" class="btn-close" aria-label="Close"
(click)="activeModal.dismiss()"
></button>
</div>
<div class="modal-body">
<p>Hello, {{ name }}!</p>
<!--A typical form-->
<div [formGroup]="form">
<input formControlName="name" />
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-outline-dark"
<!--see that only emit one value to the "submit" subject -->
(click)="submit.next(form.value)"
>
Close
</button>
</div>
然后,打开时
open() {
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = 'World';
modalRef.componentInstance.form = this.form;
modalRef.componentInstance.submit
.pipe(takeUntil(modalRef.closed))
.subscribe((data: any) => {
//I use a simple service that return "true" or "false"
this.dataService.checkData(data.name).subscribe((res: any) => {
if (res) modalRef.close(); //<--this close the popUp
});
});
}
A stackblitz(只有在“名称”中写下“Angular”时才会关闭)
注意:您可以改进指示“表单”无效的原因,或者您可以使用自定义异步验证器。
更新简要说明
在 ngb-popup 中,我们可以在自己的函数“show”中订阅:
this.ModalService.show((DynamicFormComponent), config, options).subscribe(...)
或者使用变量并订阅后
//get a reference of the "popup"
const modalRef = this.ModalService.show((DynamicFormComponent), config, options)
//Subcribe to it
modalRef.subscribe(...)
我们需要采取第二种方法。
如果在我们的“DynamicFormComponent”中我们定义了“任何公共变量”,我们就可以访问它。这就是我们可以将变量添加到 DynamicFormComponent 的原因
submitSubject:Subject<any>=new Subject<any>()
现在,我们可以“订阅这个主题”了,所以
//really we use takeWhile to unsubscribe when the modal is closed
modalRef.componentInstance.submitSubject.subscribe((data: any) => {}
在我们的 DynamicFormComponent 中我们不使用“close”。我们不使用 close,而是向主题“发出”一个值
// instead of use in .html
(click)="activeModal.close(value)"
//we use
(click)="submitSubject.next(value)"
现在,我们在关闭时订阅的所有代码都用于主题的订阅。请记住,如果一切正常,我们需要手动(通过代码)关闭弹出窗口,使用
modalRef.close();