以最优雅的方式显示弹出窗口

178

我有一个AngularJS应用程序。所有东西都运作正常。

现在,当特定条件成立时,我需要显示不同的弹出窗口,我正在考虑采取什么最好的方法。

目前我正在评估两个选项,但我绝对愿意接受其他选项。


选项1

我可以为弹出窗口创建新的HTML元素,并直接从控制器附加到DOM中。

这将破坏MVC设计模式。我对这个解决方案不满意。


选项2

我可以始终在静态HTML文件中插入所有弹出窗口的代码。然后,使用ngShow,我可以隐藏/显示只正确的弹出窗口。

这个选项不真正具有可扩展性。


因此,我非常确定必须有更好的方法来实现我的要求。


有很多种方法,控制器用于HTML绝对不是好的方式,可以看一下UI Bootstrap Modal http://angular-ui.github.com/bootstrap/#/modal - charlietfl
1
AngularJS的文档在“理解Transclusion和Scopes”一节中简要介绍了如何管理弹出窗口。希望这能有所帮助。 - Ivan Ferrer Villa
如果你真的想要通过弹出窗口进行扩展,那么请查看 popscript - Raj Nathani
5个回答

88

根据我对AngularJS模态框的经验,我认为最优雅的方法是创建一个专门的服务,我们可以向该服务提供一个部分(HTML)模板以在模态框中显示。

当我们考虑它时,模态框有点像AngularJS路由,但只是以模态弹出窗口的形式显示。

AngularUI bootstrap项目 (http://angular-ui.github.com/bootstrap/)有一个出色的$modal服务(在版本0.6.0之前称为$dialog),用于实现将部分内容显示为模态弹出窗口的服务。


10
$dialog现在变成了$modal。 - Sangram Singh
1
@pkozlowski.opensource 我喜欢 ui-bootstrap 的方法,但是我似乎不能将内容传递到模态框中。我做了一些研究,发现其他人也有这个问题。 - jusopi
2
我觉得这篇文章非常有用。 - RasikaSam
1
@superluminary 这确实是一个好的普遍规则,但了解为什么某个规则存在以及何时可以(甚至应该!)打破这样的规则也很重要。我认为模态框/工具提示等是规则的例外情况。简而言之:人们需要知道规则,同时也要理解适用/不适用这些规则的上下文。 - pkozlowski.opensource
嘿,这是创建模态框的好方法。但是我也想在打开模态框时更改URL,以便当我在地址栏中输入该URL时,模态框将打开并显示所有内容。除了您的答案,我该如何实现这一点?有什么想法吗? - Dejan Bogatinovski
显示剩余2条评论

29

很有趣,因为我自己也在学习Angular,并且正在观看他们在Youtube上的一些视频。在这个视频中,演讲者在28:30分左右提到了你的确切问题。https://www.youtube.com/watch?v=ZhfUv0spHCY#t=1681

关键是将那段特定的代码放在服务中而不是控制器中。

我的猜测是将新的弹出窗口元素注入到DOM中并单独处理它们,而不是显示和隐藏相同的元素。这样,您可以拥有多个弹出窗口。

整个视频也非常有趣 :-)


2
Misko是Angular的种子!(哈哈)。但说真的,请把他的话视为Angular的权威来源。 - deck

14
  • 创建一个'popup'指令并将其应用于弹出内容的容器
  • 在指令中,将内容与遮罩层div一起包裹在绝对定位div中。
  • 可以从指令内部根据需要移动2个divs在DOM树中的位置。任何UI代码都可以放在指令中,包括将弹出窗口定位在屏幕中心的代码。
  • 创建并绑定一个布尔标志到控制器。这个标志将控制可见性。
  • 创建作用域变量来绑定到OK / Cancel函数等。

编辑添加一个高级别示例(非功能性)

<div id='popup1-content' popup='showPopup1'>
  ....
  ....
</div>


<div id='popup2-content' popup='showPopup2'>
  ....
  ....
</div>



.directive('popup', function() {
  var p = {
      link : function(scope, iElement, iAttrs){
           //code to wrap the div (iElement) with a abs pos div (parentDiv)
          // code to add a mask layer div behind 
          // if the parent is already there, then skip adding it again.
         //use jquery ui to make it dragable etc.
          scope.watch(showPopup, function(newVal, oldVal){
               if(newVal === true){
                   $(parentDiv).show();
                 } 
              else{
                 $(parentDiv).hide();
                }
          });
      }


   }
  return p;
});

$watch应该用于'watch'。在scope.watch(showPopup, function(newVal, oldVal){中,'showPopup'应该改为'popup'。 - Sangram Singh

14

1
我刚刚快速地进行了一个迭代,才认识到这种方法适合单个弹出窗口/模态框。然而,考虑以下特定的用户体验场景:当客户订购商品时,UI会呈现确认订单弹窗(因此我们已经“占用”了Adam的弹出窗口内容)。现在我们从该弹窗中点击发送或购买或其他操作,但出现错误需要用户在上一个屏幕中修改订单。我想将该错误显示在另一个顶级弹窗中。我不认为这种方法能够实现这一点。 - jusopi
3
没错,但我认为弹出窗口超过一个可能会导致用户界面不佳。 - Nik Dow
插件就是我一直在寻找的答案! - Andres Felipe

7

Angular-UI带有对话框指令。使用该指令并将templateurl设置为您想要包含的页面即可。这是最优雅的方法,我也在我的项目中使用了它。您可以根据需要传递其他几个对话框参数。


5
从 angular-bootstrap 0.6 版本开始,$dialog 已被 $modal 替换。这意味着您需要更改所有使用 $dialog 的代码,因为 $dialog 已被弃用,要将其改写为 $modal。 - Mohammad Umair Khan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接