Rafiu
Rafiu

Reputation: 4950

how can I change the color of Toast depends on message type in Angular material $mdToast?

While using $mdToast.simple().content("some test") it is showing the toast with black color. how can I change that color to red, yellow and so, depends on the type of the error messages like error, warning and success.

Similar question as this.

Upvotes: 55

Views: 66541

Answers (9)

hurricane
hurricane

Reputation: 6734

You can do it with factory and some css.

(function () {
  'use strict';

  angular
    .module('app.core')
    .factory('ToastService', ToastService);

  /** @ngInject */
  function ToastService($mdToast) {

    var service = {
      error: error,
      success: success,
      info : info
    };

    return service;

    //////////

    function success(text) {
      $mdToast.show(
        $mdToast.simple()
          .toastClass("toast-success")
          .textContent(text)
      );
    }

    function info(text) {
      $mdToast.show(
        $mdToast.simple()
          .toastClass("toast-info")
          .textContent(text)
      );
    }

    function error(text) {
      $mdToast.show(
        $mdToast.simple()
          .toastClass("toast-error")
          .textContent(text)
      );
    }
  }
}());

And css.

.toast-error .md-toast-content{
  background-color: rgb(102,187,106) !important;
}

.toast-info .md-toast-content{
  background-color: rgb(41,182,246) !important;
}

.toast-error .md-toast-content{
  background-color: rgb(239,83,80) !important;
}

Upvotes: 0

Luca Faggianelli
Luca Faggianelli

Reputation: 2522

Just to give another option, $mdToast allows to define toast presets that you can easily instantiate in this way, though i'm struggling to understand how to change the text content, any idea?

$mdToast.show(
  $mdToast.error()
);

The presets are defined as explained on https://material.angularjs.org/latest/api/service/$mdToast :

$mdToastProvider.addPreset('error', {
  options: function() {
    return {
      template:
        '<md-toast>' +
          '<div class="md-toast-content">' +
          '</div>' +
        '</md-toast>',
      position: 'top left',
      hideDelay: 2000,
      toastClass: 'toast-error',
      controllerAs: 'toast',
      bindToController: true
    };
  }
});

Upvotes: 1

novas1r1
novas1r1

Reputation: 1934

EDIT:
For a correct implementation, please use rlay3s solution below :)!

OUTDATED:
I had problems displaying custom text with jhblacklocks solution, so I decided to do it like this using 'template':

var displayToast = function(type, msg) {

    $mdToast.show({
        template: '<md-toast class="md-toast ' + type +'">' + msg + '</md-toast>',
        hideDelay: 6000,
        position: 'bottom right'
    });
};

I also added the different types in my .css file:

.md-toast.error {
    background-color: red;
}

.md-toast.success {
    background-color: green;
}

Don't know if this is the most beautiful approach, but I don't need a template files for each dialog type and displaying custom text is really easy.

Upvotes: 32

mattatwork
mattatwork

Reputation: 127

register themes:

$mdThemingProvider.theme("success-toast");
$mdThemingProvider.theme("error-toast");

add css:

md-toast.md-error-toast-theme div.md-toast-content{
    color: white !important;
    background-color: red !important;
}

md-toast.md-success-toast-theme div.md-toast-content{
    color: white !important;
    background-color: green !important;
}

use:

$mdToast.show(
    $mdToast.simple()
        .content(message)
        .hideDelay(2000)
        .position('bottom right')
        .theme(type + "-toast")
);

Upvotes: 13

rlay3
rlay3

Reputation: 10552

There is an easier way by specifying a theme:

$mdToast.simple().content("some test").theme("success-toast")

And in your CSS:

md-toast.md-success-toast-theme {
    background-color: green;
    ...
}

You could incorporate your message type to dynamically select a theme.

Update: As Charlie Ng pointed out, to avoid warnings regarding use of an unregistered custom theme register it in your module using the theme provider: $mdThemingProvider.theme("success-toast")

Another update: There was a breaking change created on 2 Dec 2015 (v1.0.0+). You now need to specify:

md-toast.md-success-toast-theme {
    .md-toast-content {
        background-color: green;
        ...
    }
}

Upvotes: 85

Mateus AJ Leon
Mateus AJ Leon

Reputation: 1382

You can see on this link that you cannot change the background color of the element, it'll be always fixed:

https://github.com/angular/material/blob/master/src/components/toast/toast-theme.scss

This is because the Material Design Guidelines for Toasts states that the background will always remains the same:

https://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs

Note the background item on the Specs list.

Nothing is said about the text color in each situation, it's implied that it follows the backgroundPalette, on the '50' hue rotation, declared on that CSS on the GitHub Link.

The way to distinct a warn toast, or an accent-ted one, from the default, calling an action toast, each with its action button using the appropriate class (md-warn or md-accent).

$mdToast.show({
    template: '<md-toast>\
        {{ toast.content }}\
        <md-button ng-click="toast.resolve()" class="md-warn">\
            Ok\
        </md-button>\
    </md-toast>',
    controller: [function () {
        this.content = 'Toast Content';
    }],
    controllerAs: 'toast'
});

The toast itself, which its default form means an action report, with success implied. If it needs more even more attention, force its close by setting up an action button add actions like 'Retry', 'Report a problem', 'Details', which can be used to catch this click and record some technical info, etc... the examples vary from what you need.

Upvotes: 8

Charlie Ng
Charlie Ng

Reputation: 640

One more step to rlay3's answer.

Angular Material at 0.7.1 added warning to unregistered themes. https://github.com/angular/material/blob/master/CHANGELOG.md#071--2015-01-30

If theme is not registered, every time the toast shows up, you will be getting a warning message in console like, for example:

attempted to use unregistered theme 'custom-toast'
angular.js:12416 Attempted to use unregistered theme 'custom-toast'. 
Register it with $mdThemingProvider.theme().

To get rid of the warning, you will need to configure the theme 'custom-toast' in your angular app:

angular.module('myApp', ['ngMaterial'])
.config(function($mdThemingProvider) {
  $mdThemingProvider.theme('custom-toast')
});

and use it like:

$mdToast.simple().content("some test").theme("custom-toast");

references: https://material.angularjs.org/latest/#/Theming/04_multiple_themes

Upvotes: 7

Mattijs
Mattijs

Reputation: 3420

I first favoured the solution but I don't like setting up a theme in the theme provider just for a toast. So how about this solution:

JS (Coffee)

   if error
      message = ''

      if error.reason is 'Incorrect password'
        message = 'Email and password combination is incorrect'
      if error.reason is 'User not found'
        message = 'No account found with this email address'

      $mdToast.show(
        templateUrl:  'client/modules/toasts/toastError.html'
        hideDelay:    3000
        controller: ( $scope ) ->
          $scope.message    =  message
          $scope.class      = 'error'
          $scope.buttonLabel = 'close'
          $scope.closeToast = ->
            $mdToast.hide()
      ).then( ( result ) ->
        if result is 'ok'
          console.log('do action')
      )

and then HTML (JADE)

md-toast(ng-class="class")
  span(flex) {{message}}
  md-button.md-action(ng-click="closeToast()") {{buttonLabel}}

I tried to use the locals option to pass variables to the controller, but for some reason they are not injected.(https://material.angularjs.org/latest/#/api/material.components.toast/service/$mdToast check list of options under show function)

Then last the CSS (STYLUS)

md-toast.success
  background-color    green

md-toast.error
  background-color    red

Summary: there is on template in this case which you can give custom placeholders which you prefill in your controller. This solution works for me.

Upvotes: 0

jhblacklock
jhblacklock

Reputation: 146

You did ask about using the simple toast call. Would you mind trying a custom toast show like the demo and add classes to the template?

JS

$mdToast.show(
  controller: 'ToastCtrl',
  templateUrl: 'views/shared/toast.html',
  hideDelay: 6000,
  position: $scope.getToastPosition()
)

TEMPLATE

<md-toast class="flash">
  <span flex>Custom toast!</span>
  <md-button ng-click="closeToast()">
   Close
  </md-button>
</md-toast>

CSS

md-toast.flash {
  background-color: red;
  color: white;
}

CONTROLLER (COFFEE)

'use strict'

###*
 # @ngdoc function
 # @name angularApp.controller:ToastCtrl
 # @description
 # # ToastCtrl
 # Controller of the angularApp
###
angular.module('angularApp')
  .controller 'ToastCtrl', ($scope) ->
    $scope.closeToast = ()->
      $mdToast.hide()

Upvotes: 2

Related Questions