AngularJS - 服务器端验证和客户端表单

Dom*_*mra 56 json angularjs

我想了解如何做以下事情:

声明表单的可接受方式是什么.我的理解是你只是在HTML中声明表单,并添加如下所示的ng-model指令:

ng-model="item.name"
Run Code Online (Sandbox Code Playgroud)

要发送到服务器的内容.我可以将项目对象作为JSON发送到服务器,并解释它.然后我可以对对象执行验证.如果失败了,我会抛出一个JSON错误,然后发回确切的内容?这是否有可接受的方式?如何以一种很好的方式将验证错误从服务器推送到客户端?

我真的需要一个例子,但Angulars文档很难理解.

编辑:看来我的问题很糟糕.

我知道如何验证客户端,以及如何处理错误/成功作为承诺回调.我想知道的是将SERVER端错误消息捆绑到客户端的可接受方式.假设我有一个用户名和密码注册表单.我不想在服务器上轮询用户名,然后使用Angular来确定是否存在重复.我想将用户名发送到服务器,验证没有其他帐户存在同名,然后提交表单.如果发生错误,我该如何发回?

如何将数据按原样(键和值)推送到服务器,并附加一个错误字段,如下所示:

{
  ...data...

  "errors": [
    {
      "context": null,
      "message": "A detailed error message.",
      "exceptionName": null
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

然后绑定到DOM.

Der*_*ins 64

我最近也一直在玩这种东西,我已经敲了这个演示.我认为它能满足您的需求.

使用您要使用的任何特定客户端验证,按照正常方式设置表单:

<div ng-controller="MyCtrl">
    <form name="myForm" onsubmit="return false;">
        <div>
            <input type="text" placeholder="First name" name="firstName" ng-model="firstName" required="true" />
            <span ng-show="myForm.firstName.$dirty && myForm.firstName.$error.required">You must enter a value here</span>
            <span ng-show="myForm.firstName.$error.serverMessage">{{myForm.firstName.$error.serverMessage}}</span>
        </div>
        <div>
            <input type="text" placeholder="Last name" name="lastName" ng-model="lastName"/>
            <span ng-show="myForm.lastName.$error.serverMessage">{{myForm.lastName.$error.serverMessage}}</span>
        </div>
        <button ng-click="submit()">Submit</button>
    </form>
</div>
Run Code Online (Sandbox Code Playgroud)

另请注意,我serverMessage为每个字段添加了一个:

<span ng-show="myForm.firstName.$error.serverMessage">{{myForm.firstName.$error.serverMessage}}</span>
Run Code Online (Sandbox Code Playgroud)

这是一个可自定义的消息,从服务器返回,它的工作方式与任何其他错误消息相同(据我所知).

这是控制器:

function MyCtrl($scope, $parse) {
      var pretendThisIsOnTheServerAndCalledViaAjax = function(){
          var fieldState = {firstName: 'VALID', lastName: 'VALID'};
          var allowedNames = ['Bob', 'Jill', 'Murray', 'Sally'];

          if (allowedNames.indexOf($scope.firstName) == -1) fieldState.firstName = 'Allowed values are: ' + allowedNames.join(',');
          if ($scope.lastName == $scope.firstName) fieldState.lastName = 'Your last name must be different from your first name';

          return fieldState;
      };
      $scope.submit = function(){
          var serverResponse = pretendThisIsOnTheServerAndCalledViaAjax();

          for (var fieldName in serverResponse) {
              var message = serverResponse[fieldName];
              var serverMessage = $parse('myForm.'+fieldName+'.$error.serverMessage');

              if (message == 'VALID') {
                  $scope.myForm.$setValidity(fieldName, true, $scope.myForm);
                  serverMessage.assign($scope, undefined);
              }
              else {
                  $scope.myForm.$setValidity(fieldName, false, $scope.myForm);
                  serverMessage.assign($scope, serverResponse[fieldName]);
              }
          }
      };
}
Run Code Online (Sandbox Code Playgroud)

我假装调用服务器pretendThisIsOnTheServerAndCalledViaAjax你可以用ajax调用替换它,关键是它只返回每个字段的验证状态.在这个简单的例子中,我使用值VALID来指示该字段是有效的,任何其他值都被视为错误消息.你可能想要更复杂的东西!

从服务器获得验证状态后,您只需更新表单中的状态即可.

您可以从范围访问表单,在这种情况下,将调用表单,myForm以便$ scope.myForm为您提供表单.(如果您想了解它是如何工作的话,表单控制器的来源就在这里).

然后,您想告诉表单该字段是否有效/无效:

$scope.myForm.$setValidity(fieldName, true, $scope.myForm);
Run Code Online (Sandbox Code Playgroud)

要么

$scope.myForm.$setValidity(fieldName, false, $scope.myForm);
Run Code Online (Sandbox Code Playgroud)

我们还需要设置错误消息.首先使用$ parse获取该字段的访问者.然后从服务器分配值.

var serverMessage = $parse('myForm.'+fieldName+'.$error.serverMessage');
serverMessage.assign($scope, serverResponse[fieldName]);
Run Code Online (Sandbox Code Playgroud)

希望有所帮助

  • 您可以使用ng-submit代替ng-click和onsubmit变通方法. (2认同)
  • JustAMartin,这只是一些示例代码而不是完整的实现.您需要自己进一步实施.随意发布您的附加答案. (2认同)
  • 使用`$ scope.myForm.$ setValidity(fieldName,false/true,$ scope.myForm)`不会在'true/false`状态下设置`$ scope.myForm.fieldName.$ invalid`(只有表单将是).要解决这个问题,你必须设置字段`$ scope.myForm [fieldName].$ setValidity(fieldName,true/false);`. (2认同)

Jan*_*ski 17

我有与Derek类似的解决方案,在codetunes博客有所描述.TL; DR:

  • 以与Derek解决方案类似的方式显示错误:

    <span ng-show="myForm.fieldName.$error.server">{{errors.fieldName}}</span>
    
    Run Code Online (Sandbox Code Playgroud)

  • 添加指令,用于在用户更改输入时清除错误:

    <input type="text" name="fieldName" ng-model="model.fieldName" server-error />
    
    angular.module('app').directive 'serverError', ->
      {
        restrict: 'A'
        require: '?ngModel'
        link: (scope, element, attrs, ctrl) ->
          element.on 'change', ->
            scope.$apply ->
              ctrl.$setValidity('server', true)
      }
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过将错误消息传递给作用域并告知该表单有错误来处理错误:

    errorCallback = (result) ->
      # server will return something like:
      # { errors: { name: ["Must be unique"] } }
      angular.forEach result.data.errors, (errors, field) ->
        # tell the form that field is invalid
        $scope.form[field].$setValidity('server', false)
        # keep the error messages from the server
        $scope.errors[field] = errors.join(', ') 
    
    Run Code Online (Sandbox Code Playgroud)

希望它会有用:)

  • 这对angular-1.3 / 1.4有用吗?$ scope.form的值似乎是未定义的,即使表单已被命名,并且当我尝试使用表单或表单名称访问时,我也看到它是未定义的。 (2认同)

Yos*_*osh 5

好吧,Derek Ekins给出的答案是非常好的工作.但是:如果禁用提交按钮ng-disabled="myForm.$invalid"- 按钮将不会自动返回启用状态,因为基于服务器的错误状态似乎没有更改.即使您再次编辑表单中的所有字段以符合有效输入(基于客户端验证)也不会.

  • 如果您希望能够禁用提交按钮,则需要在输入更改时触发验证,否则无法知道它是否有效.如果你真的想要,我可以举一个例子. (3认同)