How to push back an object from ng-bootstrap modal to main component in Angular?

时间:2018-03-25 18:56:03

标签: angular ng-bootstrap

Struggling to transfer an object from ng-bootstrap modal to main(view) component using the @Output decorator. This is my HTML(viewProducts.component.html), where a list of products are shown, when I click on one of them, the modal is invoked:

<tr *ngFor="let product of products>
    <td class="text-center">
        <button class="btn btn-default" name="openPopUp" 
          (click)="openPopUpEdit(product)" 
          (callBackPopUp)="callBackPopUp($event)">
          <i class="fa fa-edit" style="font-size: 20px"></i>
        </button>
    </td>
</tr>

viewProducts.component.ts

 openPopUpEdit(product) {
   this.editProductModalService.open(EditProductComponent as Component, 
    product);
}

editProduct-modal.service.ts

@Injectable()
export class EditProductModalService {
    private ngbModalRef: NgbModalRef;
    constructor(
        private modalService: NgbModal
    ) {
        this.ngbModalRef = null;
    }

    open(component: Component,  product: ProductModel): Promise<NgbModalRef> {
        return new Promise<NgbModalRef>((resolve, reject) => {
            const isOpen = this.ngbModalRef !== null;
            if (isOpen) {
                resolve(this.ngbModalRef);
            }
            setTimeout(() => {
                this.ngbModalRef = this.manageModalRef(component, product);
                resolve(this.ngbModalRef);
            }, 0);
        });
    }

    manageModalRef(component: Component, product: ProductModel): NgbModalRef {
        const modalRef = this.modalService.open(component, { size: 'lg', backdrop: 'static' });
        (<EditProductComponent> modalRef.componentInstance).product = product;
        modalRef.componentInstance.callBackPopUp.subscribe(($e) => {
            console.log('call back:' + $e);
        })
        modalRef.result.then((result) => {
            this.ngbModalRef = null;
        }, (reason) => {
            console.log('dismiss reason: ' + reason);
            this.ngbModalRef = null;
        });
        return modalRef;
    }
}

And finally, the HTML modal form where I edit the product data(editProduct.component.html). When I click on the save button into editProduct.component.ts (work with a copy of the product - to avoid the two-way data binding) and try to push back modified product data into the viewProducts.component.html :

@Component({
    selector: 'editProduct',
    templateUrl: './editProduct.component.html'
})
export class EditProductComponent implements OnInit, OnDestroy {
    @Input() product: ProductModel;
    @Output() callBackPopUp: EventEmitter<ProductModel> = new 
    EventEmitter<ProductModel>();
    productCopy: ProductModel;   

    constructor(
        private activeModal: NgbActiveModal,       
        private service: ProductService,
     ) { }

    ngOnInit() {
        this.productCopy = Object.assign({}, this.product);       
    }

    save() {  
        this.service.updateProduct(this.productCopy).subscribe((res) => {
            this.callBackPopUp.emit(this.productCopy);                    
        }   
    }
}

I do not know how to push back modified data into editProduct.component.html. Any suggestions?

1 个答案:

答案 0 :(得分:1)

You have to use a service. Here is an example:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';


@Injectable()
export class StorageService {

    private product: BehaviorSubject<ProductModel> = new BehaviorSubject('');

    constructor() { }

    getProduct(): Observable<ProductModel> {
        return this.product.asObservable();
    }

    getProductValue(): ProductModel {
        return this.product.getValue();
    }

    setProduct(val: ProductModel) {
        this.product.next(val);
    }
}

In your ViewProductsComponent subscribe to this StorageService and have your local variable that provides updated product exchanged whenever the value inside the service changes.

import {StorageService} from 'storage.service.ts';

constructor(
 private storageService: StorageService
){}

ngOnInit(): void {
    // Update with every change
    this.storageService.getProduct().subscribe(product => {
        this.modifiedProduct = product; 
    });
}

And your Modal has to set the value to the StorageSevice instead of emitting it

import {StorageService} from 'storage.service.ts';

constructor(
 private storageService: StorageService
){}

save() {  
    this.service.updateProduct(this.productCopy).subscribe((res) => {
        this.storageService.setProduct(res);                    
    }   
}