$ scope更新时如何更新ng-model?(单向数据绑定)

时间:2014-05-08 09:37:06

标签: javascript angularjs

我有两个表单,一个用于创建帐户,另一个用于登录。它们位于同一个控制器中,因为它们使用相同的功能登录。

问题是,一旦我在其中一个包装盒中写入了ng-model电子邮件,另一个就会得到更新。我不想要这个,我希望只将数据从模板传输到$ scope,而不是从$ scope传输到模板。

控制器:

.controller('auth', function($scope, simperiumUser){
    $scope.auth = function(method){
        simperiumUser.create(method, $scope.email, $scope.password);
    }
})

模板:

<div ng-controller="auth" class="popup">
    <div>
        <h3>Create account</h3>
        <form ng-submit="auth('create')">
            <input ng-model="email" type="email" required placeholder="Your e-mail">
            <input ng-model="password" type="password" required placeholder="Select a password">
            <input type="submit" value="Create">
        </form>
    </div>
    <div>
        <h3>Login</h3>
        <form ng-submit="auth('authorize')">
            <input ng-model="email" type="email" required placeholder="Your e-mail">
            <input ng-model="password" type="password" required placeholder="Your password">
            <input type="submit" value="Log in">
        </form>
    </div>
</div>

1 个答案:

答案 0 :(得分:0)

AngularJS没有内置任何东西来处理从视图到模型的单向数据绑定。

ngBind指令处理从模型到视图的单向数据绑定。

Bindonce非常好,但它不是用于设置数据绑定。它用于渲染数据一次,然后完全删除绑定。

从多个视图源到同一模型的单向数据绑定听起来像一个非常不寻常的情况,并可能导致一些奇怪的情况。至少在你计划使用的时候使用。

简单的演示指示:

app.directive("oneWay", function($parse) {

  return {
    compile: function compile(tElement, tAttrs) {

      var modelSetter = $parse(tAttrs.oneWay).assign;

      return function postLink(scope, element) {

        var onChange = function() {
          scope.$apply(function() {
            modelSetter(scope, element.val());
          });
        };

        element.on('keyup', onChange);

        scope.$on('$destroy', function() {
          element.off('keyup', onChange);
        });
      };
    }
  };
});

演示: http://plnkr.co/edit/tDNcszN0FD7i9mXYRwpz?p=preview

如果您输入第一个电子邮件输入,则范围中的模型将更改。如果您输入第二个电子邮件输入,则范围中的模型将再次更改,但之前的文本将保留在第一个输入中。如果您现在按&#39;创建&#39;在第一个输入旁边,它将使用在第二个输入中键入的值调用该函数。不是用户期望的假设。

当然有办法解决这个问题。但代码会增长。该指令现在仅使用keyup事件,并且不考虑任何HTML5验证行为,如ngModel那样。

代码可能会增长得更多,最终可能不值得。

我建议坚持使用ngModel,使用两个不同的对象,并将电子邮件和密码直接传递给auth函数:

HTML:

  <form ng-submit="auth('create', create.email, create.password)">
    <input ng-model="create.email">
    <input ng-model="create.password" type="password">

  (...)

  <form ng-submit="auth('authorize', login.email, login.password)">
    <input ng-model="login.email">
    <input ng-model="login.password" type="password">

JS:

$scope.create =
{
  email: '',
  password: ''
};

$scope.login =
{
  email: '',
  password: ''
};  

$scope.auth = function(method, email, password) {
  simperiumUser.create(method, email, password);
}

演示: http://plnkr.co/edit/VsgU8k3LYzzq7gpw6JwN?p=preview

甚至可以从控制器中删除$scope.create / $scope.login个对象,ngModel使用的$parse服务将为您创建它们。但为了清楚起见,我保留了它们。