So, in case anyone is interested this is how I implemented aforementioned behavior. It might not be the right way to do it, so if you have any critics/suggestions/tips leave them down below, please.
In general, if a user clicks on existing item, I pass this Item to child component, otherwise I pass null. In child component I assume that if null was passed, its a 'create' mode, otherwise it is 'update' mode.
Change/add/close/delete are @Output EventEmitter. Is it a good way to do implement it or not?
Hope it'll be helpful to someone one day.
Parent component with a list of items: dashboard.component.html
<div class="grid grid-pad">
<a *ngFor="let e of items" class="col-1-4" (click)="openModal(newItem,e)">
<div class="module items">
<h4>{{e.name}}</h4>
</div>
</a>
</div>
<button type="button" class="btn btn-primary" (click)="openModal(newItem)">Add new item</button>
<ng-template #newItem>
<app-create-or-update-item
[item]="item"
(itemChange)="item($event)"
(itemAdd)="addItem($event)"
(close)="closeModal()"
(delete)="deleteItem($event)"
>
</app-create-or-update-item>
dashboard.component.ts
export class DashboardComponent implements OnInit {
@ViewChild(CreateOrUpdateItemComponent, { static: false }) itemModal: CreateOrUpdateItemComponent;
items: Item[] = [];
newItemModal: BsModalRef;
item: Item;
constructor(private itemService: ItemService,
private modalService: BsModalService) { }
ngOnInit() {
this.getItems();
}
getItems(): void {
this.itemService.getItems()
.subscribe(res => {
this.items = res.slice(0, 50);
});
}
openModal(template: TemplateRef<any>, item: Item) {
this.item = item;
this.newItemModal = this.modalService.show(template, { backdrop: true, keyboard: true });
}
closeModal() {
this.modalService.hide(1);
}
change(value): void {
this.closeModal();
}
addItem(value: Item) {
this.items.push(value);
this.closeModal();
}
deleteItem(value: Item) {
this.itemService.deleteItem(value.id).subscribe();
this.closeModal();
}
}
And for the child component: create-or-update-item.component.html
<div id="modal-content-wrapper">
<div class="modal-header">
<h4 class="modal-title pull-left">Add new item</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="closeModal()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<label for="itemName">Item</label>
<input type="text" class="form-control" id="itemName" [(ngModel)]="item.name">
</div>
<div class="modal-footer">
<div *ngIf="createMode; then saveBlock else updateBlock"></div>
</div>
</div>
<ng-template #saveBlock>
<button type="button" class="btn btn-secondary" (click)="save()">Save</button>
</ng-template>
<ng-template #updateBlock>
<button type="button" class="btn btn-danger" (click)="confirmDelete(confirmDeletionModal)">Delete</button>
<button type="button" class="btn btn-secondary" (click)="save()">Update</button>
</ng-template>
<ng-template #confirmDeletionModal>
<div class="modal-header">
<h4 class="modal-title pull-left">Are you sure about this?</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="closeModal()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Do you really want to delete this item?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger" (click)="deleteItem()">Delete</button>
</div>
</ng-template>
create-or-update-item.component.ts:
export class CreateOrUpdateItemComponent implements OnInit {
@Input() item: Item;
@Output() itemChange:EventEmitter<Item> = new EventEmitter<Item>();
@Output() itemAdd:EventEmitter<Item> = new EventEmitter<Item>();
@Output() close:EventEmitter<any> = new EventEmitter<any>();
@Output() delete:EventEmitter<any> = new EventEmitter<any>();
createMode: boolean;
deleteConfirmationModal: BsModalRef;
constructor(private modalService: BsModalService,
private itemService: ItemService) { }
ngOnInit() {
if (this.item==null) {
this.createMode=true;
this.item=new Item();
}
else {
this.createMode=false;
}
}
save(): void {
if (this.createMode) {
this.itemService.createItem(this.item).subscribe();
var addedItem=this.item;
this.itemAdd.emit(addedItem);
}
else {
this.itemService.updateItem(this.item).subscribe();
var updatedItem=this.item;
this.itemChange.emit(updatedItem);
}
}
closeModal(): void {
this.close.emit();
}
confirmDelete(template: TemplateRef<any>):void {
this.deleteConfirmationModal = this.modalService.show(template, { backdrop: true, keyboard: true });
}
deleteItem():void {
this.delete.emit(this.item);
this.modalService.hide(1);
}
}