是否有处理“取消"的模式?在 AngularJS 模态对话框中? [英] Is there a pattern for dealing with "Cancel" in AngularJS modal dialogs?

查看:22
本文介绍了是否有处理“取消"的模式?在 AngularJS 模态对话框中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这不是关于用 AngularJS 显示模态对话框,该主题有很多问题和答案!

这个问题是关于如何在页面上的模态对话框中对 OK 和 Cancel 做出反应.假设您有一个只有一个变量的作用域:

$scope.description = "哦,我多么喜欢豪猪......"

如果我在页面上为您提供一个模态对话框并在该对话框中使用 ng-model="description",那么您所做的所有更改实际上都是在您键入时实时对描述本身进行的.这很糟糕,因为那你如何取消那个对话框?

有这个问题说要做我在下面解释的事情.接受的答案与我想出的解决方案"相同:AngularJS:数据绑定模式 - 仅在保存"时保存更改单击,或者如果取消"忘记更改被点击

如果单击调出模态的按钮返回到后面的函数并为模态创建相关数据的临时副本,然后弹出模态,我可以看到该怎么做.然后确定"(或保存"或其他)可以将临时值复制到实际模型值中.

main.js(摘录):

$scope.descriptionUncommitted = $scope.description;$scope.commitChanges = 函数 () {$scope.description = $scope.descriptionUncommitted;}

main.html(摘录):

<button ng-click="commitChanges()">保存</button>

问题在于它不是声明性的!事实上,它与其他任何地方的 AngularJS 都不一样.这几乎就像我们需要一个 ng-model-uncommitted="description" ,他们可以在其中进行他们想要的所有更改,但只有在我们用另一个声明触发时才会提交.某个插件中是否有这样的东西,或者是 AngularJS 本身添加了它?

似乎可以采用不同方式的示例.

main.js:

$scope.filename = "panorama.jpg";$scope.description = "山脉全景.";$scope.persist = function () {//一些用于访问后端服务的函数.};

main.html:

<input type="text" ng-model-uncommitted="filename"/><input type="text" ng-model-uncommitted="description"/><button ng-commit ng-click="persist()">保存</button><button ng-discard>取消</button></表单>

我在它周围贴了一个表单标签,因为我不知道你将如何对这些项目进行分组,所以很明显它都是同一个交易"的一部分(因为没有更好的词).但是需要通过某种方式使这一切都可以自动发生,并且模型变量的克隆副本用于初始值、用于输入和自动更新、验证等,然后最终丢弃或复制到相同的值最初用于在用户决定提交时创建它们.

这样的事情难道不是比控制器中的代码更容易为大型网站中的 20 个模态一遍又一遍地完成这项工作吗?还是我疯了?

解决方案

基本上,在 Angular 中,如果某些内容不是声明性的,您可以创建一个指令.

 .directive('shadow', function() {返回 {范围: {目标:'=阴影'},链接:功能(范围,EL,ATT){范围[att.shadow] = angular.copy(scope.target);scope.commit = function() {scope.target = scope[att.shadow];};}};

那么:

 

<输入 ng-model="数据"><button ng-click="commit()">保存</button>

所以shadow 指令中的data 将是原始datacopy.并且在点击按钮时会被复制回原处.

这里是工作示例:jsbin

除此示例外,我还没有对其进行测试,因此在其他情况下可能无法正常工作,但我认为它提供了可能性的概念.

另一个使用对象而不是字符串的示例,以及表单中的多个字段(此处需要额外的 angular.copy):jsbin

Edit2,角度版本 1.2.x

根据此更改,指令中的 input 不再访问隔离范围.一种替代方法是创建一个非隔离的子作用域 (scope:true),以保存数据的副本并访问父作用域以保存它.

所以对于更高版本的 angular,这是与之前相同的方法,稍作修改即可:

.directive('shadow', function() {返回 {范围:真实,链接:功能(范围,EL,ATT){范围[att.shadow] = angular.copy(范围[att.shadow]);scope.commit = function() {scope.$parent[att.shadow] = angular.copy(scope[att.shadow]);};}};});

示例:jsbin

请注意,使用 $parent 的问题在于,如果最终中间有另一个作用域,它可能会中断.

Note: This is not about showing a modal dialog with AngularJS, that topic has plenty of questions and answers!

This question is about how to react to both OK and Cancel within a modal dialog on a page. Let's say you've got a scope with just one variable in it:

$scope.description = "Oh, how I love porcupines..."

If I provide you with a modal dialog on the page and use ng-model="description" within that dialog, all of the changes you make are actually made in real time to the description itself as you type. That's bad, because then how do you cancel out of that dialog?

There's this question that says to do what I explain below. The accepted answer for it is the same "solution" I came up with: AngularJS: Data-bound modal - save changes only when "Save" is clicked, or forget changes if "Cancel" is clicked

I can see how to do it if clicking the button to bring up a modal goes back to a function in the back and that creates a temporary copy of the relevant data for the modal and then pops up the modal. Then "OK" (or "Save" or whatever) could copy the temporary values to the actual model values.

main.js (excerpt):

$scope.descriptionUncommitted = $scope.description;

$scope.commitChanges = function () {
  $scope.description = $scope.descriptionUncommitted;
}

main.html (excerpt):

<input type="text" ng-model="descriptionUncommitted"/>

<button ng-click="commitChanges()">Save</button>

The problem with that is it's not declarative! In fact, it's nothing like AngularJS anywhere else. It's almost as though we need an ng-model-uncommitted="description" where they could make all the changes they want but they only get committed when we trigger with another declaration. Is there such a thing in a plugin somewhere or is AngularJS itself adding it?

Edit: It seems that an example of a different way of doing it might be in order.

main.js:

$scope.filename = "panorama.jpg";
$scope.description = "A panorama of the mountains.";

$scope.persist = function () { // Some function to hit a back end service. };

main.html:

<form>
  <input type="text" ng-model-uncommitted="filename"/>
  <input type="text" ng-model-uncommitted="description"/>

  <button ng-commit ng-click="persist()">Save</button>
  <button ng-discard>Cancel</button>
</form>

I stuck a form tag around it because I don't know how you would group the items so it was clear it was all part of the same "transaction" (for lack of a better word). But there would need to be some way that this could all happen automatically and the cloned copies of the model variables are used for initial values, used for input and updated automatically, validated, etc. and then finally discarded or copied to the same value that initially was used to create them if the user decides to commit.

Isn't something like this easier than code in the controller to do that work over and over again for 20 modals in a big website? Or am I nuts?

解决方案

Basically, in angular if something is not declarative, you make a directive.

 .directive('shadow', function() {
  return {
    scope: {
      target: '=shadow'            
    },
    link: function(scope, el, att) {
      scope[att.shadow] = angular.copy(scope.target);

      scope.commit = function() {
        scope.target = scope[att.shadow];
      };
    }
  };

Then:

  <div shadow="data">
    <input ng-model="data">
    <button ng-click="commit()">save</button>
  </div>

So data inside the shadow directive will be a copy of the original data. And it will be copied back to the original when the button is clicked.

And here is working example: jsbin

I've not tested it beyond this example, so it may not work in other cases, but I think it gives an idea of the possibilites.

Edit:

Another example with an object instead of a string, and several fields in the form (an additional angular.copy is required here): jsbin

Edit2, angular versions 1.2.x

As per this change, the input inside the directive is not accessing the isolated scope anymore. One alternative is creating a non-isolated child scope (scope:true), to hold the copy of the data and accessing the parent scope for saving it.

So for later versions of angular, this is the same approach as before slightly modified to do the trick:

.directive('shadow', function() {
  return {
    scope: true,
    link: function(scope, el, att) {
      scope[att.shadow] = angular.copy(scope[att.shadow]);

      scope.commit = function() {
        scope.$parent[att.shadow] = angular.copy(scope[att.shadow]);
      };
    }
  };
});

Example: jsbin

Note that the problem with using $parent, is that it may break if eventually there is another scope in the middle.

这篇关于是否有处理“取消"的模式?在 AngularJS 模态对话框中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆