传播观点的脏状态对包含窗体 [英] Propagating view's dirty state to the containing form

查看:264
本文介绍了传播观点的脏状态对包含窗体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下面的标记一种主要形式

\r
\r

<标签集垂直=真正的TYPE =药丸>\r
                                    <标签NG重复=,在tabsViews标签,选择=选择查看(tab.name,tab.index)\r
                                         NG-秀=tab.isVisible\r
                                         类={{tabsViews [tab.index-1] ['无效']'无效的标签:有效的标签'}}>\r
                                        <标签,标题为GT; {{tab.tit​​le}}< /制表标题>\r
                                    < /标签>\r
                                < /标签集>

\r

\r
\r

在我的控制器中选择查看方法如下:

\r
\r

$范围previousIndex = NULL。\r
\r
            $ scope.selectView =功能(的viewName,viewIndex){\r
                $ scope.selections.showInvoicesDetailView = FALSE;\r
                $ scope.selections.showInvoicesView = FALSE;\r
                $ scope.selections.showPassesView = FALSE;\r
                如果(viewIndex){\r
\r
                    如果($范围previousIndex = NULL&放大器;!&安培; $ scope.form){\r
                        $ scope.tabsViews [$范围previousIndex - 1] [无效] = $ scope.form $无效。\r
                    }\r
\r
                    $范围previousIndex = viewIndex。\r
                }\r
\r
                如果(viewName.substring(0,9)!='发票。')\r
                    $ scope.selections.lastSelectedView =的viewName;\r
                其他\r
                    $ scope.selections.showInvoicesDetailView =真;\r
\r
                如果(的viewName =='guestPasses')\r
                    $ scope.selections.showPassesView =真;\r
\r
                如果(的viewName =='发票')\r
                    $ scope.selections.showInvoicesView =真;\r
\r
                如果($ scope.selections.isNew){\r
                    window.console&功放;&安培;的console.log('叫选择查看新。'+的viewName +'查看...');\r
                    $ state.go('新'+的viewName);\r
                }\r
                其他{\r
                    window.console&功放;&安培;的console.log('叫选择查看与编辑。'+的viewName +'查看...');\r
                    $ state.go(修改。+的viewName);\r
                }\r
            };

\r

\r
\r

主要形式有一个指令来检测其脏状态,并要求保存更改。问题是,当我在当前视图改变什么,这种形式的肮脏的状态不会传播到该主要形式。有没有一种方法来设置基于特定标签上的主要形式脏状态(定义为视图)脏状态?

要理解这个问题比较好,这里是主要形式的标记(有选项卡中的一个):

\r
\r

DIV纳克级={'COL-MD-7:$父.showSearch,COL-MD-11':$ parent.showSearch}>!\r
    @ Html.Partial(_ EditFormHeader)\r
    < D​​IV CLASS =fourpanel>\r
        < D​​IV数据-SM崩溃=$ parent.showFormID =hideFrm级=拉左COL-SM-3 SM-搜索列表>\r
            <表格名称=guestMainFormNOVALIDATE角色=形式数据-SM:脏检查数据服务器:错误\r
                  NG-秀=$ parent.showForm&放大器;&安培;!selections.justDeleted级=NG-斗篷>\r
                < D​​IV ID =guestEditForm级=小部件数据调整大小:集装箱>\r
                    < D​​IV CLASS =小工具头>\r
                        < D​​IV CLASS =行>\r
                            < D​​IV CLASS =clearfix>< / DIV>\r
                            @ Labels.guest:{{currentGuest.contactPerson.firstName +''+ currentGuest.contactPerson.lastName}} {{是否新款!? '('+ currentGuest.guestNo +')':''}}\r
                            < D​​IV CLASS =右拉文本右COL-LG-1的风格=填充右:5像素>\r
                                < I类=发发角双左SM-滑块键NG点击=toggleFormVisibility()\r
                                   ALT =@的String.Format(Labels.hideX,Labels.account)ID =角左>< / I>\r
                            < / DIV>\r
                        < / DIV>\r
                    < / DIV>\r
                    < D​​IV CLASS =插件内容>\r
                        < D​​IV CLASS =滚动部件调整大小>\r
                            < D​​IV CLASS =PADD>\r
                                @ Html.Partial(_ EditFormAlerts)\r
                            < / DIV>\r
                            < D​​IV CLASS =COL-LG-2 COL-MD-2面板容器>\r
                                <标签集垂直=真正的TYPE =药丸>\r
                                    <标签NG重复=,在tabsViews标签,选择=选择查看(tab.name,tab.index)\r
                                         NG-秀=tab.isVisible\r
                                         类={{tabsViews [tab.index-1] ['无效']'无效的标签:有效的标签'}}>\r
                                        <标签,标题为GT; {{tab.tit​​le}}< /制表标题>\r
                                    < /标签>\r
                                < /标签集>\r
                            < / DIV>\r
\r
                            < D​​IV CLASS =COL-LG-8 COL-MD-4面板容器>\r
                                < D​​IV数据的用户界面视图数据自动滚屏=false的>< / DIV>\r
                                < D​​IV数据的用户界面视图=guestPassesNG-秀=selections.showPassesView>< / DIV>\r
                                < D​​IV数据的用户界面视图=发票数据自动滚屏=false的NG-秀=selections.showInvoicesView>< / DIV>\r
                            < / DIV>\r
                        < / DIV>\r
                    < / DIV>\r
\r
                    < D​​IV CLASS =小工具尺&​​GT;\r
                        < D​​IV NG秀=是否新款!>\r
                            <按钮类=BTN BTN-主要NG点击=保存(currentGuest)\r
                                    NG-禁用=$形式无效|| disableAction。>\r
                                @ Labels.save\r
                            < /按钮>\r
                            <数据 - 删除:按钮标题={{'@ Labels.delete:'+ currentGuest.contactPerson.firstName.trim()+''+ currentGuest.contactPerson.lastName.trim()+'('+ currentGuest.guestNo +')'}}\r
                                                消息=@的String.Format(Messages.confirmDelete,Labels.guest)\r
                                                禁用行动=disableAction\r
                                                删除=删除()>\r
                            < /数据删除:按钮>\r
                            <数据 - 取消:按钮名称=@ Labels.unsavedChanges\r
                                                消息=@ Messages.unsavedChanges\r
                                                取消=取消()\r
                                                禁用行动=disableAction\r
                                                脏=形式为$脏了。>\r
                            < /数据取消:按钮>\r
                        < / DIV>\r
                        < D​​IV NG秀=是否新款>\r
                            <按钮ID =btnAdd级=BTN BTN-主要NG点击=新的(currentGuest)\r
                                    NG-禁用=$形式无效|| disableAction。>\r
                                @ Labels.add\r
                                < /按钮>\r
                                <数据 - 取消:按钮名称=@ Labels.unsavedChanges\r
                                                    消息=@ Messages.unsavedChanges\r
                                                    取消=取消()\r
                                                    禁用行动=disableAction\r
                                                    脏=形式为$脏了。>\r
                                < /数据取消:按钮>\r
                            < / DIV>\r
                        < / DIV>\r
                    < / DIV>\r
                < /表及GT;\r
        < / DIV>\r
        < D​​IV ID =showFrm级=SM-表单展开按钮文本中心COL-SM-1\r
             NG-秀=!$ parent.showForm\r
             NG-点击=toggleFormVisibility()>\r
            < I类=发发角双右>< / I>\r
            &所述;股利类=panel2Label> @ Labels.guest:{{currentGuest.contact.firstName.trim()+''+ currentGuest.contact.lastName.trim()}} {{是否新款!? '('+ currentGuest.guestNo +')':''}}< / DIV>\r
        < / DIV>\r
\r
        < D​​IV CLASS =COL-SM-5面板容器>\r
            < D​​IV数据的用户界面视图=细节的数据自动滚屏=真正的NG-秀=selections.showInvoicesDetailView>< / DIV>\r
            < D​​IV数据的用户界面视图=passDetail>< / DIV>\r
        < / DIV>\r
    < / DIV>\r
< / DIV>

\r

\r
\r

我创建了一个新的指令,并把它添加到我的观点的形式:

\r
\r

函数($模式,$ rootScope,$位置$州){\r
            返回{\r
                限制:'A',\r
                要求:['^形式'],\r
                //范围: {\r
                //的OnOK:'和;,\r
                // onCancel:'和;'\r
                //},\r
                链接:功能(范围,元素,ATTRS,控制器){\r
\r
                    变种形式=控制器[0];\r
\r
                    window.console&功放;&安培;的console.log(表);\r
\r
                    window.onbeforeunload =功能(){\r
                        如果((形式为安培;&安培;形式$脏)|| element.hasClass('NG-脏')){\r
                            //返回resourceFactory.getResource('消息','unsavedChanges');\r
\r
                            如果(scope.form)\r
                            {\r
                                scope.form $使用setDirty()。\r
                            }\r
                        }\r
                    };\r
                   \r
                }\r
            };

\r

\r
\r

我调试,我可以看到这种形式是正确设置为我的观点的形式,我可以使用的形式访问父窗体。$$ parentForm财产。但是,我不知道我应该钩设置形式的事件。$$ parentForm。$使用setDirty当我的形式变脏。如果你能帮助我想出解决办法,那么它会为我工作,我猜。


解决方案

从引用文档角上的表格指令:


  

在棱角分明,形式可以嵌套。这意味着,外形式是有效的,当所有的子形式是有效的,以及。然而,浏览器不允许元素嵌套,所以角提供ngForm指令,它行为相同,但可以嵌套。这可以让你有嵌套形式,正在使用ngRepeat指令动态生成的形式采用了棱角分明的验证指令时,这是非常有用的。既然你不能使用插值动态生成输入元素的name属性,你必须包装每套重复投入在ngForm指令,并窝在这些外表单元素。


也许这也适用于在 $脏状态,这样,如果孩子的形式为 $脏父窗体也将是 $脏。我不知道你的情况,你就可以嵌套的表格。我没有足够的信息来可视化你想要达到的目标。

另外,您也可以手动的主要形式设置为脏的时候,其他形式之一变脏。因为你从你的主表单中添加的code,我可以你不使用内置的脏检查的角度看。也许你有一个很好的理由,但也许你不知道它的存在。你必须使用棱角指令即可。在的FormController 有以下方法: $使用setDirty();

的FormController文档

表指令文档

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:

$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. However, I don't know to which event should I hook to set form.$$parentForm.$setDirty when my form becomes dirty. If you can help me figure this out, then it will work for me, I guess.

解决方案

Quote from Angular documentation on the form directive:

In Angular, forms can be nested. 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. 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. 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.

Maybe this also works for the $dirty state so that if a child form is $dirty the parent form will also be $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. 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 documentation

Form Directive documentation

这篇关于传播观点的脏状态对包含窗体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆