Solution: Observing Bootstrap Events with Angular4 / Bootstrap4.
Summary: Intercept the bootstrap events, and fire off a custom event in its place. The custom event will be observable from within angular components.
Index.html:
<body>
...
<script>
function eventRelay(bs_event){
$('body').on(bs_event, function($event){
const customEvent = document.createEvent('Event');
customEvent.initEvent(bs_event, true, true);
let target_id = '#'+$event.target.id;
$(target_id)[0].dispatchEvent(customEvent);
});
</script>
</body>
In your Component/Service:
//dynamically execute the event relays
private registerEvent(event){
var script = document.createElement('script');
script.innerHTML = "eventRelay('"+event+"');"
document.body.appendChild(script);
}
In your Component's Constructor or ngOnInit(), you can now register and observe the bootstrap events. Eg, Bootstrap Modal 'hidden' event.
constructor(){
registerEvent('hidden.bs.modal');
Observable.fromEvent(document, 'hidden.bs.modal')
.subscribe(($event) => {
console.log('my component observed hidden.bs.modal');
//...insert your code here...
});
}
Note: the 'eventRelay' function must be inside index.html so that the DOM loads it. Otherwise it will not be recognized when you issue the calls to 'eventRelay' from within 'registerEvent'.
Conclusion: This is a middle-ware workaround solution that works with vanilla Angular4/Bootstrap4. I don't know why bootstrap events are not visible within angular, and I have not found any other solution around this.
Note1: Only call registerEvent once for each event. That means 'once' in the entire app, so consider putting all registerEvent calls in app.component.ts. Calling registerEvent multiple times will result in duplicate events being emitted to angular.
Note2: There is an alternative bootstrap framework you can use with angular called ngx-bootstrap (https://valor-software.com/ngx-bootstrap/#/) which might make the bootstrap events visible, however I have not tested this.
Advanced Solution: Create an Angular Service that manages the events registered through 'registerEvent', so it only only call 'registerEvent' once for each event. This way, in your components you can call 'registerEvent' and then immediately create the Observable to that event, without having to worry about duplicate calls to 'registerEvent' in other components.