1

I have some a component structured like this:

detail-component.ts

<app-base-modal>
 <app-body></app-body>
</app-base-modal>

On my base modal component.ts I have this:

base-modal.component.ts

@Component({
  selector: 'app-base-modal',
  template: `
    <div class="modal fade" bsModal #staticModal="bs-modal" [config]="{backdrop: 'static'}" tabindex="-1" role="dialog" aria-labelledby="dialog-static-name">
            <button type="button" class="close pull-right" aria-label="Close" (click)="staticModal.hide()">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <ng-content></ng-content>
          </div>
    </div>
  `
})
export class BaseModalComponent implements OnInit {

  @ViewChild('staticModal', { static: true })
  staticModal: ModalDirective;

  @Input()
  toShowModal: BehaviorSubject<boolean> = new BehaviorSubject(false);

  modalIsHidden = false;

  constructor(private modalService: BsModalService) { }

  ngOnInit() {
    this.toShowModal.subscribe(t => {
      if (t) {
        this.staticModal.show();
      }
    });

    this.staticModal.onHidden.subscribe(() => {
      this.modalIsHidden = true;
    })
  }

  closeModal() {
    this.staticModal.hide();
  }

}

I need to pass the closeModal method or modalIsHidden to ng-content so I can do a cleanup on the projected/child html.

The modal body component or child looks like this:

body.component.ts

@Component({
  selector: 'app-body',
  template: `

  <section *ngIf="hasRespondedWithError || isReasonSubmitSuccessful">
    <p class="alert alert-danger" *ngIf="hasRespondedWithError">Something went wrong. Please try again later.</p>
    <p class="alert alert-success" *ngIf="isReasonSubmitSuccessful">Thank you! Please allow us to review your return and we will contact you soon</p>
  </section>

  <form (ngSubmit)="onSubmit()" [formGroup]="sForm">
    <div class="form-group">
      <textarea type="text" formControlName="reasonTextArea" name="reasonTextArea" placeholder="Return Reason" class="form-control"></textarea>
    </div>
    <div class="d-flex flex-row justify-content-end">
      <button type="submit" class="btn btn-primary ml-2">Submit</button>
    </div>
  </form>
`
})
export class BodyComponent {

  @Output()
  returnValueOrder = new EventEmitter<Order>();



  toShowLoading = false;
  hasRespondedWithError = false;
  isReasonSubmitSuccessful = false;

  constructor(private fooService: FooService) { }


  sForm = new FormGroup({
    reasonTextArea: new FormControl('', Validators.required)
  });




  onSubmit(): void {
    this.toShowLoading = true;
    this.fooService
      .createRequest(this.orderNumber, {
        order_id: this.orderId,
        reason: this.sForm.value.reasonTextArea
      })
      .subscribe((order: Order) => {
        this.returnValueOrder.emit(order);
      }, (err) => {
        this.toShowLoading = false;
        this.hasRespondedWithError = true;
      }, () => {
        this.toShowLoading = false;
        this.isReasonSubmitSuccessful = true;
      });
  }

}

So right here I need to check/listen if the modal is closed so can set the isReasonSubmitSuccessful, and hasRespondedWithError to false.


I have read this but it's so confusing. Confusing because templateRef needs to be in the same file so I can reference it like <template #temp></template> using the pound sign?

halfer
  • 19,824
  • 17
  • 99
  • 186
aRtoo
  • 1,686
  • 2
  • 18
  • 38

1 Answers1

0

One of possible solutions might be using dependency injection mechanism:

First determine what you want to pass:

export abstract class ModalContext {
  abstract closeModal();
}

Then decouple your parent component from DI:

base-modal.component.ts

@Component({
  selector: "app-base-modal",
  template: `...`,
  providers: [
    {
      provide: ModalContext,
      useExisting: BaseModalComponent
    }
  ]
})
export class BaseModalComponent implements ModalContext, OnInit {
  ...
  closeModal() {
    ...
  }
}

Finally, you can use this ModalContext in your projected component:

body.component.ts

@Component({...})
export class BodyComponent {
  ...
  
  constructor(... private modalContext: ModalContext) { }

  closeModal() {
    this.modalContext.closeModal();
  }
}

Forked Stackblitz

yurzui
  • 205,937
  • 32
  • 433
  • 399