1

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>";
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • You are trying to set text values in DOM elements, and then read them back out. This might be the problem. I would either store the current view in variable, or use radio buttons instead of buttons which set their value via an onclick function. – Danmoreng Apr 03 '17 at 15:50

1 Answers1

0

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;
    }
});
Danmoreng
  • 2,367
  • 1
  • 19
  • 32
  • But are the values for these variables going to persist across post back? I was using a string array before to store the values and was still having issues. Though I do believe the issues were playing a little better with each other. –  Apr 03 '17 at 16:05
  • What exactly does postBack do? If it reloads the page, you have to set those variables again afterwards. I'll edit something into the code to show you how I would do it. – Danmoreng Apr 03 '17 at 16:11
  • I just attempted using the variable idea to no avail, the same thing is still happening with the query string. –  Apr 03 '17 at 16:11
  • [What Is A Postback?](http://stackoverflow.com/questions/4251157/what-is-a-postback); this link should be quite helpful. –  Apr 03 '17 at 16:16
  • So to continue this I would have to do sequential if blocks for each property in the query string? This seems a little over-complicated, but I'm open for anything at this point. I'll give it a try and let you know how it goes. Also, the 'over-complication' comment is more of in relation to me not truly understanding your javascript code; could you put a little more comments into it and explain what's going on? I can 'sort-of' understand it; however the most confusion occurs with the if blocks in your loop. Also, why do you consider this to be the correct way to do this? –  Apr 03 '17 at 16:22
  • The QueryString snippet is something I took from another stackoverflow question long ago - it really just makes an Javascript object out of the query parameters, so they are easy to access. I don't really know what doPostback() does, from my understanding it is clicking the button for you...maybe you are not posting the new parameters to the server in the first place? – Danmoreng Apr 03 '17 at 16:25
  • Okay, so that definately worked; now I just have to repair my server side code to re-build the grid at this point; however, can you break down the if structure inside your loop for me? –  Apr 03 '17 at 16:28
  • Not really. As I said I took the entire snippet from another stackoverflow question. It is just a helper to get all the parameters in the URL. You can read more about it http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript, though this question doesn't contain the exact snippet I use. – Danmoreng Apr 03 '17 at 16:35