Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/454.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript md对话框的自定义堆栈很少导致作用域中断_Javascript_Angularjs_Dialog_Angular Material - Fatal编程技术网

Javascript md对话框的自定义堆栈很少导致作用域中断

Javascript md对话框的自定义堆栈很少导致作用域中断,javascript,angularjs,dialog,angular-material,Javascript,Angularjs,Dialog,Angular Material,前提 从引导切换到angular material时,我看到的一个限制是,在单个工作流中没有多个对话框的固有机制(至少,从文档的角度来看不是这样)。为了解决这个问题,我创建了自己的堆栈,我认为这是一个合理的抽象机制,可以有效地使用它。该文件复制如下 问题 大多数情况下,它的工作原理与您预期的一样。但是,如果对话框最初是使用现有范围创建的,则关闭对话框也会破坏关联范围的情况非常罕见(而且似乎没有一致性)。有时,这表现为后续对话框无法打开,或者如果它们确实打开,则无法填充其中嵌套的绑定。在其他情况下

前提

从引导切换到angular material时,我看到的一个限制是,在单个工作流中没有多个对话框的固有机制(至少,从文档的角度来看不是这样)。为了解决这个问题,我创建了自己的堆栈,我认为这是一个合理的抽象机制,可以有效地使用它。该文件复制如下

问题

大多数情况下,它的工作原理与您预期的一样。但是,如果对话框最初是使用现有范围创建的,则关闭对话框也会破坏关联范围的情况非常罕见(而且似乎没有一致性)。有时,这表现为后续对话框无法打开,或者如果它们确实打开,则无法填充其中嵌套的绑定。在其他情况下,它会导致父页面上的每个角度元素失败。标准链接工作正常,但任何ng click事件等不再起作用。我不知道为什么会这样。我希望有一双新的眼睛能帮助我发现我犯下的任何愚蠢的错误

用法

堆栈有两种使用方式:推送或替换。如果将新对话框推送到堆栈中,任何当前对话框都将隐藏并以保留其上下文的方式存储。这基本上意味着首先用于生成模态的所有参数都存储在一个对象中,并推送到堆栈上,堆栈是本地存储在DialogStack服务中的数组。在此之后,渲染函数使用堆栈上的最高元素生成一个新模式。如果选择替换,则过程实际上是相同的,只是在添加新对话框之前堆栈已完全清除

实际对话框参数存储在全局对象DIALOGS中。所有对话框(dialogs.DEFAULTS)都使用默认参数,然后为系统创建的每个对话框都有自己的属性集,包括一个templateUrl和一个简要说明。有时,它们也会替代标准特性。渲染对话框时,与当前对话框关联的对象将与DIALOGS.DEFAULTS对象混合使用Lodash,以使自定义特性优先。特别值得注意的是preserveScope属性,它在DIALOGS.DEFAULTS中设置为true。我本来希望扩大这面旗帜的使用范围,但为了稳定起见,这面旗帜基本上被搁置了。我看到的问题来自于未触及preserveScope的对话框(设置为true)

请注意,还有一个实用程序函数可以使用内置的确认对话框,该对话框使用基本构造函数而不是DIALOGS对象生成其参数

代码

普朗克:

对话框堆栈:

对话

'use strict';

/**
 * @ngdoc function
 * @name dialogsuite.service:DialogStack
 * @description
 * # DialogStack
 * Handles dialog management under angular-material
 */
angular.module('dialogsuite')
  .factory('DialogStack',
    ['$mdDialog', '$q', '$rootScope',
     'Util',
     'DIALOGS',
    function ($mdDialog, $q, $rootScope,
              Util,
              DIALOGS) {

    var stack;
    var processing;
    // var debugCount = 0;

    /**
     * Removes all dialogs from the stack
     **/
    function clear (hideAll)
    {
      if (!!hideAll)
      {
        stack = [];

        renderDialog ();
      }
      else
      {
        if (!!stack && stack.length === 1)
        {
          processing = false;
        }

        $mdDialog.hide ();
      }
    }

    /**
     * Closes the visible dialog
     **/
    function close ()
    {
      if (!stack || !stack.length) { return; }

      $mdDialog.hide ();
    }

    /**
     * Shows a confirm dialog and calls the appropriate callback
     **/
    function confirm (message, confirmCallback, cancelCallback)
    {
      if (!stack)
      {
        stack = [];
      }
      else if (!!stack.length)
      {
        processing = true;
      }

      var params = $mdDialog.confirm ()
                    //.title('Confirm Action')
                    .textContent (message)
                    .ariaLabel ('dialog')
                    .ok ('CONFIRM')
                    .cancel ('CANCEL')
                    .theme ('default')
                    ._options;

      params.onRemoving = function () { pop (); };

      stack.push (params);

      $rootScope.$evalAsync (function ()
      {
        $mdDialog.show (params).then (confirmCallback, cancelCallback);
      });
    }

    /**
     * Removes the dialogue at the top of the stack. If there are any dialogs
     * remaining, opens the next one down
     **/
    function pop (force)
    {
      if ((!!stack && !!stack.length && !processing) ||
          (!!stack && !!stack.length && force === true))
      {
        var removed = stack.pop ();

        $rootScope.$broadcast ('llDialogClosed', removed);

        renderDialog ();
      }

      processing = false;
    }

    /**
     * Adds a dialog to the stack and opens it immediately
     **/
    function push (dialog, scope, locals)
    {
      if (!dialog)
      {
        throw 'Exception: No dialog provided';
      }

      if (!stack)
      {
        stack = [];
      }

      processing = true;

      if (!!scope)
      {
        dialog.scope = scope;
      }

      //Note: Locals get injected into the dialog's controller
      if (!!locals)
      {
        dialog.locals = locals;
      }

      stack.push (dialog);

      renderDialog ();
    }

    /**
     * Closes any dialog that may currently be open, then shows the dialog at
     * this top of the stack
     **/
    function renderDialog ()
    {
      /*
      locals     {object=}:   An object containing key/value pairs. The keys will be used as names of values to inject into the controller. For example, `locals: {three: 3}` would inject three into the controller, with the value 3. If bindToController is true, they will be copied to the controller instead.
      onShowing  {function=}: Callback function used to announce the show() action is starting.
      onComplete {function=}: Callback function used to announce when the show() action is finished.
      onRemoving {function=}: Callback function used to announce the close/hide() action is starting. This allows developers to run custom animations in parallel the close animations.
      resolve    {object=}:   Similar to locals, except it takes promises as values, and the dialog will not open until all of the promises resolve.
      */

      if (!stack || !stack.length)
      {
        $mdDialog.hide ();
        processing = false;
        return;
      }

      var params = _.assign (DIALOGS.DEFAULTS, stack[stack.length - 1]);

      params.onRemoving = function () { pop (); };

      $rootScope.$evalAsync (function ()
      {
        //When a modal becomes visible, any previous modals are automatically
        //hidden. By doing this manually we can clear the processing flag without
        //destroying the rest of the stack, since onRemoving resolves before the
        //promise does
        $mdDialog.hide ()
        .then (function ()
        {
          processing = false;
          $mdDialog.show (params);
        });
      });
    }

    /**
     * Replaces the dialog stack with the given dialog
     **/
    function replace (dialog, scope, locals)
    {
      stack = [];

      push (dialog, scope, locals);
    }

    /* ********************************************************************** */

    //Service public-facing functions
    var DialogStack = {
      clear: clear,
      close: close,
      confirm: confirm,
      pop: pop,
      push: push,
      replace: replace
    };

    return DialogStack;
  }]);
app.value ('DIALOGS',
  {
    'DEFAULTS':
    {
      autoWrap: false,
      clickOutsideToClose: true,
      disableParentScroll: true,
      escapeToClose: true,
      focusOnOpen: true,
      fullscreen: true,
      hasBackdrop: true,
      parent: $('body'),
      preserveScope: true
    },
    'MODALROOT':
    {
      desc: 'multi-purpose container, usually for displaying messages',
      fullscreen: false,
      name: 'root',
      templateUrl: 'modal-root.html'
    }
  })