简体   繁体   English

将视图的脏状态传播到包含窗体

[英]Propagating view's dirty state to the containing form

I have a main form with the following markup 我有一个带有以下标记的主表格

  <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> 

and the selectView method in my controller is the following: 我的控制器中的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); } }; 

The main form has a directive to detect its dirty state and ask for saving the changes. 主窗体具有一条指令,用于检测其脏状态并请求保存更改。 The problem is that when I change anything in my current view, that form's dirty state is not propagated into that main form. 问题是,当我在当前视图中更改任何内容时,该表单的脏状态不会传播到该主表单中。 Is there a way to set main form dirty state based on the particular tab (defined as the view) dirty state? 有没有一种方法可以基于特定选项卡(定义为视图)的脏状态来设置主窗体的脏状态?

To understand the problem better, here is the main form markup (the one that has tabs): 为了更好地理解该问题,这是主要的表单标记(带有标签的表单):

 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> 

I created a new directive and added it to my view forms: 我创建了一个新指令并将其添加到我的视图表单中:

 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(); } } }; } }; 

I am debugging and I can see that form is correctly set to my view's form and I can access the parent form using form.$$parentForm property. 我正在调试,可以看到该表单已正确设置为视图的表单,并且可以使用form。$$ parentForm属性访问父表单。 However, I don't know to which event should I hook to set form.$$parentForm.$setDirty when my form becomes dirty. 但是,我不知道当我的表单变脏时应该挂接到哪个事件来设置form。$$ parentForm。$ setDirty。 If you can help me figure this out, then it will work for me, I guess. 我想,如果您能帮助我解决这个问题,那么它将对我有用。

Quote from Angular documentation on the form directive: 引用Angular文档中的form指令:

In Angular, forms can be nested. 在Angular中,表单可以嵌套。 This means that the outer form is valid when all of the child forms are valid as well. 这意味着外部形式在所有子形式都有效时也有效。 However, browsers do not allow nesting of elements, so Angular provides the ngForm directive which behaves identically to but can be nested. 但是,浏览器不允许嵌套元素,因此Angular提供了ngForm指令,该指令的行为与之相同,但可以嵌套。 This allows you to have nested forms, which is very useful when using Angular validation directives in forms that are dynamically generated using the ngRepeat directive. 这使您可以拥有嵌套的表单,这在使用ngRepeat伪指令动态生成的表单中使用Angular验证伪指令时非常有用。 Since you cannot dynamically generate the name attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an ngForm directive and nest these in an outer form element. 由于无法使用插值动态生成输入元素的名称属性,因此必须将每组重复的输入包装在ngForm指令中,并将它们嵌套在外部表单元素中。

Maybe this also works for the $dirty state so that if a child form is $dirty the parent form will also be $dirty . 也许这也适用于$dirty状态,因此,如果子窗体为$dirty则父窗体也将为$dirty I'm not sure that in your case you'll be able to nest the forms. 我不确定您是否可以嵌套表格。 I don't have enough context to visualise what you want to achieve. 我没有足够的上下文来可视化您想要实现的目标。

Alternatively, you can manually set the main form to dirty when one of those other forms becomes dirty. 或者,您可以在其他表单之一变脏时手动将主表单设置为肮脏。 Because you added the code from your main form, I can see you're not using the built in dirty checker from angular. 因为您是从主窗体中添加代码的,所以可以看到您没有使用angular内置的脏检查器。 Maybe you have a good reason for this, but perhaps you didn't know of it's existence. 也许您对此有充分的理由,但也许您不知道它的存在。 You'll have to use the angular form directive then. 然后,您必须使用角度形式指令。 The FormController has the following method: $setDirty(); FormController具有以下方法: $setDirty(); .

FormController documentation FormController文档

Form Directive documentation 表单指令文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM