将视图的脏状态传播到包含的表单

时间:2015-08-14 17:55:28

标签: javascript html angularjs controller

我有一个带有以下标记的主表单

 <tabset vertical="true" type="pills">
                                    <tab ng-repeat="tab in tabsViews" select="selectView(tab.name, tab.index)"
                                         ng-show="tab.isVisible"
                                         class=" {{tabsViews[tab.index-1]['invalid'] ? 'invalid-tab': 'valid-tab' }}">
                                        <tab-heading>{{tab.title}}</tab-heading>
                                    </tab>
                                </tabset>

并且我的控制器中的selectView方法如下:

$scope.previousIndex = null;

            $scope.selectView = function (viewName, viewIndex) {
                $scope.selections.showInvoicesDetailView = false;
                $scope.selections.showInvoicesView = false;
                $scope.selections.showPassesView = false;
                if (viewIndex) {

                    if ($scope.previousIndex != null && $scope.form) {
                        $scope.tabsViews[$scope.previousIndex - 1]["invalid"] = $scope.form.$invalid;
                    }

                    $scope.previousIndex = viewIndex;
                }

                if (viewName.substring(0, 9) != 'invoices.')
                    $scope.selections.lastSelectedView = viewName;
                else
                    $scope.selections.showInvoicesDetailView = true;

                if (viewName == 'guestPasses')
                    $scope.selections.showPassesView = true;

                if (viewName == 'invoices')
                    $scope.selections.showInvoicesView = true;

                if ($scope.selections.isNew) {
                    window.console && console.log('SelectView called with the new.' + viewName + ' view...');
                    $state.go('new.' + viewName);
                }
                else {
                    window.console && console.log('SelectView called with the edit.' + viewName + ' view...');
                    $state.go('edit.' + viewName);
                }
            };

主窗体有一个指令来检测其脏状态并要求保存更改。问题是,当我在当前视图中更改任何内容时,该窗体的脏状态不会传播到该主窗体中。有没有办法根据特定的选项卡(定义为视图)脏状态设置主窗体脏状态?

为了更好地理解这个问题,这里是主要的表单标记(带标签的标记):

div ng-class="{'col-md-7': $parent.showSearch, 'col-md-11': !$parent.showSearch}">
    @Html.Partial("_EditFormHeader")
    <div class="fourpanel">
        <div data-sm:collapse="$parent.showForm" id="hideFrm" class="pull-left col-sm-3 sm-search-list">
            <form name="guestMainForm" novalidate role="form" data-sm:dirty-check data-server:error
                  ng-show="$parent.showForm && !selections.justDeleted" class="ng-cloak">
                <div id="guestEditForm" class="widget" data-resize:container>
                    <div class="widget-head">
                        <div class="row">
                            <div class="clearfix"></div>
                            @Labels.guest: {{currentGuest.contactPerson.firstName + ' ' + currentGuest.contactPerson.lastName}} {{ !isNew ? '(' + currentGuest.guestNo + ')' : '' }}
                            <div class="pull-right text-right col-lg-1" style="padding-right:5px">
                                <i class="fa fa-angle-double-left sm-slider-button" ng-click="toggleFormVisibility()"
                                   alt="@String.Format(Labels.hideX, Labels.account)" id="angle-left"></i>
                            </div>
                        </div>
                    </div>
                    <div class="widget-content">
                        <div class="scrollable widget-resize">
                            <div class="padd">
                                @Html.Partial("_EditFormAlerts")
                            </div>
                            <div class="col-lg-2 col-md-2 panel-container">
                                <tabset vertical="true" type="pills">
                                    <tab ng-repeat="tab in tabsViews" select="selectView(tab.name, tab.index)"
                                         ng-show="tab.isVisible"
                                         class=" {{tabsViews[tab.index-1]['invalid'] ? 'invalid-tab': 'valid-tab' }}">
                                        <tab-heading>{{tab.title}}</tab-heading>
                                    </tab>
                                </tabset>
                            </div>

                            <div class="col-lg-8 col-md-4 panel-container">
                                <div data-ui-view data-autoscroll="false"></div>
                                <div data-ui-view="guestPasses" ng-show="selections.showPassesView"></div>
                                <div data-ui-view="invoices" data-autoscroll="false" ng-show="selections.showInvoicesView"></div>
                            </div>
                        </div>
                    </div>

                    <div class="widget-foot">
                        <div ng-show="!isNew">
                            <button class="btn btn-primary" ng-click="save(currentGuest)"
                                    ng-disabled="form.$invalid || disableAction">
                                @Labels.save
                            </button>
                            <data-delete:button title="{{ '@Labels.delete: ' + currentGuest.contactPerson.firstName.trim() + ' ' + currentGuest.contactPerson.lastName.trim() + ' (' + currentGuest.guestNo +')' }}"
                                                message="@String.Format(Messages.confirmDelete, Labels.guest)"
                                                disable-action="disableAction"
                                                delete="delete()">
                            </data-delete:button>
                            <data-cancel:button title="@Labels.unsavedChanges"
                                                message="@Messages.unsavedChanges"
                                                cancel="cancel()"
                                                disable-action="disableAction"
                                                dirty="form.$dirty">
                            </data-cancel:button>
                        </div>
                        <div ng-show="isNew">
                            <button id="btnAdd" class="btn btn-primary" ng-click="new(currentGuest)"
                                    ng-disabled="form.$invalid || disableAction">
                                @Labels.add
                                </button>
                                <data-cancel:button title="@Labels.unsavedChanges"
                                                    message="@Messages.unsavedChanges"
                                                    cancel="cancel()"
                                                    disable-action="disableAction"
                                                    dirty="form.$dirty">
                                </data-cancel:button>
                            </div>
                        </div>
                    </div>
                </form>
        </div>
        <div id="showFrm" class="sm-form-expand-button text-center col-sm-1"
             ng-show="!$parent.showForm"
             ng-click="toggleFormVisibility()">
            <i class="fa fa-angle-double-right"></i>
            <div class="panel2Label">@Labels.guest: {{ currentGuest.contact.firstName.trim() + ' ' + currentGuest.contact.lastName.trim() }} {{ !isNew ? '(' + currentGuest.guestNo + ')' : '' }}</div>
        </div>

        <div class="col-sm-5 panel-container">
            <div data-ui-view="detail" data-autoscroll="true" ng-show="selections.showInvoicesDetailView"></div>
            <div data-ui-view="passDetail"></div>
        </div>
    </div>
</div>

我创建了一个新指令并将其添加到我的视图表单中:

function ($modal, $rootScope, $location, $state) {
            return {
                restrict: 'A',
                require: ['^form'],
                //scope: {
                //    onOk: '&',
                //    onCancel: '&'
                //},
                link: function (scope, element, attrs, controllers) {

                    var form = controllers[0];

                    window.console && console.log(form);

                    window.onbeforeunload = function () {
                        if ((form && form.$dirty) || element.hasClass('ng-dirty')) {
                            //         return resourceFactory.getResource('Messages', 'unsavedChanges');

                            if (scope.form)
                            {
                                scope.form.$setDirty();
                            }
                        }
                    };
                   
                }
            };

我正在调试,我可以看到该表单已正确设置为我的视图表单,我可以使用表单访问父表单。$$ parentForm属性。但是,我不知道应该挂钩哪个事件来设置表单。$$ parentForm。$ setDirty当我的表单变脏时。如果你可以帮我解决这个问题,那我觉得它对我有用。

1 个答案:

答案 0 :(得分:1)

引用来自表单指令的Angular文档:

  

在Angular中,表格可以嵌套。这意味着当所有子表单都有效时,外部表单也是有效的。但是,浏览器不允许嵌套元素,因此Angular提供的ngForm指令行为相同但可以嵌套。这允许您使用嵌套表单,这在使用ngRepeat指令动态生成的表单中使用Angular验证指令时非常有用。由于无法使用插值动态生成输入元素的name属性,因此必须在ngForm指令中包装每组重复输入,并将它们嵌套在外部表单元素中。

也许这也适用于$dirty州,因此如果子表单为$dirty,则父表单也将为$dirty。我不确定在你的情况下你是否能够嵌套表格。我没有足够的背景来想象你想要达到的目标。

或者,当其中一个表单变脏时,您可以手动将主表单设置为脏。因为您添加了主表单中的代码,所以我可以看到您没有使用内置的脏检查器。也许你有充分的理由,但也许你并不知道它的存在。那么你必须使用angular form指令。 FormController具有以下方法:$setDirty();

FormController documentation

Form Directive documentation