如何扩展/覆盖 Angular Material $mdDialog.show 中的默认选项?

Posted

技术标签:

【中文标题】如何扩展/覆盖 Angular Material $mdDialog.show 中的默认选项?【英文标题】:How to extend/overwrite default options in Angular Material $mdDialog.show? 【发布时间】:2016-09-17 17:31:36 【问题描述】:

TL;DR:我需要一种方法来使用提供程序(与任何其他 Angular 模块一样 - a random example)覆盖提供我的 Angular 材质(尤其是在材质对话框中)提供的默认选项。

我一直在寻找一种方法来自定义默认值options Angular Material Modal,但没有任何可用的结果。

就像我在其他插件/模块上使用的一样,这种方式可以使用provider 来实现。查看材料的核心 (1.0.8) 我试图使用这样的setDefaults 方法设置选项(假设我只想暂时禁用背景):

app.config(['$mdDialogProvider', function($mdDialogProvider)
    console.log($mdDialogProvider); 
    // ^ $get/addMethod/addPreset/setDefaults

    var defaults = 
        options: function()
            return 
                hasBackdrop: false
            
        
    
    $mdDialogProvider.setDefaults(defaults);
]);

现在,当我检查 onComplete 回调上的选项时:

如您所见,hasBackdrop 选项已更新,但模式不再起作用,所以我想我遗漏了一些东西。

您知道如何以适当的方式扩展默认角度吗?

谢谢

UPDATE : 没有.setDefaults 活动的选项对象(de 初始状态)

注意:我从他们的核心 transformTemplate 复制并添加到我的默认对象中,但结果是相同的。我可以看到 DOM 更新了,控制台没有错误,但模式不可见。

【问题讨论】:

你能解释一下你最终想要达到的目标吗?制定任务,也许可以有一种更透明的方式来实现它然后修补原始服务 请检查我的更新。我只需要一种更新默认材质选项的方法。现在,假设我想删除所有模块的背景,我必须在每个 show 显示实例上调用它,而不是添加 hasBackdrop: false 作为所有模式的全局选项 我现在明白了。在我看来,您可以通过创建一个模态工厂来实现这一点,该工厂将使用更新的属性包装角材料模态。我会尽力说明我的意思 我为此做了一种包装服务,但我很好奇是否可以使用似乎是 Angular 的“正确方法”的提供程序。我还将使用我的服务更新代码。无论如何,将其添加到答案中,它可以以比我更好的方式完成。 【参考方案1】:

当您想从第三方库更新现有功能时,您应该尝试使用装饰器模式并装饰服务方法。

Angular 在配置应用程序时提供了一种在providers 上使用decorators 的简洁方法:https://docs.angularjs.org/api/auto/service/$provide

$provide.decorator

$provide.decorator(name, decorator);

使用 $injector 注册一个服务装饰器。服务装饰器拦截服务的创建,允许它覆盖或修改服务的行为。装饰器返回的对象可能是原始服务,也可能是替换或包装并委托给原始服务的新服务对象。

您可以为$mdDialogProvider 编写一个装饰器来扩展.show 方法的功能,并将扩展的options 对象传递给它,如下所示:

.config(function ($provide) 
  // Decorate the $mdDialog service using $provide.decorator
  $provide.decorator("$mdDialog", function ($delegate) 
    // Get a handle of the show method
    var methodHandle = $delegate.show;

    function decorateDialogShow () 
      var args = angular.extend(, arguments[0],  hasBackdrop: false )
      return methodHandle(args);
    

    $delegate.show = decorateDialogShow; 
    return $delegate;
  );
);

我创建了一个带有 hasBackdrop: false 工作示例的代码笔,因此在调用$mdDialog.show() 时不会显示背景:http://codepen.io/addi90/pen/RaXqRx

【讨论】:

对此的一个小提示:var args = angular.extend(, arguments[0], hasBackdrop: false )。我会更改顺序以确保模式特定选项将覆盖我的自定义默认值,因此将变为:var args = angular.extend(, hasBackdrop: false , arguments[0])。同样对于更简洁的代码,可以在变量中定义具有默认值的对象:D 同意。但这是对解决方案的优化:) 不错的解决方案!如果对话框是从Preset 创建的,也许您需要检查arguments[0]._options【参考方案2】:

请在此处找到带有演示的 codepen:http://codepen.io/shershen08/pen/vGoQZd?editors=1010

服务的外观如下:

   var dialogFactory = function($mdDialog) 
      var options = ;
  return 

    create: function(conf) 
      var preset = $mdDialog.alert()._options; //get defaults
      var newOptions = angular.extend(preset, conf, options);//extend with yours
      $mdDialog.show(newOptions);
    ,
    //toggle various props
    setProp: function(prop, val) 
      options[prop] = val;
    
  ;

;

在控制器中你可以像这样使用它:

$scope.toggleBackdrop = function() 
        $scope.backdrop = !$scope.backdrop;
        //here we change the state of the service internal var
        dialogService.setProp('hasBackdrop', $scope.backdrop);
      ;
      $scope.showDialogViaService = function(ev) 
        //here we fill in the needed params of the modal and pass to the service
        var obj = 
          'title': 'title',
          'content': 'content',
          'ok':'Ok!'
        ;
        dialogService.create(obj);
      

【讨论】:

以上是关于如何扩展/覆盖 Angular Material $mdDialog.show 中的默认选项?的主要内容,如果未能解决你的问题,请参考以下文章

Angular Material Snackbar 位置

包装或扩展 angular-material 组件,允许将未知属性传递给子组件

Angular Material mat-spinner 自定义颜色

Angular 9 - 删除 Angular Material Stepper 上的默认图标(创建)

Angular Material Chips 显示为矩形,而不是在 sidenav 内被舍入

如何有效地使用 Angular Material 自定义调色板颜色 Angular Material