Search code examples
javascriptangularjsangularjs-scopees6-classangularjs-material

Scope problem - Nested $mdDialog within class based controller


I am moving my AngularJS controllers over to a class based model in order to support a few newer ideas that have come up lately. This has brought up an issue using AngularJS Materials $mdDialog service that I'm having trouble with.

I have a setup where a parent dialog is opened, and another performs a confirmation step when a user wants to undo any changes they've made.

Parent dialog Code:

// Expand item data
expandItem(data, ev){
  this._mdDialog.show({
    controller: 'expandCtrl',
    controllerAs: 'ec',
    templateUrl: 'path/to/template',
    parent: angular.element( document.body ),
    targetEvent: ev,
    clickOutsideToClose: true,
    locals: { 
      data: {
        asset: data,
        table: this.selectTable
      }}
  }).then(rowData => {
  }, function(){});
}

Nested dialog Code:

(function () {
'use strict';
class expandCtrl {

  constructor($mdDialog, data) {
    this.itemData = data;
    this.itemStateCapture = angular.copy(this.itemData);
    this._mdDialog = $mdDialog;
  }

  // Cancel edits and revert item back to its previous state
  cancelEdits(ev) {

    let cancelConfirm = this._mdDialog.confirm()
    .multiple(true)
    .title('Are you sure?')
    .textContent('Really cancel all edits and revert this item back to its original state?')
    .ariaLabel('Edit cancel confirmation')
    .targetEvent(ev)
    .ok('Cancel Edits!')
    .cancel('Go Back');

    this._mdDialog.show(cancelConfirm).then(function() {

      //**************************//
      //**** The Problem Line ****//
      //**************************//
      this.itemData = this.itemStateCapture;

    }, function() {});
  }
}
// Init Controller
angular.module('dbProject').controller('expandCtrl', expandCtrl);

})();

I need to have the top level this.itemData variable be rewritten inside of the this._mdDialog.show() line. There appears to be a scoping problem though, and nothing I've tried successfully accesses that variable. I have tried injecting $scope, redirecting to an outside function, even accessing the data through angular.element().controller(), but I haven't made any headway.

What am I doing wrong?


Solution

  • I ended up converting my controller to a hybrid sort of approach, and including $scope. $mdDialog seems to not function well without it (Though I would love to be proven wrong).

    See below:

    (function () {
    'use strict';
      angular
        .module('myProject')
        .controller('expandCtrl', expandCtrl);
    
        expandCtrl.$inject = [
          '$mdDialog',
          '$timeout',
          '$scope',
          'data',
          'uaService',
          'dataService'
        ];
    
        function expandCtrl($mdDialog, $timeout, $scope, data, uaService, dataService){
          // Submit edits functionality
          this.submitEdits = function(table, access, data, ev){
            let confirmSubmit = $mdDialog.confirm()
            .multiple(true)
            .title('Are you sure?')
            .textContent('Really submit these changes?')
            .ariaLabel('Submit confirmation')
            .targetEvent(ev)
            .ok('Submit!')
            .cancel('Go Back');
    
            $mdDialog.show(confirmSubmit).then(function() {
    
                let editData = {
                    table: $scope.table,
                    data: $scope.itemData,
                    prevData: $scope.itemStateCapture
                }
    
                dataService.submitEdits(editData)
                .then(res =>{
                    console.log(res);
                }).catch(e =>{console.error(e)})
    
            }, function() {});
        }
      }
    })();