angularng-bootstrapangular-signals

Setting signal input on a component in ng boostrap modal


In Angular 17.3, I have a component that is using some signal inputs, like

myInput = input(false);

I want to show this component in a modal, using ng-bootstrap. Is it possible to do this, and set the value of myInput? I have tried

private modalService = inject(NgbModal);

const modalRef = this.modalService.open(MyComponent);
modalRef.componentInstance.myInput = true;

as shown in the bootstrap documentation, but this seems to override the field myInput to turn it into a boolean instead of a signal. I tried

modalRef.componentInstance.myInput.set(true);

but it says "modalRef.componentInstance.myInput.set is not a function".

Is this at all possible? or it's just not compatible with signals?


Solution

  • Since input cannot be modified, you should either use a signal or a model, which can be modified.

    If you need the component to accept inputs [someInputSignal]="'test'" and be updatable by ng-bootstrap go for modal ( until input signal setInput is supported), if not use an ordinary signal

    Model inputs - Signals

    We can set the model to accept inputs

    @Component({
      selector: 'ngbd-modal-content',
      standalone: true,
      template: `
            {{someInputSignal()}}
        `,
    })
    export class NgbdModalContent {  
      someInputSignal: ModelSignal<string> = model('');
      ...
    }
    

    Then on the open method use set to set the value of the signal.

        open() {
            const modalRef = this.modalService.open(NgbdModalContent);
            const comp: NgbdModalContent = modalRef.componentInstance;
            comp.someInputSignal.set('it works!');
        }
    

    Full Code:

    import {
      Component,
      inject,
      input,
      ModelSignal,
      InputSignal,
      Input,
      signal,
      model,
    } from '@angular/core';
    import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
    
    @Component({
      selector: 'ngbd-modal-content',
      standalone: true,
      template: `
            {{someInputSignal()}}
        `,
    })
    export class NgbdModalContent {
      activeModal = inject(NgbActiveModal);
    
      someInputSignal: ModelSignal<string> = model('');
      @Input() some: string = '';
    
      ngOnInit() {}
    }
    
    @Component({
      selector: 'ngbd-modal-component',
      standalone: true,
      templateUrl: './modal-component.html',
    })
    export class NgbdModalComponent {
      private modalService = inject(NgbModal);
    
            open() {
                const modalRef = this.modalService.open(NgbdModalContent);
                const comp: NgbdModalContent = modalRef.componentInstance;
                comp.someInputSignal.set('it works!');
            }
    }
    

    Stackblitz Demo