Skip to content

Commit

Permalink
feat(alert): change API due to the introduction of animations
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

Alert closing API has changed due to the introduction of the imperative `.close()` method to trigger the 'fade out' animation

Before:

```
<ngb-alert (close)="..."></ngb-alert>
```

After:

```
// template
<ngb-alert (closed)="..."></ngb-alert>

// component
alert.close();
```

The `closed` event is emitted after the 'fade out' animation is finished.
The 'fade out' animation can be triggered either by clicking on the alert's 'cross button' or calling `.close()` method.
  • Loading branch information
maxokorokov committed May 12, 2020
1 parent 22ddad7 commit 95f75cc
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p *ngFor="let alert of alerts">
<ngb-alert [type]="alert.type" (close)="close(alert)">{{ alert.message }}</ngb-alert>
<ngb-alert [type]="alert.type" (closed)="close(alert)">{{ alert.message }}</ngb-alert>
</p>
<p>
<button type="button" class="btn btn-primary" (click)="reset()">Reset</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<p>
Static self-closing alert that disappears after 20 seconds (refresh the page if it has already disappeared)
</p>
<ngb-alert #staticAlert *ngIf="!staticAlertClosed" (close)="staticAlertClosed = true">Check out our awesome new
<ngb-alert #staticAlert *ngIf="!staticAlertClosed" (closed)="staticAlertClosed = true">Check out our awesome new
features!</ngb-alert>

<hr />

<p>
Show a self-closing success message that disappears after 5 seconds.
</p>
<ngb-alert #selfClosingAlert *ngIf="successMessage" type="success" (close)="successMessage = ''">{{ successMessage }}
<ngb-alert #selfClosingAlert *ngIf="successMessage" type="success" (closed)="successMessage = ''">{{ successMessage }}
</ngb-alert>
<p>
<button class="btn btn-primary" (click)="changeSuccessMessage()">Change message</button>
</p>
</p>
21 changes: 20 additions & 1 deletion src/alert/alert.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import createSpy = jasmine.createSpy;
import {async, ComponentFixture, inject, TestBed} from '@angular/core/testing';
import {isBrowserVisible, createGenericTestComponent} from '../test/common';
import {By} from '@angular/platform-browser';

import {Component} from '@angular/core';

Expand Down Expand Up @@ -101,7 +103,7 @@ describe('ngb-alert', () => {

it('should fire an event after closing a dismissible alert', () => {
const fixture =
createTestComponent('<ngb-alert [dismissible]="true" (close)="closed = true">Watch out!</ngb-alert>');
createTestComponent('<ngb-alert [dismissible]="true" (closed)="closed = true">Watch out!</ngb-alert>');
const alertEl = getAlertElement(fixture.nativeElement);
const buttonEl = getCloseButton(alertEl);

Expand All @@ -112,6 +114,23 @@ describe('ngb-alert', () => {
expect(fixture.componentInstance.closed).toBe(true);
});

it('should fire an event after closing a dismissible alert imperatively', () => {
const fixture =
createTestComponent('<ngb-alert [dismissible]="true" (closed)="closed = true">Watch out!</ngb-alert>');
const alertEl = getAlertElement(fixture.nativeElement);
const alert = fixture.debugElement.query(By.directive(NgbAlert)).injector.get(NgbAlert);

const closedSpy = createSpy();
expect(fixture.componentInstance.closed).toBe(false);
alert.close().subscribe(closedSpy);
fixture.detectChanges();

expect(fixture.componentInstance.closed).toBe(true);
expect(closedSpy).toHaveBeenCalledTimes(1);
expect(alertEl).toHaveCssClass('show');
expect(alertEl).toHaveCssClass('fade');
});

it('should project the content given into the component', () => {
const fixture = createTestComponent('<ngb-alert>Cool!</ngb-alert>');
const alertEl = getAlertElement(fixture.nativeElement);
Expand Down
24 changes: 18 additions & 6 deletions src/alert/alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
ViewEncapsulation
} from '@angular/core';

import {Observable} from 'rxjs';

import {NgbAlertConfig} from './alert-config';
import {ngbRunTransition} from '../util/transition/ngbTransition';
import {ngbAlertFadingTransition} from '../util/transition/ngbFadingTransition';
Expand All @@ -23,6 +25,7 @@ import {ngbAlertFadingTransition} from '../util/transition/ngbFadingTransition';
*/
@Component({
selector: 'ngb-alert',
exportAs: 'ngbAlert',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: {'role': 'alert', 'class': 'alert show fade', '[class.alert-dismissible]': 'dismissible'},
Expand Down Expand Up @@ -64,7 +67,7 @@ export class NgbAlert implements OnInit,
/**
* An event emitted when the close button is clicked. It has no payload and only relevant for dismissible alerts.
*/
@Output('close') closeEvent = new EventEmitter<void>();
@Output() closed = new EventEmitter<void>();


constructor(config: NgbAlertConfig, private _renderer: Renderer2, private _element: ElementRef) {
Expand All @@ -73,11 +76,20 @@ export class NgbAlert implements OnInit,
this.animation = config.animation;
}

close() {
ngbRunTransition(this._element.nativeElement, ngbAlertFadingTransition, {
animation: this.animation,
runningTransition: 'continue'
}).subscribe(() => this.closeEvent.emit());
/**
* Triggers alert closing programmatically (same as clicking on the close button (×)).
*
* The returned observable will emit and be completed once the closing transition has finished.
* If the animations are turned off this happens synchronously.
*
* Alternatively you could listen or subscribe to the `(closed)` output
*/
close(): Observable<void> {
const transition = ngbRunTransition(
this._element.nativeElement, ngbAlertFadingTransition,
{animation: this.animation, runningTransition: 'continue'});
transition.subscribe(() => this.closed.emit());
return transition;
}

ngOnChanges(changes: SimpleChanges) {
Expand Down

0 comments on commit 95f75cc

Please sign in to comment.