Answered by:
Accordion for Dynamic Data Entities

Question
-
User-635256440 posted
Hello everyone,
I'm trying to implement an Accordion style for a "Dynamic Data" application and can't find much help. Has anyone been able to do this whether through jQuery or Ajax? Would appreciate your help.
The reason for Accordion is that I have over 150 fields and the form looks overwhelming without an Accordion or Tab to simplify. So, if you have other ideas would love to hear from ya.
Thanks.
Thursday, April 26, 2012 4:19 PM
Answers
-
User-330204900 posted
Just added new Wijmo Tabs and Accordion sample to my blog here Creating a Tabbed Entity Template using Wijmo Open for Juice UI code download at bottom of the article.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Saturday, May 26, 2012 9:47 AM
All replies
-
User-330204900 posted
Hi Bja58, I used an AJAX tab control in an Entity Template see this articel for tha basic idea Custom Entity Templates – Dynamic Data 4 I basically used the AJAX Control Toolkit Tab control in an Entity Template to achive this. I should really do an article for that.
Friday, April 27, 2012 7:24 AM -
User-635256440 posted
Thanks Steve. I had actually read your article before...nice work. I'd love to see a working sample of an Accordion using AJAX.
Can anyone else help?
Monday, April 30, 2012 7:03 PM -
User1865095734 posted
Hi,
If you go for jquery stuff. you can use jquery UI accordion. That is a nice stuff. search for "Jquery UI accordion"
Thanks
Raj
Thursday, May 3, 2012 6:35 AM -
User350138131 posted
The reason for Accordion is that I have over 150 fields and the form looks overwhelming without an Accordion or Tab to simplify.
To apply the accordion for this purpose is hardly possible.
You can create your own pseudo-accordion, providing it with the appropriate functionality.
The task of mapping groups of fields, I decided to use an ordinary Combo Box. This solution I found the easiest.
If this interest you, I can put the code.Friday, May 11, 2012 1:28 AM -
User-330204900 posted
Try the JuiceUI that will give you the jQuery UI accordian and it should be easyer to do I will give it a try in the morning,
Friday, May 11, 2012 7:08 PM -
User350138131 posted
Hi, Sjnaughton. If you can use jQuery Accordion for Dynamic Data Entities, I considered it a miracle, and once again I'll be grateful! In the meantime, I will present a pseudo-accordion, I was talking about. This example is based on your http://csharpbits.notaclue.net/2010/02/grouping-field-on-details-edit-and.html. Here it is.
[AttributeUsage(AttributeTargets.Class)] public class ColumnsGroupsAttribute : Attribute { public string[] Groups { get; set; } } public static string[] GetColumnsGroups(this MetaTable table) { var groups = table.Attributes.OfType<ColumnsGroupsAttribute>().DefaultIfEmpty(new ColumnsGroupsAttribute()).First() as ColumnsGroupsAttribute; return groups.Groups; } public static int GetGroupIndex(this MetaColumn column) { if (column.GetAttributeOrDefault<DisplayAttribute>().GroupName == null) return -1; else return Convert.ToInt16(column.GetAttributeOrDefault<DisplayAttribute>().GroupName); }
public partial class DefaultEntityTemplate : System.Web.DynamicData.EntityTemplateUserControl { public MetaColumn currentColumn; public String groupName; public Boolean groupHeading; string[] clgr = null; private int currentGroup = -1; protected override void OnLoad(EventArgs e) { // get a list of groups ordered by group name var groupings = from t in Table.GetScaffoldColumns(Mode, ContainerType) group t by t.GetGroupIndex() into menu orderby menu.Key select menu.Key; clgr = Table.GetColumnsGroups(); // loop through the groups foreach (var groupId in groupings) { // get columns for this group var columns = from c in Table.GetScaffoldColumns(Mode, ContainerType) where (groupId == -1 && c.GetAttributeOrDefault<DisplayAttribute>().GroupName == null) || c.GetAttributeOrDefault<DisplayAttribute>().GroupName == groupId.ToString() orderby c.GetAttributeOrDefault<DisplayAttribute>().GetOrder() select c; // add group separator if (groupId!=-1) { groupHeading = true; currentColumn = columns.First(); currentGroup = groupId; groupName = groupId.ToString(); Control item = new _NamingContainer(); EntityTemplate1.ItemTemplate.InstantiateIn(item); EntityTemplate1.Controls.Add(item); } // add fields foreach (MetaColumn column in columns) { groupHeading = false; currentColumn = column; Control item = new _NamingContainer(); EntityTemplate1.ItemTemplate.InstantiateIn(item); EntityTemplate1.Controls.Add(item); } } } protected void Label_Init(object sender, EventArgs e) { if (!groupHeading) { Label label = (Label)sender; label.Text = currentColumn.DisplayName; int gr = currentColumn.GetGroupIndex(); label.GetParentControl<HtmlTableRow>().Attributes["class"] += " gr gr" + gr.ToString(); } else { Label label = (Label)sender; label.CssClass = "button"; label.Width = Unit.Percentage(100); label.Text = clgr[Convert.ToInt16(groupName)]; var parentCell = label.GetParentControl<HtmlTableCell>(); parentCell.ColSpan = 2; label.Attributes["onclick"] = "return ChangeTab(event);"; label.Attributes["title"] = currentGroup.ToString(); //parentCell.Attributes.Add("class", "DDGroupHeader"); } } protected void DynamicControl_Init(object sender, EventArgs e) { DynamicControl dynamicControl = (DynamicControl)sender; dynamicControl.DataField = currentColumn.Name; if (groupHeading) { // hide Dynamic Control maybe overkill dynamicControl.Visible = false; // get the parent cell var parentCell = dynamicControl.GetParentControl<HtmlTableCell>(); // hide the cell parentCell.Visible = false; } } public class _NamingContainer : Control, INamingContainer { } }
dd.js
function pageLoad() { $(".button").button(); ChangeTab(null); } function ChangeTab(evt, bSave) { var o; if (evt != null) { evt = evt || window.event; o = evt.target || evt.srcElement; if (o != null) { o = o.parentNode; } } else { o = $(".button")[0] } if (o == null) return; var groupNum = o.title var oD = $(".gr") if (groupNum == null) oD.show(); else { oD.hide(); oD = $(".gr-1") oD.show(); if (groupNum != "-1") { oD = $(".gr" + groupNum) oD.show(100); } } }
[MetadataType(typeof(OrderMetadata))] public partial class Order { [ColumnsGroups(Groups = new string[] { "Dates", "Ship Info", "Other Info" })] internal partial class OrderMetadata { public Object OrderID { get; set; } public Object CustomerID { get; set; } public Object EmployeeID { get; set; } [Display(Order = 0,GroupName = "0")] public Object OrderDate { get; set; } [Display(Order = 1,GroupName = "0")] public Object RequiredDate { get; set; } [Display(Order = 2,GroupName = "0")] public Object ShippedDate { get; set; } [Display(Order = 4,GroupName = "1")] public Object ShipVia { get; set; } [Display(Order = 5,GroupName = "1")] public Object Freight { get; set; } [Display(Order = 3,GroupName = "1")] public Object ShipName { get; set; } [Display(Order = 6,GroupName = "1")] public Object ShipAddress { get; set; } [Display(Order = 7,GroupName = "1")] public Object ShipCity { get; set; } [Display(Order = 8,GroupName = "1")] public Object ShipRegion { get; set; } [Display(Order = 9,GroupName = "1")] public Object ShipPostalCode { get; set; } [Display(Order = 10,GroupName = "1")] public Object ShipCountry { get; set; } // Entity Ref [Display(Order = 12)] public Object Customer { get; set; } // Entity Ref [Display(Order = 13)] public Object Employee { get; set; } // Entity Set [Display(Order = 14)] public Object Order_Details { get; set; } // Entity Ref [Display(Order = 11,GroupName = "1")] public Object Shipper { get; set; } } }
Site.master
<link href="css/ui-lightness/jquery-ui-1.8.13.custom.css" rel="stylesheet" type="text/css" /> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Path="Scripts/jquery-1.5.2.min.js" /> <asp:ScriptReference Path="Scripts/jquery-ui-1.8.17.custom.min.js" /> <asp:ScriptReference Path="Scripts/DD.js" /> </Scripts> </asp:ScriptManager>
Thank you.
Sunday, May 13, 2012 2:10 AM -
User-330204900 posted
Hi Valz, here is my AJAX tab Entity templte
public partial class AjaxTabGroupsTemplate : System.Web.DynamicData.EntityTemplateUserControl { private const string STR__AjaxActiveTabIndex = "_AjaxActiveTabIndex"; private String _seperator; private TabContainer _tabContainer; protected override void OnInit(EventArgs e) { base.OnInit(e); _seperator = this.ClientIDSeparator.ToString(); // create a row with one cell to fill the // surrounding table from the form view var row = new HtmlTableRow(); var td = new HtmlTableCell(); row.Controls.Add(td); this.Controls.Add(row); // create tab container to hold each children column _tabContainer = new TabContainer() { ID = "tabContainer_" + Table.Name, // set auto post back to enable events AutoPostBack = true }; _tabContainer.ActiveTabChanged += tabContainer_ActiveTabChanged; // add the tab container to the page td.Controls.Add(_tabContainer); } private void tabContainer_ActiveTabChanged(object sender, EventArgs e) { Page.AddValueToSession<int>(Table.Name + STR__AjaxActiveTabIndex, _tabContainer.ActiveTabIndex); } protected override void OnLoad(EventArgs e) { var activeTab = Page.GetValueFromSession<int>(Table.Name + STR__AjaxActiveTabIndex); _tabContainer.ActiveTabIndex = activeTab; // get a list of groups ordered by group name var scaffoldedColumns = Table.GetScaffoldColumns(Mode, ContainerType); //var groupings = from t in scaffoldedColumns // group t by t.GetAttributeOrDefault<GroupAttribute>().Index into columnGroups // orderby columnGroups.Key // select columnGroups.Key; var groupAttribute = Table.GetAttribute<GroupNamesAttribute>(); if (groupAttribute == null) throw new InvalidOperationException("A GroupsAttribute is required for AJAX tab group to work."); //if (groupings.Count() != groupAttribute.Groups.Count) // throw new InvalidOperationException(""); // add table for each group //foreach (var gi in groupings) foreach (var gi in groupAttribute.Groups) { var groupName = gi.Value;//groupAttribute.Groups[gi]; // create table panel var tabPanel = new TabPanel() { ID = (Table.Name + _seperator + groupName).Replace(" ", _seperator), HeaderText = groupName }; // add tab to tab container _tabContainer.Tabs.Add(tabPanel); // create table to go inside tab var tabTable = new HtmlTable(); tabTable.Attributes.Add("class", "DDDetailsTable"); tabTable.Attributes.Add("cellpadding", "6"); tabTable.Attributes.Add("Name", groupName); // add the DynamicControl to the tab panel tabPanel.Controls.Add(tabTable); // get columns for this group var columns = from c in Table.GetScaffoldColumns(Mode, ContainerType) where c.GetAttributeOrDefault<GroupAttribute>().Index == gi.Key orderby c.GetAttributeOrDefault<GroupAttribute>().Index select c; // add fields foreach (MetaColumn column in columns) { var tableRow = new HtmlTableRow(); tabTable.Controls.Add(tableRow); var tdHeader = new HtmlTableCell(); tdHeader.Attributes.Add("class", "DDLightHeader"); tdHeader.InnerText = column.DisplayName; // add header cell to row tableRow.Controls.Add(tdHeader); var tdData = new HtmlTableCell(); var dynamicControl = new DynamicControl(Mode); dynamicControl.DataField = column.Name; dynamicControl.ValidationGroup = this.ValidationGroup; tdData.Controls.Add(dynamicControl); // add data cell to row tableRow.Controls.Add(tdData); } } } protected void Label_PreRender(object sender, EventArgs e) { Label label = (Label)sender; DynamicControl dynamicControl = (DynamicControl)label.FindControl("DynamicControl"); FieldTemplateUserControl ftuc = dynamicControl.FieldTemplate as FieldTemplateUserControl; if (ftuc != null && ftuc.DataControl != null) label.AssociatedControlID = ftuc.DataControl.GetUniqueIDRelativeTo(label); } public class _NamingContainer : Control, INamingContainer { }
Which is what I will base the Accordian on obviousely I could use the Accordian fromt eh AJAX control toolkit but I facy trying the JuiceUI accordian as it uses jQuery UI :)
You also need this:
public class AdvancedEntityTemplateFactory : System.Web.DynamicData.EntityTemplateFactory { public override string BuildEntityTemplateVirtualPath(string templateName, DataBoundControlMode mode) { string path = base.BuildEntityTemplateVirtualPath(templateName, mode); if (File.Exists(HttpContext.Current.Server.MapPath(path))) return path; return path.Replace("_" + mode.ToString(), ""); } public override EntityTemplateUserControl CreateEntityTemplate(MetaTable table, DataBoundControlMode mode, string uiHint) { var et = table.GetAttribute<EntityUIHintAttribute>(); if (et != null && !String.IsNullOrEmpty(et.UIHint)) return base.CreateEntityTemplate(table, mode, et.UIHint); return base.CreateEntityTemplate(table, mode, uiHint); } public override string GetEntityTemplateVirtualPath(MetaTable table, DataBoundControlMode mode, string uiHint) { var et = table.GetAttribute<EntityUIHintAttribute>(); if (et != null && !String.IsNullOrEmpty(et.UIHint)) return base.GetEntityTemplateVirtualPath(table, mode, et.UIHint); return base.GetEntityTemplateVirtualPath(table, mode, uiHint); } }
Which is used like this:
// add new entity template factory that works with single files also DefaultModel.EntityTemplateFactory = new AdvancedEntityTemplateFactory();
in the Global.asax.cs to add advanced features to entity templates the main feature is that you only need one EntityTemplate (Default) for all the states (i.e. ReadOnly, Edit and Insert) which my AjaxTabControl takes advantage of.
Sunday, May 13, 2012 4:10 AM -
User350138131 posted
Hi, Sjnaughton. Thank you, I'm starting to learn your decision
Sunday, May 13, 2012 4:35 AM -
User-330204900 posted
As soon as I get a momnet I will get the accordian working too.
Sunday, May 13, 2012 8:11 AM -
User-330204900 posted
Just added new Wijmo Tabs and Accordion sample to my blog here Creating a Tabbed Entity Template using Wijmo Open for Juice UI code download at bottom of the article.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Saturday, May 26, 2012 9:47 AM -
User350138131 posted
Hi, Steve.
Sorry for the long silence. I was not feeling well.
Thank you. This is an excellent and edifying work. Based on your example I built Tabbed Entity Template, which can be used by Default? ie if there is no GroupNamesAttribute, and in the absence GroupAttribute. I also added a radio button which allows you to choose between the Tabs and Accordion in real time. The only problem, juice.js not want to work with EnablePartialRendering = "false". Therefore, instead of using the Juice, I wrote a couple of lines on javascript and everything got better. (Neither the head nor the headache)
Thanks again, Steve.P.S.
bja58 probably forgot about this ThreadMonday, September 10, 2012 5:02 AM