title: Trigger Angular Material toast on state change
body: <p>I'm currently developing an <a href="https://angularjs.org/" rel="nofollow noreferrer">AngularJS</a> web application, which is setup and using <a href="https://material.angularjs.org/latest/demo/toast" rel="nofollow noreferrer">Angular Material</a>.</p>
  
  <p>I have implemented the <a href="https://material.angularjs.org/latest/demo/toast" rel="nofollow noreferrer">Angular Material Toast</a> feature, without any problems. </p>
  
  <p>Also, I have setup several views using <a href="https://github.com/angular-ui/ui-router" rel="nofollow noreferrer">ui-router</a> - 1. Index, 2. Parent &amp; 3. Child (See attached).</p>
  
  <p>I'm able to view and click through Prev/Next states:</p>
  
  <pre><code>#/dashboard/raiding-the-rails/1
  </code></pre>
  
  <p>So what is the problem? Well I want to be able to trigger specific toast messages depending and relevant to the current state ID. </p>
  
  <p>e.g <code>#/dashboard/raiding-the-rails/5</code> will display toast message 5.</p>
  
  <p>I tried setting up a service/factory and couldn't figure out how todo this!</p>
  
  <p>I even subscribed to <a href="http://egghead.io" rel="nofollow noreferrer">egghead.io</a> just to try and find a pro solution! </p>
  
  <p>Any help and advice would really help!<br/>Thank you!!!</p>
  
  <p><strong>Diagram:</strong> <br/><br/>
  <a href="https://i.stack.imgur.com/T1Q66.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/T1Q66.jpg" alt="Screenshot"></a>
  <br/><br/>
  <strong>App:</strong><br/></p>
  
  <pre><code>(function(angular, undefined){
    "use strict";
    var am = angular.module('virtual-fitting', ['ngAnimate', 'ngAria', 'ngMaterial', 'ui.router', 'firebase']);
    // Beginning
    am.config(function ($stateProvider, $urlRouterProvider) {
      $stateProvider
        .state('authentication', {
          url: '/authentication',
          templateUrl: '../views/authentication.html'
        })
        .state('dashboard', {
          url: '/dashboard',
          controller: 'dashboardCtrl as dashboard',
          templateUrl: '../views/dashboard.html'
        })
        .state('dashboard.bodytype', {
          url: '/body-type',
          templateUrl: '../views/dashboard.body-type.html'
        })
        .state('dashboard.raidingtherails', {
          abstract: true,
          url: '/raiding-the-rails',
          templateUrl: '../views/dashboard.raiding-the-rails.html'
        })
        .state('dashboard.raidingtherails.dress', {
          url: '/:id',
          controller: 'raidingtherailsCtrl as raiding',
          templateUrl: '../views/dashboard.raiding-the-rails.dress.html'
        })
        .state('dashboard.collection', {
          url: '/collection',
          templateUrl: '../views/dashboard.collection.html'
        })
        .state('dashboard.lovelist', {
          url: '/love-list',
          templateUrl: '../views/dashboard.love-list.html'
        })
        .state('dashboard.secondopinion', {
          url: '/second-opinion',
          templateUrl: '../views/dashboard.second-opinion.html'
        });
        $urlRouterProvider.otherwise('/dashboard/raiding-the-rails/1');
    });
    // End
  })(angular);
  </code></pre>
  
  <p><br/>
  <strong>Primary Controller:</strong></p>
  
  <pre><code>(function(angular, undefined) {
    "use strict";
    var am = angular.module('virtual-fitting');
    // Beginning
    am.controller('dashboardCtrl', function($scope, $state, $mdDialog, $mdToast) {
      var self = this;
      // FAB Speed Dial
      self.isOpen = false;
      self.selectedMode = 'md-scale';
      self.selectedDirection = 'down';
      // onClick State
      self.pageUrl = function(state) {
        $state.go(state);
      };
      // Dialog Show
      self.dialog = function($event, id) {
        $mdDialog.show({
          clickOutsideToClose: true,
          controller: function($mdDialog) {
            this.item = id;
            // Dialog Hide
            this.close = function() {
              $mdDialog.cancel();
            };
            this.submit = function() {
              $mdDialog.hide();
            };
          },
          controllerAs: 'dialog',
          templateUrl: '../views/dashboard.dialog.html',
          targetEvent: $event
        });
      };
      // Toast Setup
      self.toastPosition = angular.extend({}, {
        bottom: true,
        left: true
      });
      self.getToastPosition = function() {
        return Object.keys(self.toastPosition)
          .filter(function(pos) {
            return self.toastPosition[pos];
          })
          .join(' ');
      };
      // Toast Show
      self.showToast = function() {
        $mdToast.show({
          controller: function() {
            this.item = 'Hello';
            // Toast Hide
            this.hideToast = function() {
              $mdToast.hide();
            };
          },
          controllerAs: 'toast',
          templateUrl: '../views/dashboard.toast.html',
          hideDelay: 10000,
          position: self.getToastPosition()
        });
      };
    });
    // End
  })(angular);
  </code></pre>
  
  <p><strong>Child Controller:</strong></p>
  
  <pre><code>(function(angular, undefined) {
    "use strict";
    var am = angular.module('virtual-fitting');
    // Beginning
    am.controller('raidingtherailsCtrl', function($scope, $state, $stateParams) {
      var self = this;
      self.id = $stateParams.id;
      self.prev = function() {
        self.minus = parseFloat(self.id) - parseFloat(1);
        $state.go('dashboard.raidingtherails.dress', {'id': self.minus});
      };
      self.next = function() {
        self.plus = parseFloat(self.id) + parseFloat(1);
        $state.go('dashboard.raidingtherails.dress', {'id': self.plus});
      };
    });
    // End
  })(angular);
  </code></pre>
  
  <p><br/>
  <strong>Service (Deleted):</strong></p>
  
  <pre><code>(function(angular, undefined) {
    "use strict";
    var am = angular.module('virtual-fitting');
    // Beginning
    am.service('', function() {});
    // End
  })(angular);
  </code></pre>
  
  <p><strong>Update:</strong><br/><br/>
  I tried using the following but as you can see the console.log is out putting the previous id instead of the correct &amp; current id. Now I just need to trigger the message allocated to the state id! Any Ideas?</p>
  
  <pre><code>$rootScope.$on('$stateChangeStart',
    function(event, toState, toParams, fromState, fromParams){
      var test = $state.params.id;
      console.log(test);
    });
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/RNMEt.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RNMEt.png" alt="enter image description here"></a></p>
  
  <p><strong>Update</strong><BR/>
  After further Googling around and rewriting the above I finally managed to get the current state ID.</p>
  
  <pre><code>$rootScope.$watchCollection(function(){
    return $state.params;
  }, function(){
      console.log($state.params.id);
  });
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/IAeRJ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IAeRJ.png" alt="enter image description here"></a>
  <strong>Answer</strong></p>
  
  <pre><code>// Toast Setup
      self.toastPosition = angular.extend({}, {
        bottom: true,
        left: true
      });
      self.getToastPosition = function() {
        return Object.keys(self.toastPosition)
        .filter(function(pos) {
          return self.toastPosition[pos];
        }).join(' ');
      };
      $rootScope.$watchCollection(function(){
        return $state.params;
      }, function(){
        // State ID (State Params)
        var stateID = $state.params.id;
        // Toast Messages
        var toastMessages = {
          "results": [
            {'id': '1', 'message':'Textured fabrics are what you want to look for, this will help.'},
            {'id': '2', 'message':'This dress is perfect for a Triangle body shape like yours, Kerry! Its a beautiful style too!'},
            {'id': '3', 'message':'Just click on a designers name to view their collection - We have some amazing dresses!'}
          ]
        };
        // Filter against State ID
        var toastMessage = $filter('filter')(toastMessages.results, {id: stateID})[0];
        // Prevent Undefined ID
        if(toastMessage){
          self.messageID = toastMessage.id;
        }
        // Check State ID against Message ID
        if(stateID === self.messageID) {
          // Show Toast
          $mdToast.show({
            controller: function() {
              this.item = toastMessage.message;
              // Hide Toast
              this.hideToast = function() {
                $mdToast.hide();
              };
            },
            controllerAs: 'toast',
            templateUrl: '../views/dashboard.toast.html',
            hideDelay: 10000,
            position: self.getToastPosition()
          });
        } else {
          // Hide Toast on 'IF' Fail
          $mdToast.hide();
        }
      });
  </code></pre>