bootstrap手风琴在updatepanel内的buttonclick上关闭

时间:2016-01-02 23:36:42

标签: asp.net twitter-bootstrap webforms

我在一个页面上有一个bootstrap 3.x 手风琴(折叠),我试图让用户能够添加/编辑大量信息而无需大量滚动。其中一些信息取决于其他信息,因此我在其中一个手风琴选项卡中有一个UpdatePanel。更新面板不是正确地做它的事情,或者它只是不能以其他方式与手风琴一起玩。

以下是基本的手风琴代码:

<div class="panel-group" id="ccAccordion" role="tablist" aria-multiselectable="true">
    <asp:Panel ID="pnlAddress" runat="server" class="panel panel-default">
        <div class="panel-heading" role="tab" id="billAddressHeading">
            <h4 class="panel-title">
                <a role="button" data-toggle="collapse" data-parent="#ccAccordion" href="#billToAddressTab" aria-expanded="false" aria-controls="billToAddressTab">
                    <asp:Literal ID="BillToAddressLabelTxt" runat="server" Text="Bill Address" />
                </a>
            </h4>
        </div>
        <div id="billToAddressTab" class="panel-collapse collapse" role="tabpanel" aria-labelledby="billAddressHeading">
            <div class="panel-body">
                <!-- Other controls -->
            </div>
        </div>
    </asp:Panel>
    <div class="panel panel-default">
        <div class="panel-heading" role="tab" id="thirdPartyHeading">
            <h4 class="panel-title">
                <a role="button" data-toggle="collapse" data-parent="#ccAccordion" href="#thirdPartyTab" aria-expanded="false" aria-controls="thirdPartyTab">
                    <asp:Literal ID="ThirdPartyShippingLabelTxt" runat="server" Text="Shipping Accounts" />
                </a>
            </h4>
        </div>
        <div id="thirdPartyTab" class="panel-collapse collapse" role="tabpanel" aria-labelledby="thirdPartyHeading">
            <div class="panel-body">
                <asp:UpdatePanel runat="server" UpdateMode="Always" ChildrenAsTriggers="true">
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="btnAddShipAccount" EventName="Click" />
                        <asp:AsyncPostBackTrigger ControlID="btnSaveSABA" EventName="Click" />
                        <asp:AsyncPostBackTrigger ControlID="btnAddShipAccountNo" EventName="Click" />
                    </Triggers>
                    <ContentTemplate>
                                        <asp:Button ID="btnAddShipAccount" runat="server" CssClass="btn btn-success" Text="Add New Shipping Account"
                                             OnClick="btnAddShipAccount_Click" /><!-- moved from inside panel -->
                        <asp:Panel ID="pnlBranchShipping" runat="server" DefaultButton="btnSaveSABA">
                            <div class="panel panel-default">
                                <div class="controls">
                                    <div class="form-group">
                                    <!-- Other controls -->
                                    </div>
                                    <asp:panel ID="pnlAddEditAcct" CssClass="controls" runat="server" Visible="false">
                                        <!-- Other controls -->
                                        <div>
                                            <asp:LinkButton ID="btnSaveSABA" Text="Save" runat="server" ValidationGroup="vgSAB" OnClick="btnSaveSABA_Click"
                                                CssClass="btn btn-default" />
                                        </div>
                                        <div class="form-group">
                                            <asp:Button ID="btnAddShipAccountNo" runat="server" CssClass="btn btn-default" Text="Add Shipping Account" OnClick="btnAddShipAccountNo_Click"
                                                ValidationGroup="vgShipAccount" />
                                        </div>
                                    </asp:panel>
                                </div>
                            </div>
                        </asp:Panel>

                    </ContentTemplate>
                </asp:UpdatePanel>
            </div>
        </div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading" role="tab" id="vatHeading">
            <h4 class="panel-title">
                <a role="button" data-toggle="collapse" data-parent="#ccAccordion" href="#vatTab" aria-expanded="false" aria-controls="vatTab"> 
                    <asp:Literal ID="VatNumberLabelTxt" runat="server" Text="Tax Ids" />
                </a>
            </h4>
        </div>
        <div id="vatTab" class="panel-collapse collapse" role="tabpanel" aria-labelledby="vatHeading">
            <div class="panel-body">
                <asp:Panel ID="pnlTaxId" runat="server" class="form-group" DefaultButton="btnAddTaxId">
                <!-- Other controls -->
                </asp:Panel>
            </div>
        </div>
    </div>
</div>

当你点击里面的任何一个按钮时会发生什么呢?它基本上会刷新整个页面,手风琴会回到原来的状态,但按钮所做的事情(例如显示其他字段)在你打开时是可见的再次打开标签。

更新

我今天意识到上面的所有代码都在MasterPage中的另一个UpdatePanel中。此UpdatePanel具有所有默认设置,因此上面代码中的回发触发了父代。我猜想要解决这个问题,我将不得不改变整个表格的运作方式。

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题并使用了以下一些自定义代码来解决它。

(function (rc, $, undefined) {
(function (ui, $, undefined) {

    // #region Coordinator

    ui.updatePanelControlStateManagers = (function () {

        var managers = [];

        function UpdatePanelControlStateCoordinator() {
            $(function () {
                initialize(this);
            });
        }

        // #region Private

        function initialize(module) {
            Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(onBeginRequest);
            Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest);
        }

        function onBeginRequest(prm, e) {
            managers.forEach(function (m) {
                var updatePanels = e.get_updatePanelsToUpdate().map(function (v) { return $("[id$=" + v.substring(v.lastIndexOf("$") + 1) + "]"); });
                m.persistStates(updatePanels);
            });
        }

        function onEndRequest() {
            managers.forEach(function (m) {
                m.restoreStates();
            });
        }

        // #endregion

        // #region Public

        UpdatePanelControlStateCoordinator.prototype.add = function (instance) {
            managers.push(instance);
        };

        UpdatePanelControlStateCoordinator.prototype.remove = function (type) {
            var index = managers.findIndex(function (m) { return m instanceof type });

            if (index)
                managers = managers.splice(index, 1);
        };

        // #endregion

        return new UpdatePanelControlStateCoordinator();

    }());

    // #endregion

    // #region Managers

    ui.accordionControlStateManager = (function () {

        function AccordionControlStateManager() {
            this.states = [];
            this.scrollPosition = null;
        }

        // #region Public

        AccordionControlStateManager.prototype.persistStates = function (updatePanels) {
            var that = this;

            updatePanels.forEach(function (panel) {
                var $panel = $(panel);

                $panel.find(".panel-collapse").each(function (i, elem) {
                    var selector = rc.utilities.getNestedSelectorForElement(elem, $panel);
                    var expanded = $(elem).hasClass("in");

                    that.states.push({ selector: selector, expanded: expanded });
                });
            });

            this.scrollPosition = $(window).scrollTop();
        };

        AccordionControlStateManager.prototype.restoreStates = function () {
            this.states.forEach(function (state) {
                var $elem = $(state.selector);

                if ($elem.length)
                    $elem.toggleClass("in", state.expanded);
            });

            $(window).scrollTop(this.scrollPosition);

            this.scrollPosition = null;
            this.states = [];
        };

        // #endregion

        return AccordionControlStateManager;

    }());

    ui.tabsControlStateManager = (function () {

        function TabsControlStateManager() {
            this.states = [];
            this.scrollPosition = null;
        }

        // #region Public

        TabsControlStateManager.prototype.persistStates = function (updatePanels) {
            var that = this;

            updatePanels.forEach(function (panel) {
                var $panel = $(panel);

                $panel.find("ul.nav-tabs").each(function (i, elem) {
                    var selector = rc.utilities.getNestedSelectorForElement(elem, $panel);
                    var tab = $(elem).find("li.active a").attr("href");

                    that.states.push({ selector: selector, tab: tab });
                });
            });

            this.scrollPosition = $(window).scrollTop();
        };

        TabsControlStateManager.prototype.restoreStates = function () {
            this.states.forEach(function (state) {
                var $elem = $(state.selector);

                if ($elem.length)
                    $elem.find("li > a[href='" + state.tab + "']").tab("show");
            });

            $(window).scrollTop(this.scrollPosition);

            this.scrollPosition = null;
            this.states = [];
        };

        // #endregion

        return TabsControlStateManager;

    }());

    // #endregion

}(rc.ui = rc.ui || {}, $));
}(window.rc = window.rc || {}, jQuery));

其中引用了以下实用程序js:

(function (rc, $, undefined) {
(function (utilities, $, undefined) {
    utilities.getSelectorForElement = function($elem) {
        var result = null,
            id = $elem.attr("id"),
            className = $elem[0].className,
            tagName = $elem[0].tagName;

        if (id) {
            result = "#" + id;
        } else if (className) {
            result = "." + className.replace(/\s/g, ".");
        } else {
            result = tagName;
        }

        if ($elem.parent().children(result).length > 1) {
            result = result + ":eq(" + $elem.index() + ")";
        }

        return result;
    }

    utilities.getNestedSelectorForElement = function (elem, $recurseTo) {
        var $elem = $(elem);

        if ($elem.is($recurseTo)) {
            return "";
        }

        var selector = utilities.getSelectorForElement($elem);
        var parentSelector = utilities.getNestedSelectorForElement($elem.parent(), $recurseTo);

        selector = parentSelector ? parentSelector + " > " + selector
                                  : selector;

        return selector;
    }

}(rc.utilities = rc.utilities || {}, $));
}(window.rc = window.rc || {}, jQuery));

并初始化如下:

$(function() {
    rc.ui.updatePanelControlStateManagers.add(new rc.ui.accordionControlStateManager());
    rc.ui.updatePanelControlStateManagers.add(new rc.ui.tabsControlStateManager());
});

这个想法是你可以为导致你麻烦的任何控件创建一个自定义状态管理器(我的选项卡和手风琴),在初始化逻辑中连接它,并在任何更新面板中处理它

答案 1 :(得分:1)

我实际上最终在这个答案中使用了解决方案:https://stackoverflow.com/a/25258290/727857

这也适用于 Bootstrap 3.x.x ,需要来自https://github.com/carhartl/jquery-cookie的jquery-cookie.js

已修改,以便在链接死亡时添加上述答案的全文:

手风琴的示例HTML:

<div class="panel-group" id="accordion">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h4 class="panel-title">
                <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">Collapsible Group
                    Item #1 </a>
            </h4>
        </div>
        <div id="collapseOne" class="panel-collapse collapse in">
            <div class="panel-body">
                Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson
                ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food
                truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put
                a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim
                keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident.
                Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table,
                raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus
                labore sustainable VHS.
            </div>
        </div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">
            <h4 class="panel-title">
                <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">Collapsible Group
                    Item #2 </a>
            </h4>
        </div>
        <div id="collapseTwo" class="panel-collapse collapse">
            <div class="panel-body">
                Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson
                ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food
                truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put
                a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim
                keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident.
                Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table,
                raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus
                labore sustainable VHS.
            </div>
        </div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">
            <h4 class="panel-title">
                <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">Collapsible
                    Group Item #3 </a>
            </h4>
        </div>
        <div id="collapseThree" class="panel-collapse collapse">
            <div class="panel-body">
                Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson
                ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food
                truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put
                a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim
                keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident.
                Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table,
                raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus
                labore sustainable VHS.
            </div>
        </div>
    </div>
</div>

Javascript(jquery)保留此手风琴中标签的状态:

$(document).ready(function () {
        //when a group is shown, save it as the active accordion group
        $("#accordion").on('shown.bs.collapse', function () {
            var active = $("#accordion .in").attr('id');
            $.cookie('activeAccordionGroup', active);
          //  alert(active);
        });
        $("#accordion").on('hidden.bs.collapse', function () {
            $.removeCookie('activeAccordionGroup');
        });
        var last = $.cookie('activeAccordionGroup');
        if (last != null) {
            //remove default collapse settings
            $("#accordion .panel-collapse").removeClass('in');
            //show the account_last visible group
            $("#" + last).addClass("in");
        }
    });

我不知道dshapiro的答案是否有效或更好,但这不是javascript,可以很容易地制作成可在不同页面上重复的功能。