AngularJS - 保存验证和 Creating/Publishing

AngularJS - Validation for Saving and Creating/Publishing

我们正在开发一个网站,让产品经理可以保存和创建产品。

保存对已输入的任何数据进行一些基本验证。 create/publish 具有所有验证,包括所需的数据检查。

有没有什么好的方法可以对一个表单进行两种不同类型的验证?

以下是我尝试过的几种方法:

ng-需要

<input type="text" name="planName" ng-model="vm.product.planName" ng-required="vm.publishAttempt" />

我们的保存将表单标记为原始状态。

    function saveSuccess()
    {
        vm.editForm.$setPristine();
        vm.publishAttempt = false;
        vm.isLoading = false;
    }

这使得带有 ng-required 的表单输入在单击发布按钮时不会被触发以进行验证,并且设置了一个真值来验证它们。我见过的唯一解决方案是遍历表单元素并将它们标记为脏。不过这似乎是错误的方法。

    function publish()
    {
        vm.isLoading = true;
        vm.publishAttempt = true;

        angular.forEach(vm.editForm, function (field)
        {
            if (field && field.$pristine != null)
            {
                console.log(field);
                field.$setDirty();
            }
        });

        setTimeout(function()
        {
            if (vm.editForm.$invalid)
            {
                vm.isLoading = false;
                logger.error('Required data is missing. Please check the form and try again.');
            }
            else
            {
                if ($window.confirm('Are you sure you want to publish this product? Doing so will make this product available to everyone and any changes going forward will be considered corrections to the product. '))
                {
                    productService.publishProduct($routeParams.productId)
                        .then(publishSuccess, publishFail);
                }
                else
                {
                    vm.isLoading = false;
                    vm.publishAttempt = false;
                }
            }
        }, 1000);
    }

后端验证使用 fluentvalidation

我们还使用 FluentValidation 进行后端验证。我试过返回这些结果,但随后必须遍历所有结果并在表单上找到值并将其标记为无效。

    function publishSuccess(result)
    {
        if (!result.IsValid)
        {
            angular.forEach(result.errors, function(error)
            {
                // Map error back to input and set invalid.  
            });        
        }
        else
        {
            openDetail($routeParams.productId);
        }
        vm.isLoading = false;
    }

默认使用 jQuery 作为解决方案是非常诱人的,但必须有一种 AngularJS 的方式,我只是想念它。

我是 Angular 的新手,我是否遗漏了什么明显的东西?

我将 vm.publishAttempt 添加到我的编辑控制器上的视图模型并将其设置为 false。

function Edit(productService, logger, $routeParams, $location, $timeout, $modal, ...)
{
    var vm = this;
    vm.publishAttempt = false;
    vm.save = save;
    vm.publish = publish;
    // ...

在视图中,我将 ng-required 属性放在发布所需的所有输入上。

ng-required="vm.publishAttempt"

保存时,我将 publishAttempt 设置为 false,以便从视图中清除所有特定于发布的错误。保存成功后,表单将设置回原始状态。

    function save()
    {
        vm.publishAttempt = false;

        $timeout(function()
        {
            if (vm.editForm.$invalid)
            {
                vm.isLoading = false;
                logger.error('Required data is missing. Please check the form and try again.');
            }
            else
            {
                productService
                    .saveProduct(vm.product)
                    .$promise
                    .then(saveSuccess, saveFail);
            }
        }, 500);
    }

    function saveSuccess()
    {
        vm.editForm.$setPristine();
        vm.publishAttempt = false;
    }

    function saveFail(error)
    {
        // Display errors
    }

在发布时,我将 publishAttempt 标记为 true,然后使所有表单输入变脏以显示错误。然后我们检查表单是否无效。如果是,我们通过向浏览器发送记录器消息让用户知道。

    function publish()
    {
        vm.publishAttempt = true;

        setAllInputsDirty(vm.editForm);

        $timeout(function()
        {
            if (vm.editForm.$invalid)
            {
                logger.error('Required data is missing. Please check the form and try again.');
            }
            else
            {
                if ($window.confirm('Are you sure ... ?'))
                {
                    productService.publishProduct($routeParams.productId)
                        .then(publishSuccess, publishFail);
                }
                else
                {
                    vm.publishAttempt = false;
                }
            }
        }, 500);
    }

    function publishSuccess(result)
    {
        // If there are errors display them. 
        // This shouldn't happen because the front end validation should find these first.
        // These are the server side errors from FluentValidation
        if (!result.IsValid)
        {
            $modal.open({
                templateUrl: '/app/edit/server-errors.html',
                controller: 'ServerErrors',
                controllerAs: 'vm',
                size: 'lg',
                resolve: {
                    errors: function ()
                    {
                        return result.errors;
                    }
                }
            });

            return;
        }

        openDetail($routeParams.productId);
        logger.info('Product successfully published.');
        vm.isLoading = false;
    }

    function publishFail(error)
    {
        vm.isLoading = false;
        logger.error('Publish failed', error);
    }

这是用于使所有输入变脏以便使条件验证适用于发布的方法。这是下面评论中 URL 的副本。

    // http://blog.pixelastic.com/2014/09/10/setting-all-inputs-as-$dirty-in-angularjs-1.2/
    function setAllInputsDirty(form)
    {
        _.each(form, function (value, key)
        {
            // We skip non-form and non-inputs
            if (!value || value.$dirty === undefined)
            {
                return;
            }

            // Recursively applying same method on all forms included in the form
            if (value.$addControl)
            {
                return setAllInputsDirty(value);
            }

            return value.$setDirty();
        });
    }
}