角度嵌套表单验证setPristine on subForm->在parentForm上设置Pristine

angular nested form validation setPristine on subForm -> setPristine on parentForm

本文关键字:gt parentForm Pristine 设置 subForm- 嵌套 表单 验证 on setPristine      更新时间:2024-06-15

我有一个包含多个子表单的父表单(例如。http://jsfiddle.net/riemersebastian/9zr00ear/3/)

当用户更改任何字段时,相应的子窗体和父窗体都会使类ng变脏,以指示发生了更改。

我在每个子窗体上都有一个保存按钮(实际上它是一个链接),用于保存所有子窗体更改并调用子窗体$setPristine更新子窗体的状态。

然而,我希望父窗体在不再有脏子窗体时也注意到这一点,从而删除其脏类。

我想出了这个解决方案:http://jsfiddle.net/riemersebastian/9zr00ear/3/

正如您所看到的,我使用jQuery手动检查控制器是否有任何标记为脏的子窗体,如果没有,我将父窗体设置为原始。为此,我需要使用$timeout延迟jQuery,否则$setPristine的调用可能还没有更改DOM,因此父窗体将不会更新。

我想知道,有更好的方法吗?

这是代码:

var myApp = angular.module('myApp',[]);
myApp.controller('FirstCtrl', ['$scope', '$timeout', function($scope, $timeout) {          
    $scope.setFormPristine = function(subForm) {
        console.log(subForm);
        subForm.$setPristine();    
        $timeout(function() {
        if (!($('body').find(".subForm").is(".ng-dirty"))) {
           console.log("none is dirty, set main form pristine")
           $scope.form.$setPristine();
        }
        }, 10);
    }    
}]);
angular.bootstrap(document, ['myApp']);

<body>
    <div ng-controller="FirstCtrl">            
        <div>
            (outer) form is dirty? <b>{{ form.$dirty }}       </b>
        </div>
        <form name="form" ng-init="variants = [{duration:10, price:100}, {duration:30, price:200}]">
            <div>
                <div class="subForm" ng-repeat="variant in variants" ng-form="subForm">
                 <div>
                    <label>Duration:</label>                    
                    <input name="duration" ng-model="variant.duration"/>                    
                 </div>                  
                 <div>
                    <label>Price:</label>
                    <input name="price" ng-model="variant.price"/>                  
                </div>
                 <a href="" ng-click="setFormPristine(subForm)">Reset Form to pristine</a>
                 <div>
                    (inner) subform is dirty? <b>{{ subForm.$dirty }}           </b>
                 </div>
                  <br></br>
                </div>
            </div>            
        </form>        
    </div>        
</body>

ARG!把jquery拿出来!;)

我的第一个解决方案是指令和控制器api,让子表单将通知推送到主表单,一些伪代码:

    app.directice('mainForm', function($scope) {
    return {
        restrict: 'E',
        transclude: true,
        controllerAs: 'mainCtrl',
        controller: function($scope){
            this.publishState = function (childIsDirty) {
                if (!$scope.parentForm.$dirty && !childIsDirty)
                    $scope.parentForm.$setPristine();
                if (childIsDirty) {
                    $scope.parentForm.$setDirty();
                }
            }
        },
        templateUrl: 'parentForm.html'
    };
});
app.directice('subForm', function ($scope) {
    return {
        require: '^parentForm',
        restrict: 'A',
        transclude: true,
        controllerAs : 'viewModel',
        link: function (scope, element, attrs, parentForm) {
            console.log("Hey I am subForm!");
            scope.$watch('subForm1.$dirty', function(isDirty, wasDirty) {
                parentForm.publishState(isDirty);
            });
        },
        controller : function() {
            var viewModel = this;
            viewModel.myData = "Hello World";
        },
        templateUrl: 'subForm.html'
    };
});

有了html,你应该避免嵌套表单,这些表单被认为是糟糕的html表单(对不起,必须这样做),它们无论如何都不需要嵌套,因为所需的命令只会查看已注入的所有其他控制器。

<div>
    <parent-form></parent-form>
    <script type="text/ng-template" id="parentForm.html">
        <form name="parentForm">
            content
        </form>
        <form name="subForm1" sub-form></form>
    </script>
    <script type="text/ng-template" id="subForm.html">
        <div>
            <input type="text" name="myInput" ng-model="viewModel.myData" >
        </div>
    </script>
</div>

您还可以将main form方法传入作用域"&"如果你不想链接的话。

另一种方法是创建一个共享服务/工厂,用于发布更改,然后表单控制器将监视属性或将其方法注册到singleton工厂。