状态改变时触发 Angular Material toast

Trigger Angular Material toast on state change

我目前正在开发 AngularJS web application, which is setup and using Angular Material

我已经实现了 Angular Material Toast 功能,没有任何问题。

此外,我使用 ui-router 设置了几个视图 - 1. 索引,2. 父级和 3. 子级(见附件)。

我可以查看并点击 Prev/Next 状态:

#/dashboard/raiding-the-rails/1

那么问题是什么?好吧,我希望能够触发特定的 toast 消息,具体取决于并与当前状态 ID 相关。

例如 #/dashboard/raiding-the-rails/5 将显示 toast 消息 5.

我试过设置 service/factory 但不知道该怎么做!

我什至订阅了 egghead.io 只是为了尝试找到专业的解决方案!

任何帮助和建议都会很有帮助!
谢谢!!!

图:



应用程序:

(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);


主控制器:

(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);

子控制器:

(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);


服务(已删除):

(function(angular, undefined) {
  "use strict";
  var am = angular.module('virtual-fitting');
  // Beginning
  am.service('', function() {});
  // End
})(angular);

更新:

我尝试使用以下内容,但如您所见,console.log 输出的是之前的 ID,而不是正确的和当前的 ID。现在我只需要触发分配给状态id的消息!有什么想法吗?

$rootScope.$on('$stateChangeStart',
  function(event, toState, toParams, fromState, fromParams){
    var test = $state.params.id;
    console.log(test);
  });

更新
在进一步谷歌搜索并重写以上内容后,我终于设法获得了当前状态 ID。

$rootScope.$watchCollection(function(){
  return $state.params;
}, function(){
    console.log($state.params.id);
});

回答

// 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();
      }
    });

来自 https://github.com/angular-ui/ui-router/wiki#state-change-events

$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams){ ... })

当你改变状态时会让你跟踪。你可能想把它放在你的主控制器中,或者放在 make/configure 你的模块之后的 .run() 上。

在设置状态时,您可以添加数据 属性,它包含一个对象,您可以在其中放置任意数据。我建议用这个来保存要在 toasts 中显示的字符串,例如:

.state('dashboard.raidingtherails', {
    abstract: true,
    url: '/raiding-the-rails',
    templateUrl: '../views/dashboard.raiding-the-rails.html',
    data: {
        toast: "Raiding the rails toast"
    }
})

然后在你的onStateChangeStart中你可以引用toState.data.toast。如果你这样做,你将不需要 service/provider,但如果你想要更高级的功能,你可能会决定制作一个。

此外,您可以使用ui-router的URL参数获取URL参数(/5和url的结尾)。

// 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();
      }
    });