May 01, 2014, 11:28 PM
[CLOSED] GridPanel RowExpander issues
I know there are issues with using the RowExpander and loading inner grids. But I'm not sure how else to handle my requirements (listed below). So I'm hoping to get some help either resolving the issues, or using a different solution that still meets requirements.
Requirements:
The issues I'm finding:
Here is the sample code:
GridExpander.cshtml
Thanks! Joel
Requirements:
- Notify user on main grid row that there could be an issue with a document (loaded in RowExpander grid)
- Allow user to select rows on main grid to be submitted to an action
- When user expands a main row, they will see, and be able to click on associated records (Documents) to perform an action
- When user expands a main row with an alert (Incomplete), they will see the document at issue and mouse over the alert icon to see a list of empty tables in a callout
The issues I'm finding:
- The main rows have rendered columns that substitute in icons for text (Preferred, Incomplete). When user expands any row, the icons move out of alignment - significantly.
- When user expands a row, a grey bar shows between the main row content and the inner grid data.
- When user expands the row with an incomplete alert, the callout works and user can mouse over entire area without issue. However, if a row without an alert is expanded, if user mouses vertically across the span of the row - javascript error(s) occur (screenshot).
Here is the sample code:
GridExpander.cshtml
@model [YOUR PATH].Models.DebugViewModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>GridExpander</title>
<script type="text/javascript">
var bulletStarUrl = Ext.net.ResourceMgr.getIconUrl("BulletStar");
var bulletErrorUrl = Ext.net.ResourceMgr.getIconUrl("BulletError");
var incompleteColumnRenderer = function (value, meta, record, index) {
if (value == true)
return Ext.String.format("<img src='{0}' />", bulletErrorUrl);
return "";
};
var preferredColumnRenderer = function (value, meta, record, index) {
if (value == true)
return Ext.String.format("<img src='{0}' />", bulletStarUrl);
return "";
};
var viewColumnPreparer = function (grid, command, record, row) {
command.text = record.data.FileName;
}
var loadDocument = function (column, command, record, recordIndex, cellIndex) {
alert("You would be loading: " + record.data.FileName);
}
var calloutOuterHtml = "<ul style='margin-left:5px; margin-bottom:0px; margin-top:0px; padding-left:0px;'>{0}</ul>";
var setCalloutContent = function (callout) {
var grid = callout.calloutOwner,
record = grid.view.getRecord(callout.triggerElement.dom.parentNode),
emptyTables = record.data.EmptyTables;
if (emptyTables.length == 0) return false;
var html = Ext.String.format(calloutOuterHtml, Ext.String.format("<li style='margin-bottom:2px;'>{0}</li>", emptyTables.split(",").join("</li><li style='margin-bottom:2px;'>")));
callout.setHtml(html);
}
</script>
</head>
<body>
@Html.X().ResourceManager()
@(Html.X().Viewport()
.Layout(LayoutType.Anchor)
.Padding(10)
.Items(
Html.X().GridPanel()
.ID("GridPanelPeople")
.Title("People")
.Frame(true)
.Border(true)
.AnchorHorizontal("100%")
.Margin(10)
.ForceFit(true)
.MinHeight(500)
.Store(
Html.X().Store()
.ID("StorePeople")
.PageSize(20)
.DataSource(Model.People)
.Model(
Html.X().Model()
.IDProperty("PersonId")
.Fields("PersonId",
"First",
"Last",
"Email",
"IsPreferred",
"HasEmptyTables")
)
)
.ColumnModel(
Html.X().Column().DataIndex("First").Text("First"),
Html.X().Column().DataIndex("Last").Text("Last"),
Html.X().Column().DataIndex("Email").Text("Email"),
Html.X().Column()
.DataIndex("IsPreferred")
.Text("Preferred")
.Align(Alignment.Center)
.Width(32)
.Renderer(new Renderer() { Fn = "preferredColumnRenderer" }),
Html.X().Column()
.DataIndex("HasEmptyTables")
.Text("Incomplete")
.ItemID("HasEmptyTables")
.Align(Alignment.Center)
.Width(32)
.Renderer(new Renderer() { Fn = "incompleteColumnRenderer" })
)
.SelectionModel(
Html.X().RowSelectionModel()
.ID("RowSelectionModelDocument")
.Mode(SelectionMode.Simple)
)
.View(
Html.X().GridView().TrackOver(false)
)
.Plugins(
Html.X().RowExpander()
.ScrollOffset(10)
.Loader(
Html.X().ComponentLoader()
.Url(Url.Action("LoadDocuments"))
.Mode(LoadMode.Component)
.LoadMask(mask => mask.ShowMask = true)
.Params(new { id = JRawValue.From("this.record.getId()") })
)
)
.BottomBar(
Html.X().PagingToolbar()
)
)
)
</body>
</html>
DocumentGrid.cshtml@model [YOUR PATH].Models.DebugViewModel
@(Html.X().GridPanel()
.Border(false)
.Header(false)
.HideHeaders(true)
.EnableColumnHide(false)
.DisableSelection(true)
.Store(
Html.X().Store()
.DataSource(Model.Documents)
.Model(
Html.X().Model()
.Fields(
Html.X().ModelField().Name("DocumentId").Type(ModelFieldType.Int),
Html.X().ModelField().Name("FileName"),
Html.X().ModelField().Name("HasEmptyTables").Type(ModelFieldType.Boolean),
Html.X().ModelField().Name("EmptyTables")
)
)
)
.ColumnModel(
Html.X().Column()
.Width(420)
.RightCommandAlign(false)
.MenuDisabled(true)
.Hideable(false)
.PrepareCommand(p => p.Fn = "viewColumnPreparer")
.Commands(
Html.X().ImageCommand()
.CommandName("ViewReport")
.Icon(Icon.PageWhiteAcrobat)
)
.Listeners(l =>
{
l.Command.Fn = "loadDocument";
}),
Html.X().Column()
.DataIndex("HasEmptyTables")
.ItemID("HasEmptyTables")
.Align(Alignment.Center)
.Width(32)
.Renderer(new Renderer() { Fn = "incompleteColumnRenderer" })
)
.View(
Html.X().GridView().TrackOver(false)
)
.Callouts(cos =>
{
cos.Add(
Html.X().Callout()
.Title("Empty Tables")
.HeaderStyle("font-size:9pt;")
.Trigger(CalloutTrigger.Hover)
.Alignment(AnchorPoint.Left)
.Delegate(".x-grid-cell-HasEmptyTables")
.UI(UI.Warning)
.Listeners(l =>
{
l.BeforeShow.Fn = "setCalloutContent";
})
);
})
)
Controller[AllowAnonymous]
public ActionResult GridExpander()
{
return View(new DebugViewModel()
{
People = new List<DebugViewModel.Person>()
{
new DebugViewModel.Person { PersonId=1, First="Homer", Last="Simpson", Email="hsimpson@springfield.net", IsPreferred=true, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=2, First="Montgomery", Last="Burns", Email="hburns@springfield.net", IsPreferred=true, HasEmptyTables=true },
new DebugViewModel.Person { PersonId=3, First="Krusty", Last="Clown", Email="kclown@springfield.net", IsPreferred=false, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=4, First="Edna", Last="Krabappel", Email="ekrabappel@springfield.net", IsPreferred=false, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=5, First="Bumblebee", Last="Man", Email="bman@springfield.net", IsPreferred=false, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=6, First="Selma", Last="Bouvier", Email="sbouvier@springfield.net", IsPreferred=true, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=7, First="Gary", Last="Chalmers", Email="gchalmers@springfield.net", IsPreferred=true, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=8, First="Apu", Last="Nahasapeemapetilon", Email="anahasapeemapetilon@springfield.net", IsPreferred=true, HasEmptyTables=false },
new DebugViewModel.Person { PersonId=9, First="Ned", Last="Flanders", Email="nflanders@springfield.net", IsPreferred=true, HasEmptyTables=false },
}
});
}
public ActionResult LoadDocuments(int id)
{
int id1 = id *10;
int id2 = id1 + 1;
bool hasEmptyTables = false;
string emptyTables = String.Empty;
if (id == 2)
{
hasEmptyTables = true;
emptyTables = "Table One,Table Two,Table Three";
}
return this.ComponentConfig("DocumentGrid",
new DebugViewModel()
{
Documents = new List<DebugViewModel.Document>()
{
new DebugViewModel.Document { DocumentId=id1, FileName="Document " + id1 + ".pdf", EmptyTables=emptyTables, HasEmptyTables=hasEmptyTables },
new DebugViewModel.Document { DocumentId=id2, FileName="Document " + id2 + ".pdf", EmptyTables=String.Empty, HasEmptyTables=false }
}
}
);
}
Modelusing System.Collections.Generic;
namespace [YOUR PATH].Models
{
public class DebugViewModel
{
public List<Person> People { get; set; }
public List<Document> Documents { get; set; }
public class Person
{
public int PersonId { get; set; }
public string First { get; set; }
public string Last { get; set; }
public string Email { get; set; }
public bool IsPreferred { get; set; }
public bool HasEmptyTables { get; set; }
}
public class Document
{
public int DocumentId { get; set; }
public string FileName { get; set; }
public bool HasEmptyTables { get; set; }
public string EmptyTables { get; set; }
}
}
}
Again ... I'm open to alternate suggestions.Thanks! Joel
Last edited by Daniil; May 16, 2014 at 2:38 PM.
Reason: [CLOSED]