Is it possible to customize the appearance of a toast notification using Toastr beyond the default settings? If so, what options are available for creating

Working with Angular 9 and ngx-toastr has presented me with an interesting challenge.

I am tasked with creating custom toast styles that differ significantly from the default ones provided by toastr. Each toast in the set will have unique border colors, fontawesome icons, and messages.

Check out one of the toast mockups here: enter image description here

ngx-toastr comes with its own toastr.css style sheet, which I have added to angular.json. Without this addition, the toasts do not render properly. In order to achieve my desired customizations, I created a separate toast-messages.scss file containing all the necessary CSS properties based on my mockup design. This file is also included in angular.json.

            "styles": [
              "node_modules/@fortawesome/fontawesome-free/css/fontawesome.css",
              "node_modules/@fortawesome/fontawesome-free/css/solid.css",
              "src/styles.scss",
              "node_modules/ngx-toastr/toastr.css",
              "src/app/styles/toast-messages.scss"
            ],

Unfortunately, I've encountered an issue where every line in my toast-messages.scss file requires an !important declaration to override styles defined in toastr.css, making the process cumbersome.

My question is: What other options do I have for styling these toasts without relying heavily on !important tags in my CSS? Could I be referencing the CSS/SCSS files incorrectly? Is there a recommended approach for creating custom toast designs, considering I am relatively new to Angular (just 2 months in)?

toast-messages.scss (Note: formatting needs improvement due to trial and error)

.toast-container .ngx-toastr {
  /* Custom styles */
}
/* Other classes and styles for the toast messages go here */

Answer №1

If you want to customize your toast message, you can easily do so by referring to the official documentation

Check out this sample code snippet to see how it's done:

import {
  animate,
  keyframes,
  state,
  style,
  transition,
  trigger
} from '@angular/animations';
import { Component } from '@angular/core';

import { Toast, ToastrService, ToastPackage } from '../lib/public_api';

@Component({
  selector: '[pink-toast-component]',
  styles: [`
    :host {
      background-color: #FF69B4;
      position: relative;
      overflow: hidden;
      margin: 0 0 6px;
      padding: 10px 10px 10px 10px;
      width: 300px;
      border-radius: 3px 3px 3px 3px;
      color: #FFFFFF;
      pointer-events: all;
      cursor: pointer;
    }
    .btn-pink {
      -webkit-backface-visibility: hidden;
      -webkit-transform: translateZ(0);
    }
  `],
  template: `
  <div class="row" [style.display]="state.value === 'inactive' ? 'none' : ''">
    <div class="col-9">
      <div *ngIf="title" [class]="options.titleClass" [attr.aria-label]="title">
        {{ title }}
      </div>
      <div *ngIf="message && options.enableHtml" role="alert" aria-live="polite"
        [class]="options.messageClass" [innerHTML]="message">
      </div>
      <div *ngIf="message && !options.enableHtml" role="alert" aria-live="polite"
        [class]="options.messageClass" [attr.aria-label]="message">
        {{ message }}
      </div>
    </div>
    <div class="col-3 text-right">
      <a *ngIf="!options.closeButton" class="btn btn-pink btn-sm" (click)="action($event)">
        {{ undoString }}
      </a>
      <a *ngIf="options.closeButton" (click)="remove()" class="btn btn-pink btn-sm">
        close
      </a>
    </div>
  </div>
  <div *ngIf="options.progressBar">
    <div class="toast-progress" [style.width]="width + '%'"></div>
  </div>
  `,
  animations: [
    trigger('flyInOut', [
      state('inactive', style({
        opacity: 0,
      })),
      transition('inactive => active', animate('400ms ease-out', keyframes([
        style({
          transform: 'translate3d(100%, 0, 0) skewX(-30deg)',
          opacity: 0,
        }),
        style({
          transform: 'skewX(20deg)',
          opacity: 1,
        }),
        style({
          transform: 'skewX(-5deg)',
          opacity: 1,
        }),
        style({
          transform: 'none',
          opacity: 1,
        }),
      ]))),
      transition('active => removed', animate('400ms ease-out', keyframes([
        style({
          opacity: 1,
        }),
        style({
          transform: 'translate3d(100%, 0, 0) skewX(30deg)',
          opacity: 0,
        }),
      ]))),
    ]),
  ],
  preserveWhitespaces: false,
})
export class PinkToast extends Toast {
  // Used for demonstration purposes
  undoString = 'undo';

  // Constructor is necessary only when AoT compilation is not used
  constructor(
    protected toastrService: ToastrService,
    public toastPackage: ToastPackage,
  ) {
    super(toastrService, toastPackage);
  }

  action(event: Event) {
    event.stopPropagation();
    this.undoString = 'undid';
    this.toastPackage.triggerAction();
    return false;
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular toolbar permanently positioned at the top of the screen

My custom toolbar, along with other components, is present in the app I'm working on. In the app.component, the structure looks something like this: <app-toolbar> </app-toolbar> <main> <a [routerLink]="['/login/en&a ...

Invoke the method in customButton component of fullcalendar

I've integrated a custom button into my fullcalendar: ngOnInit() { this.calendarOptions = { customButtons: { custom1: { text: 'Add event', click() { this.openModal(); } } }, height: 600, editable: t ...

Adjust the dropdown width on a bootstrap form to match the size of the textbox

In order to maintain a combined width of 450px, I have two textboxes. One textbox includes a dropdown menu while the other does not. Both textboxes are part of an input group. The dropdown can switch between either textbox at any time. I need the width ...

What could be the reason for the unexpected behavior of position sticky?

I am encountering an issue while trying to figure out why the container__item--special element behaves as a sticky element in this code snippet <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8> ...

Troubleshooting ng-bind-html issue with displaying images loaded using CSS within HTML content

I followed the instructions provided in a related post on the same topic. I used 'ngSanitize' and formatted the HTML content using 'sce.trustAsHtml()', and it rendered correctly when the HTML contained both text and images. However, I e ...

How to reference global Sass variables in a Sass module

My preferred method involves utilizing a global .scss file that houses all the foundational styles, such as primary color selections. Following this, I create separate modules for each React Component to maintain organization and reduce the need for import ...

Ways to stylize bullet points in lists with CSS in HTML document

I am currently working on a Q&A page using simple HTML. This is the current appearance of my page. Check it out here on JSFIDDLE. My task involves adding an 'A' to the answer for each question. Some answers have multiple paragraphs, so the ...

If either the form is invalid or has been submitted, disable the button

Is there a way to either disable the button when the form is invalid or after the user clicks it, but not both at the same time? How can I incorporate two statements inside the quotes for this purpose? I attempted the following code, but it didn't w ...

Issue encountered when attempting to render a fully dynamic table with an empty object

I'm looking to dynamically generate a table with headers, rows, and cells based on JSON data retrieved from an API call. The data being fetched from the API is in the form of a dataframe. Here is a sample of the JSON'd dataframe (as seen in the ...

Optimal approach for vertically aligning elements in CSS

I'm looking to arrange my header ('Sail away today with Starboard Rentals.') and link buttons on top of each other. I want the navigation buttons to be positioned below the h1 on the lower half of the 'home-jumbo' div. What's ...

Place the h1 text inside of a div tag for organization

Here is an example of HTML code: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <tit ...

JavaScript function for automatic scrolling to the bottom of the page is not functioning as expected

I'm working on incorporating a terminal/console feature into my website. I came across the JavaScript functions for scrolling down a page, namely window.scrollTo(0,document.body.scrollHeight); and window.scrollTo(0,document.querySelector(".fakeSc ...

What is the best way to verify the presence of a route in Angular with Jasmine testing framework?

I'm currently in the process of developing a test to verify the presence of a specific route within my Angular application using Jasmine: import { routes } from './app-routing.module'; import { UsersComponent } from './users/users.comp ...

Tips for wrapping text labels in mat-slide-toggles (Angular Material)

Is there a way to get the title in mat-slide-toggle to wrap if it's too long while keeping its default position to the right of the toggle? <mat-slide-toggle class="slider">A really long title wrapped</mat-slide-toggle> I attemp ...

The inclusion of Angular 2 router queryParams in the URL is not happening

I implemented an auth guard to protect certain pages of my web-app. In order to enable users to return to the page they intended to access, I tried adding queryParams to the URL during a redirect. Initially, the code below worked as expected. However, rece ...

Tips for positioning a mat-form-field beside an h1 tag

I've been attempting to place an h1 next to a mat-form-field from Angular Material, but I'm encountering some difficulties. Here's what I've attempted so far: <div class="mat-elevation-z8"> <mat-form-field> <mat-l ...

Uploading files using Angular 6 to communicate with a Flask (Python) API

I have developed a web service using Flask to save files, following the example provided in the official Flask documentation: @app.route('/parse_table', methods=['POST']) def upload_file(): print(request.files) # check if the p ...

Angular 5: The templateRef.createEmbeddedView method is throwing an error and is not functioning as

Having trouble getting this code to function properly in Angular 5: import { Component, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core'; @Component({ selector: 'vcr', template: ` <template #tpl> & ...

Decipher and comprehend the buttons listed in the language translation document

Looking for assistance with a pipe issue. I've created the following custom SafeHtmlPipe: import { DomSanitizer } from '@angular/platform-browser'; import { Pipe, PipeTransform, SecurityContext } from '@angular/core'; @Pipe({ nam ...

Tips for adding a CSS class to an HTML element on-the-fly

As a newcomer to JavaScript and AngularJS, my question may be considered naive by some. I am currently working on a tutorial project involving AngularJS. Here is the HTML code snippet I am dealing with: <link href="http://netdna.bootstrapcdn.com/boo ...