File

src/app/app.component.ts

Metadata

selector app-root
styleUrls ./app.component.scss
templateUrl ./app.component.html

Index

Properties
Methods

Constructor

constructor(snotifyService: SnotifyService)
Parameters :
Name Type Optional
snotifyService SnotifyService No

Methods

getConfig
getConfig()
Returns : SnotifyToastConfig
onAsyncLoading
onAsyncLoading()
Returns : void
onClear
onClear()
Returns : void
onConfirmation
onConfirmation()
Returns : void
onError
onError()
Returns : void
onHtml
onHtml()
Returns : void
onInfo
onInfo()
Returns : void
onPrompt
onPrompt()
Returns : void
onSimple
onSimple()
Returns : void
onSuccess
onSuccess()
Returns : void
onWarning
onWarning()
Returns : void

Properties

backdrop
Default value : -1
blockMax
Type : number
Default value : 6
body
Type : string
Default value : 'Lorem ipsum dolor sit amet!'
bodyMaxLength
Type : number
Default value : 80
closeClick
Default value : true
dockMax
Type : number
Default value : 8
filterDuplicates
Default value : false
newTop
Default value : true
pauseHover
Default value : true
position
Type : SnotifyPosition
Default value : SnotifyPosition.rightBottom
progressBar
Default value : true
style
Type : string
Default value : 'material'
timeout
Type : number
Default value : 3000
title
Type : string
Default value : 'Snotify title!'
titleMaxLength
Type : number
Default value : 15
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { SnotifyService, SnotifyPosition, SnotifyToastConfig } from 'ng-snotify';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  style = 'material';
  title = 'Snotify title!';
  body = 'Lorem ipsum dolor sit amet!';
  timeout = 3000;
  position: SnotifyPosition = SnotifyPosition.rightBottom;
  progressBar = true;
  closeClick = true;
  newTop = true;
  filterDuplicates = false;
  backdrop = -1;
  dockMax = 8;
  blockMax = 6;
  pauseHover = true;
  titleMaxLength = 15;
  bodyMaxLength = 80;

  constructor(private snotifyService: SnotifyService) {}

  /*
  Change global configuration
   */
  getConfig(): SnotifyToastConfig {
    this.snotifyService.setDefaults({
      global: {
        newOnTop: this.newTop,
        maxAtPosition: this.blockMax,
        maxOnScreen: this.dockMax,
        // @ts-ignore
        filterDuplicates: this.filterDuplicates
      }
    });
    return {
      bodyMaxLength: this.bodyMaxLength,
      titleMaxLength: this.titleMaxLength,
      backdrop: this.backdrop,
      position: this.position,
      timeout: this.timeout,
      showProgressBar: this.progressBar,
      closeOnClick: this.closeClick,
      pauseOnHover: this.pauseHover
    };
  }

  onSuccess() {
    this.snotifyService.success(this.body, this.title, this.getConfig());
  }
  onInfo() {
    this.snotifyService.info(this.body, this.title, this.getConfig());
  }
  onError() {
    this.snotifyService.error(this.body, this.title, this.getConfig());
  }
  onWarning() {
    this.snotifyService.warning(this.body, this.title, this.getConfig());
  }
  onSimple() {
    // const icon = `assets/custom-svg.svg`;
    const icon = `https://placehold.it/48x100`;

    this.snotifyService.simple(this.body, this.title, {
      ...this.getConfig(),
      icon
    });
  }

  onAsyncLoading() {
    const errorAction = new Observable(observer => {
      setTimeout(() => {
        observer.error({
          title: 'Error',
          body: 'Example. Error 404. Service not found'
        });
      }, 2000);
    });

    const successAction = new Observable(observer => {
      setTimeout(() => {
        observer.next({
          body: 'Still loading.....'
        });
      }, 2000);

      setTimeout(() => {
        observer.next({
          title: 'Success',
          body: 'Example. Data loaded!',
          config: {
            closeOnClick: true,
            timeout: 5000,
            showProgressBar: true
          }
        });
        observer.complete();
      }, 5000);
    });

    /*
      You should pass Promise or Observable of type Snotify to change some data or do some other actions
      More information how to work with observables:
      https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/create.md
     */
    const { timeout, ...config } = this.getConfig(); // Omit timeout
    this.snotifyService.async('This will resolve with error', 'Async', errorAction, config);
    this.snotifyService.async('This will resolve with success', successAction, config);
    this.snotifyService.async(
      'Called with promise',
      'Error async',
      new Promise((resolve, reject) => {
        setTimeout(
          () =>
            reject({
              title: 'Error!!!',
              body: 'We got an example error!',
              config: {
                closeOnClick: true
              }
            }),
          1000
        );
        setTimeout(() => resolve(), 1500);
      }),
      config
    );
  }

  onConfirmation() {
    /*
    Here we pass an buttons array, which contains of 2 element of type SnotifyButton
     */
    const { timeout, closeOnClick, ...config } = this.getConfig(); // Omit props what i don't need
    this.snotifyService.confirm(this.body, this.title, {
      ...config,
      buttons: [
        { text: 'Yes', action: () => console.log('Clicked: Yes'), bold: false },
        { text: 'No', action: () => console.log('Clicked: No') },
        {
          text: 'Later',
          action: toast => {
            console.log('Clicked: Later');
            this.snotifyService.remove(toast.id);
          }
        },
        {
          text: 'Close',
          action: toast => {
            console.log('Clicked: Close');
            this.snotifyService.remove(toast.id);
          },
          bold: true
        }
      ]
    });
  }

  onPrompt() {
    /*
     Here we pass an buttons array, which contains of 2 element of type SnotifyButton
     At the action of the first buttons we can get what user entered into input field.
     At the second we can't get it. But we can remove this toast
     */
    const { timeout, closeOnClick, ...config } = this.getConfig(); // Omit props what i don't need
    this.snotifyService
      .prompt(this.body, this.title, {
        ...config,
        buttons: [
          {
            text: 'Yes',
            action: toast => console.log('Said Yes: ' + toast.value)
          },
          {
            text: 'No',
            action: toast => {
              console.log('Said No: ' + toast.value);
              this.snotifyService.remove(toast.id);
            }
          }
        ],
        placeholder: 'Enter "ng-snotify" to validate this input' // Max-length = 40
      })
      .on('input', toast => {
        console.log(toast.value);
        toast.valid = !!toast.value.match('ng-snotify');
      });
  }

  onHtml() {
    const html = `<div class="snotifyToast__title"><b>Html Bold Title</b></div>
    <div class="snotifyToast__body"><i>Html</i> <b>toast</b> <u>content</u></div>`;
    this.snotifyService.html(html, this.getConfig());
  }

  onClear() {
    this.snotifyService.clear();
  }
}
<div class="wrapper">
  <aside>
    <h3 class="text-center">Toast config</h3>

    <div class="form-group">
      <label for="title">Title</label>
      <input [(ngModel)]="title" type="text" id="title" class="form-control" />
    </div>
    <div class="form-group">
      <label for="body">Body</label>
      <textarea [(ngModel)]="body" id="body" rows="2" class="form-control"></textarea>
    </div>
    <div class="row">
      <div class="col-xs-6">
        <div class="form-group">
          <label for="titlemaxlen">Title max-length</label>
          <input [(ngModel)]="titleMaxLength" type="text" id="titlemaxlen" class="form-control" />
        </div>
      </div>
      <div class="col-xs-6">
        <div class="form-group">
          <label for="bodymaxlen">Body max-length</label>
          <input [(ngModel)]="bodyMaxLength" type="text" id="bodymaxlen" class="form-control" />
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-6">
        <div class="form-group">
          <label for="timeout">Timeout</label>
          <input [(ngModel)]="timeout" type="number" id="timeout" class="form-control" />
        </div>
      </div>
      <div class="col-xs-6">
        <div class="form-group">
          <label for="backdrop">
            Backdrop (0.0 - 1.0)
          </label>
          <input [(ngModel)]="backdrop" type="number" id="backdrop" class="form-control" min="-1" max="1" />
        </div>
      </div>
    </div>

    <div class="form-group">
      <label for="position">Position</label>
      <div class="row">
        <div class="col-sm-12">
          <select [(ngModel)]="position" id="position" class="form-control">
            <option [ngValue]="'leftTop'">LEFT - TOP</option>
            <option [ngValue]="'leftCenter'">LEFT - CENTER</option>
            <option [ngValue]="'leftBottom'">LEFT - BOTTOM</option>
            <option [ngValue]="'rightTop'">RIGHT - TOP</option>
            <option [ngValue]="'rightCenter'">RIGHT - CENTER</option>
            <option [ngValue]="'rightBottom'">RIGHT - BOTTOM</option>
            <option [ngValue]="'centerTop'">CENTER - TOP</option>
            <option [ngValue]="'centerCenter'">CENTER - CENTER</option>
            <option [ngValue]="'centerBottom'">CENTER - BOTTOM</option>
          </select>
        </div>
      </div>
    </div>
    <div class="switch-group-wrapper">
      <div class="switch-wrapper">
        <strong>Show progress bar?</strong>
        <div class="switch">
          <input [(ngModel)]="progressBar" id="progressBar" class="cmn-toggle cmn-toggle-yes-no" type="checkbox" />
          <label for="progressBar" data-on="On" data-off="Off"></label>
        </div>
      </div>
      <div class="switch-wrapper">
        <strong>Close on click?</strong>
        <div class="switch">
          <input [(ngModel)]="closeClick" id="closeClick" class="cmn-toggle cmn-toggle-yes-no" type="checkbox" />
          <label for="closeClick" data-on="On" data-off="Off"></label>
        </div>
      </div>
      <div class="switch-wrapper">
        <strong>Pause on hover?</strong>
        <div class="switch">
          <input [(ngModel)]="pauseHover" id="pauseHover" class="cmn-toggle cmn-toggle-yes-no" type="checkbox" />
          <label for="pauseHover" data-on="On" data-off="Off"></label>
        </div>
      </div>
      <div class="switch-wrapper">
        <strong>New items on top?</strong>
        <div class="switch">
          <input [(ngModel)]="newTop" id="newTop" class="cmn-toggle cmn-toggle-yes-no" type="checkbox" />
          <label for="newTop" data-on="On" data-off="Off"></label>
        </div>
      </div>
      <div class="switch-wrapper">
        <strong>Filter duplicates?</strong>
        <div class="switch">
          <input
            [(ngModel)]="filterDuplicates"
            id="filterDuplicates"
            class="cmn-toggle cmn-toggle-yes-no"
            type="checkbox"
          />
          <label for="filterDuplicates" data-on="On" data-off="Off"></label>
        </div>
      </div>
    </div>

    <div class="row">
      <div class="col-xs-6">
        <div class="form-group">
          <label for="dockMax">
            Max on screen
          </label>
          <input [(ngModel)]="dockMax" type="number" id="dockMax" class="form-control" min="1" />
        </div>
      </div>
      <div class="col-xs-6">
        <div class="form-group">
          <label for="blockMax">
            Max at position
          </label>
          <input [(ngModel)]="blockMax" type="number" id="blockMax" class="form-control" min="1" />
        </div>
      </div>
    </div>

    <div class="form-group">
      <label for="style">Toast Style</label>
      <div class="row">
        <div class="col-sm-12">
          <select [(ngModel)]="style" id="style" class="form-control">
            <option [ngValue]="'material'">Material</option>
            <option [ngValue]="'dark'">Dark</option>
            <option [ngValue]="'simple'">Simple</option>
          </select>
        </div>
      </div>
    </div>

    <div class="form-group">
      <div class="buttons">
        <div class="btn-group btn-group-justified">
          <div class="btn btn-success" (click)="onSuccess()">Success</div>
          <div class="btn btn-info" (click)="onInfo()">Info</div>
          <div class="btn btn-danger" (click)="onError()">Error</div>
          <div class="btn btn-warning" (click)="onWarning()">Warning</div>
        </div>
        <div class="btn-group btn-group-justified">
          <div class="btn btn-default" (click)="onSimple()">Simple</div>
          <div class="btn btn-blue" (click)="onAsyncLoading()">Async</div>
          <div class="btn btn-teal" (click)="onConfirmation()">Confirm</div>
          <div class="btn btn-black" (click)="onPrompt()">Prompt</div>
        </div>
        <div class="btn-group btn-group-justified">
          <div class="btn btn-default" (click)="onHtml()">HTML</div>
        </div>
      </div>
    </div>

    <div class="btn btn-block btn-primary" (click)="onClear()">Clear all</div>
  </aside>
  <div class="content">
    <main>
      <div class="brand">
        <h1>Ng-Snotify</h1>
        <p>Angular 2+ Notification Center</p>
      </div>
    </main>
    <footer>
      <div class="footer">
        <a href="documentation/index.html" target="_blank">Documentation</a> &#9673;
        <a href="compodoc/index.html" target="_blank">Compodoc</a> &#9673;
        <a href="https://github.com/artemsky/ng-snotify" target="_blank">GitHub</a> &#9673;
        <a href="https://www.npmjs.com/package/ng-snotify" target="_blank">NPM</a>
        <h6>MIT &copy; 2018 <a href="https://github.com/artemsky/">artemsky</a></h6>
      </div>
    </footer>
    <ng-snotify class="{{ style }}"></ng-snotify>
  </div>
</div>

./app.component.scss

@import url("https://fonts.googleapis.com/css?family=Audiowide");

.wrapper {
  display: flex;
  height: 100vh;
  width: 100vw;
  overflow: hidden;

  @media (max-width: 767px) {
    flex-flow: column nowrap;
    height: auto;
    font-size: 12px;
  }

  aside {
    flex: 0 0 350px;
    padding: 10px 15px;
    overflow-y: auto;
    z-index: 5;
    .btn-group {
      .btn {
        padding: 6px 9px;
      }
    }

    h3 {
      margin: 0;
    }

    @media (max-width: 767px) {
      order: 1;
      overflow: initial;
    }
  }

  .content {
    position: relative;
    width: 100%;
    display: flex;
    flex-flow: column nowrap;
    background: #ea5c54; /* Old browsers */
    background: -moz-linear-gradient(-45deg, #ea5c54 0%, #bb6dec 100%); /* FF3.6+ */
    background: -webkit-gradient(
      linear,
      left top,
      right bottom,
      color-stop(0%, #ea5c54),
      color-stop(100%, #bb6dec)
    ); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(-45deg, #ea5c54 0%, #bb6dec 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(-45deg, #ea5c54 0%, #bb6dec 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(-45deg, #ea5c54 0%, #bb6dec 100%); /* IE10+ */
    background: linear-gradient(135deg, #ea5c54 0%, #bb6dec 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EA5C54 ', endColorstr='#bb6dec',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */

    main {
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      .brand {
        position: absolute;
        color: #ffffff;

        h1 {
          font-family: "Audiowide", cursive;
          font-display: swap;
          font-size: 6em;
        }
        p {
          font-size: 2em;
          text-align: center;
        }

        @media (max-width: 992px) {
          h1 {
            font-size: 4.5em;
          }
          p {
            font-size: 1.8em;
          }

          @media (max-width: 767px) {
            h1 {
              font-size: 4em;
            }
            p {
              font-size: 1.5em;
            }
          }
        }
      }

      @media (max-width: 767px) {
        flex-flow: column nowrap;
        order: 0;
        height: 110px;
      }
    }

    footer {
      flex: 0 0 65px;
      text-align: center;
      color: #ffffff;
      font-size: 1em;
      a {
        color: #fff;
      }
      h6 {
        font-size: 0.9em;
      }

      @media (max-width: 767px) {
        flex: 0 0 40px;
      }
    }
  }
}
//
//main {
//  position: fixed;
//  top: 0;
//  left: 0;
//  width: 100%;
//  height: 100%;
//  background: #EA5C54 ; /* Old browsers */
//  background: -moz-linear-gradient(-45deg,  #EA5C54  0%, #bb6dec 100%); /* FF3.6+ */
//  background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,#EA5C54 ), color-stop(100%,#bb6dec)); /* Chrome,Safari4+ */
//  background: -webkit-linear-gradient(-45deg,  #EA5C54  0%,#bb6dec 100%); /* Chrome10+,Safari5.1+ */
//  background: -o-linear-gradient(-45deg,  #EA5C54  0%,#bb6dec 100%); /* Opera 11.10+ */
//  background: -ms-linear-gradient(-45deg,  #EA5C54  0%,#bb6dec 100%); /* IE10+ */
//  background: linear-gradient(135deg,  #EA5C54  0%,#bb6dec 100%); /* W3C */
//  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EA5C54 ', endColorstr='#bb6dec',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
//  z-index: 1;
//}
//
//aside {
//  position: fixed;
//  top: 0;
//  left: 0;
//  width: 340px;
//  height: 100%;
//  padding: 15px;
//  background: #fff;
//  overflow-y: auto;
//  overflow-x: hidden;
//  z-index: 3;
//  .btn-group {
//    .btn {
//      padding: 6px 9px;
//    }
//  }
//
//  h3 {
//    margin: 0;
//  }
//}
//
//.brand {
//  position: absolute;
//  top: 50%;
//  left: 50%;
//  transform: translateY(-50%) translateX(calc(-50% + 340px / 2));
//  color: #ffffff;
//  h1 {
//    font-family: 'Audiowide', cursive;
//    font-size: 6em;
//  }
//  p {
//    font-size: 2em;
//    text-align: center;
//  }
//}
//
//textarea{
//  resize: vertical;
//}
//
//footer {
//  display: block;
//  padding: 10px;
//  position: fixed;
//  bottom: 15px;
//  left: 50%;
//  font-size: 15px;
//  text-align: center;
//  color: white;
//  width: calc(100% - 340px);
//  transform: translateX(calc(-50% + 340px / 2));
//  z-index:2;
//  a {
//    color: #ffffff;
//  }
//}

.buttons {
  margin: 20px 0;
}

.btn-group {
  margin: 5px 0 0;
}

.btn-black {
  color: #f8f8f8;
  background-color: #2d2d2d;
  border-color: #000000;
  &:hover {
    color: #fff;
    background-color: #000000;
    border-color: #000000;
  }
}

.btn-blue {
  color: #f8f8f8;
  background-color: #2095f2;
  border-color: #1a80d1;
  &:hover {
    color: #fff;
    background-color: #1a80d1;
    border-color: #1a80d1;
  }
}

.btn-teal {
  color: #f8f8f8;
  background-color: #009587;
  border-color: #018175;
  &:hover {
    color: #fff;
    background-color: #018175;
    border-color: #018175;
  }
}

.switch-wrapper {
  width: 50%;
}

.switch-group-wrapper {
  display: flex;
  flex-flow: row wrap;
  margin: 5px 0 10px;
}

.cmn-toggle {
  position: absolute;
  margin-left: -9999px;
  padding: 2px;
  width: 60px;
  height: 30px;
  visibility: hidden;

  + label {
    display: block;
    position: relative;
    padding: 2px;
    width: 60px;
    height: 30px;
    cursor: pointer;
    outline: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;

    &::before,
    &::after {
      display: block;
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      color: #fff;
      font-family: "Roboto Slab", serif;
      font-size: 20px;
      text-align: center;
      line-height: 30px;
    }
    &::before {
      background-color: #dddddd;
      content: attr(data-off);
      transition: transform 0.5s;
      backface-visibility: hidden;
    }

    &::after {
      background-color: #8ce196;
      content: attr(data-on);
      transition: transform 0.5s;
      transform: rotateY(180deg);
      backface-visibility: hidden;
    }
  }

  &:checked {
    + label {
      &::before {
        transform: rotateY(180deg);
      }
      &::after {
        transform: rotateY(0);
      }
    }
  }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""