Search code examples
javascriptc#sessionquery-stringhidden-field

Query String Parameters


The Idea:


A custom gridview with only two columns. Instead of a traditional grid view with multiple columns for values, I have two columns with multiple values inside the columns. Below is a link to a screen showing this has turned out well.

Custom Grid View

Now that the grid view is working properly and it's values are populating as they should on page load, I am incorporating traditional functionality associated with a grid view. For example; search, filter, sort, and paging. These are the four primary functionalities I would like my grid view to have.

The Issue:


So far so good, the search, filter, sort, and paging all work as they should; however, they all have one singular issue in common: I can not combine these features. I wish to be able to, however upon adding a query string into project and completely refactoring my code, each feature only works one time.

For example: if I choose to filter by new, then sort by date created I would click 'New', and then 'Date Created'. When I click 'New', the query string looks like 'view=new&sort=customer&dir=ASC&page=1'. This is expected, however the unexpected result is when I click 'Date Created'; the query string changes to 'view=all&sort=creaon&dir=ASC&page=1'. The view has changed when it should not have.

This fact remains the same for all test cases. The hidden fields are receiving the values but not retaining their values across the post back due to their values being assigned on a click event. I haven't had any issues in the past with hidden fields doing this, so I am wondering what I am doing wrong at this point, what am I over looking? Also, if this isn't the correct approach for this issue then what would be?

The Code


Now currently all I can supply is the relevant code for this particular issue; The search value is handled by Session and the rest of the values are handled by hidden fields.

The paging elements are created on page load in the code behind.

JavaScript:

function setView(id, mode) {
    document.getElementById('PlaceHolderMainLower_PackageView_hfViewMode').setAttribute('Value', mode);
    setHref(id);
}

function setSort(id, mode) {
    document.getElementById('PlaceHolderMainLower_PackageView_hfSortMode').setAttribute('Value', mode);
    setHref(id);
}

function setPage(id, page) {
    document.getElementById('PlaceHolderMainLower_PackageView_hfPageIndex').setAttribute('Value', page);
    setHref(id);
}

function setHref(id) {
    var view = document.getElementById('PlaceHolderMainLower_PackageView_hfViewMode').value;
    var sort = document.getElementById('PlaceHolderMainLower_PackageView_hfSortMode').value;
    var dir = document.getElementById('PlaceHolderMainLower_PackageView_hfSortDirection').value;
    var page = document.getElementById('PlaceHolderMainLower_PackageView_hfPageIndex').value;

    document.getElementById(id).href = 'ActivePackages.aspx?' + 'view=' + view + '&sort=' + sort + '&dir=' + dir + '&page=' + page;
    __doPostBack();
}

CSS:

.viewLinks {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}

.viewLinks:hover {
    cursor: pointer;
}

HTML:

<asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="upHiddenFields" runat="server" UpdateMode="Always" EnableViewState="true" ViewStateMode="Enabled" >
    <ContentTemplate>
        <asp:HiddenField ID="hfViewMode" runat="server" Value="all" EnableViewState="true" ViewStateMode="Enabled" />
        <asp:HiddenField ID="hfSortMode" runat="server" Value="customer" EnableViewState="true" ViewStateMode="Enabled" />
        <asp:HiddenField ID="hfSortDirection" runat="server" Value="ASC" EnableViewState="true" ViewStateMode="Enabled" />
        <asp:HiddenField ID="hfPageIndex" runat="server" Value="1" EnableViewState="true" ViewStateMode="Enabled" />
    </ContentTemplate>
</asp:UpdatePanel>

<div id="divViews" style="display: table; width: 100%; table-layout: fixed;">
                <span>View By Status:</span>
                <asp:LinkButton ID="lnkAll" runat="server" CssClass="viewLinks" Text="All" OnClientClick="setView(this.id, 'all');" />
                <asp:LinkButton ID="lnkNew" runat="server" CssClass="viewLinks" Text="New" OnClientClick="setView(this.id, 'new');" />
                <asp:LinkButton ID="lnkProgress" runat="server" CssClass="viewLinks" Text="In Progress" OnClientClick="setView(this.id, 'inProgress');" />
            </div>

            <div id="divViews" style="display: table; width: 100%; table-layout: fixed;">
                <span>Sort By:</span>
                <asp:LinkButton ID="lnkCustomer" runat="server" CssClass="viewLinks" Text="Customer" OnClientClick="setSort(this.id, 'customer');" />
                <asp:LinkButton ID="lnkType" runat="server" CssClass="viewLinks" Text="Type" OnClientClick="setSort(this.id, 'type');" />
                <asp:LinkButton ID="lnkCreatedOn" runat="server" CssClass="viewLinks" Text="Date Created" OnClientClick="setSort(this.id, 'creaon');" />
            </div>

C#:

private const string pageLinkTemplateHTML = @"<a id=""pageLink{0}"" onclick=""setPage(this.id, {1});"" class=""viewLinks"">{2}</a>";
    private void BuildPaging() {
    divPages.InnerHtml = @"<table style=""width: 100%;""><tr><td style=""width: 100%"">";

    for (int i = 1; i <= Packages.Count / pageSize; i++)
        divPages.InnerHtml += string.Format(pageLinkTemplateHTML, i, i, i);

    divPages.InnerHtml += "</td></tr></table>";
}

Solution

  • As I said in my comment, you could use variables for storing the state of your selection. Example:

    // do the same for your other variables
    var view = 'all';
    function setView(id, mode) {
        view = mode;
        setHref(id);
    }
    
    function setHref(id) {
        // now you don't need to read view, sort,
        // dir and page from DOM elements, they are already there
        document.getElementById(id).href = 'ActivePackages.aspx?' + 'view=' + view + '&sort=' + sort + '&dir=' + dir + '&page=' + page;
        __doPostBack();
    }
    
    // on page load, you read the querystring from the url, check for the values and put them back into variables
    window.addEventListener('load', function(){
        var query_string = {};
        var query = window.location.search.substring(1);
        var vars = query.split("&");
        for (var i=0;i<vars.length;i++) {
            var pair = vars[i].split("=");
            // If first entry with this name
            if (typeof query_string[pair[0]] === "undefined") {
                query_string[pair[0]] = decodeURIComponent(pair[1]);
                // If second entry with this name
            } else if (typeof query_string[pair[0]] === "string") {
                query_string[pair[0]] = [query_string[pair[0]],decodeURIComponent(pair[1])];
                // If third or later entry with this name
            } else {
                query_string[pair[0]].push(decodeURIComponent(pair[1]));
            }
        }
        // do the same for your other parameters
        if(query_string.hasOwnProperty('view')){
            view = query_string.view;
        }
    });