SPGridview and collapsed grouping by default!
This really bugged me when I came across the SPGridView (as you can read in the previous about this control) that when you set the following properties
oGrid.AllowGrouping = true; oGrid.AllowGroupCollapse = true;
You'd expect that there is another property where you can specify if you want to have it collapsed or expanded when the Grid gets rendered. Unfortunately there isn't.. but (and that's why I'm posting ;)) there is dirty way to do it and that's injecting some javascript after the grid gets rendered. Thanks to my collegua Servé "CSS/HTML & Javascript Wizard" Hermans the following bit of script gets the job done.
<script type="text/javascript"> var rows = document.getElementsByTagName('tr'); var numRows = rows.length; for (var i = 0; i < numRows; ++i) { if (rows[i].getAttribute("isexp") != null && rows[i].getAttribute("isexp").toLowerCase() == "true") { if(rows[i].firstChild.firstChild != null && rows[i].firstChild.firstChild.tagName.toLowerCase() == "a") { if (rows[i].firstChild.firstChild.title.toLowerCase() == "expand/collapse") { rows[i].firstChild.firstChild.fireEvent("onclick"); } } } } </script>
To explain it the script.. an event called "ToggleSPGridViewGroup" (which can be found in the spgridview.js in the Layouts folder) is fired when you click on the expand/collapse icon on the grouped item. So I thought "Why not fire all of the links to have it all collapsed by default?" :) I thought this wasn't possible since it seems REALLY dirty to actually fire events without user interaction. But it actually is possible! Thank god ;)
28 comments:
If you were to incorporate this script into a web part, would adding it via the ClientScriptManager.RegisterClientScriptBlock work?
I have attempted this and it doesn't seem to be working. I'm not getting any errors, but the groups are not collapsing either.
Does the register block in the OnLoad event allow the script to actually fire on the page?
Hi Randy,
well what I did was the include the script using the Render function. And I 'display' this bit of javascript at the very end. I will post some code example tomorrow!
I got it working now. What I did was to add the script block at the OnLoad event but I made it a function. I then called the function using a literal control added at the end of CreateChildControls.
Thanks for the work-around!
try this http://msdn2.microsoft.com/en-us/library/ms948916.aspx
sam from chicago
Hi Robin,
Could you please post a small example of, how you add the script and call it on your aspx-page?
Thank you
Lasse from Denmark
It works well putting into a Content Editor Web Part after the grid.
Thanks it works
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
//All Code
}
writer.Write(DisplayScript());
}
In DisplayScript is the java script
Is there any way of doing this without a front web page? pure c#
Thank you
For JQuery users, I was able to do this as the single line:
$('a[title^="Expand"]').trigger("click");
Thanks for the article!
Hi John,
thanks.. and indeed very clever to use JQuery for stuff like this! :)
Thanks for the tip! I had to modify your script a bit after I found out that my Polish version of SharePoint rendered 'expand/collapse' titles as their Polish equivalents.
Lots of thanks for the code...it worked perfectly to me.
In my case, I used Sharepoint Designer, and I paste the javascript below this label:
ContentPlaceHolderId="PlaceHolderBodyAreaClass"
I found some problems when I used your JS code.I was obliged to use many firstchild properties and with sharepoint in french the expand/collapse is replaced by another title!!
Thanks for the post! This is great stuff, only like Anonymous, I had many more nested children, so this didn't work for me.
Instead of using a bunch of "firstChild" references, I whittled the code down to just search for "a" tags with the appropriate title.
For what it's worth, here's what works best with my SPGridView:
var rows = document.getElementsByTagName('a');
var numRows = rows.length;
for (var i = 0; i < numRows; ++i)
{
if (rows[i].title.toLowerCase()=="expand/collapse")
{
rows[i].fireEvent("onclick");
}
}
Eric, the only problem with your approach is that you're getting all elements with a tag of 'a', which, as we all know, can be highly unpredictable. Try using the original approach first.
I have a question:
Does this code work if you need 2 levels of nested sub-grouping.
Example:
XYZ corp- Sales (first child) - US Sales (second child)
Hope you got what I am trying to say.
Example: To call JS in web part.
protected override void RenderContents(HtmlTextWriter writer)
{
writer.Write(errorMessage);
writer.Write(DisplayScript());
EnsureChildControls();
RenderChildren(writer);
}
private string DisplayScript()
{
StringBuilder strCollapseScript = new StringBuilder();
strCollapseScript.Append("--script language='javascript'--");
strCollapseScript.Append("var rows = document.getElementsByTagName('tr');");
strCollapseScript.Append("var numRows = rows.length;");
strCollapseScript.Append("for (var i = 0; i < numRows; ++i) ");
strCollapseScript.Append("{");
strCollapseScript.Append("if (rows[i].getAttribute('isexp') != null && rows[i].getAttribute('isexp').toLowerCase() == 'true')");
strCollapseScript.Append("{");
strCollapseScript.Append("if(rows[i].firstChild.firstChild != null && rows[i].firstChild.firstChild.tagName.toLowerCase() == 'a')");
strCollapseScript.Append("{ ");
strCollapseScript.Append("if (rows[i].firstChild.firstChild.title.toLowerCase() == 'expand/collapse')");
strCollapseScript.Append("{");
strCollapseScript.Append("rows[i].firstChild.firstChild.fireEvent('onclick');");
strCollapseScript.Append("}");
strCollapseScript.Append("}");
strCollapseScript.Append("}");
strCollapseScript.Append("}");
strCollapseScript.AppendLine("--/script--");
Page.ClientScript.RegisterStartupScript(Page.GetType(), "SearchScript", strCollapseScript.ToString());
return string.Empty ;
}
replace -- with greater sign.
None of these options appear to be working for me. The grid loads but all of the groups are still expanded.
Use this:
if (rows[i].firstChild.firstChild.title.indexOf('Expand/Collapse')==0) {
rows[i].firstChild.firstChild.fireEvent("onclick");
}
Got this working as well, embedded my script as a function at the top of my sharepoint web part just after the @register and @assembly registrations. Then injected an ASP LiteralControl like the following:
protected override void CreateChildControls()
{
Control control = Page.LoadControl(_ascxPath);
Controls.Add(control);
Controls.Add(new LiteralControl("--script type='text/javascript'>CollapseAll()--/script--"));
}
Nuisance that CollapseAll is not provided
Please right indexOf("expand/collapse")
if (rows[i].firstChild.firstChild.title.toLowerCase().indexOf("expand/collapse") != -1) {
......
}
instade of comparing the value like
if (rows[i].firstChild.firstChild.title.toLowerCase() == "expand/collapse")
{
...........
}
instead of code
if (rows[i].firstChild.firstChild.title.toLowerCase() == "expand/collapse")
{
....
}
Please write
if (rows[i].firstChild.firstChild.title.toLowerCase().indexOf("expand/collapse") != -1) {
....
}
instead of code
if (rows[i].firstChild.firstChild.title.toLowerCase() == "expand/collapse")
{
....
}
Please write
if (rows[i].firstChild.firstChild.title.toLowerCase().indexOf("expand/collapse") != -1) {
....
}
instead of code
if (rows[i].firstChild.firstChild.title.toLowerCase() == "expand/collapse")
{
....
}
Please write
if (rows[i].firstChild.firstChild.title.toLowerCase().indexOf("expand/collapse") != -1) {
....
}
If some one wants to make grouping collapse by default using Jquery please use the below code:
$(document).ready(function () {
$("#<%=YourGridViewId.ClientID %> tr[isexp$='true']").each(function () {
$(this).find('a').click();
});
});
Its not working in IE11 and chrome.Can you please specify where i have to change.
jQuery('tr[isexp="true"] a[title^="Expand/Collapse"]').click()
Post a Comment