A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

How to customise HTML output of XFormStatistics?

Vote:
 
Could anyone with more experience than me in "skinning" EPiServer controls give me some pointers on how I can customise the output of the HTML that XFormStatistics generates? Do I have to try and buffer the output on a pre-render event and then do string manipulation, or is there a better way? The output will be displayed on every page (within the template), so I need an efficient solution. Or, is XFormStatisitics not really suited to customised output, and if so, should I be extracting form results another way? Any ideas appreciated! /\dam
#13090
Jun 26, 2007 13:47
Vote:
 
Hi Adam! I'd use a ControlAdapter to override rendering, either by implementing a custom CreateChildControls() or a RenderChildren() and take care of the rendering myself. The "standard" CreateChildControls() adds childcontrols of type Table / Row / Cell, every voted alternative is represented by one row, where Cell1 holds the option name, Cell2 an array of images, either showing a total number of votes or the percentage and Cell3 the number/percentage. Regards, Johan Olofsson EPiServer AB
#15396
Jun 26, 2007 15:55
Vote:
 
Thanks Johan, I will have a play! Do you think there is any appreciable overhead to using this method? As noted, I'd be doing it for almost every page view across the site. /\dam
#15397
Jun 26, 2007 17:35
Vote:
 
The overhead should be minimal, as your rendering or createchildcontrols will be called _instead_ of the original controls methods. The alternative to parse the generated html and make inline modifications would probably be a lot less efficient performance wise. /johan
#15398
Jun 26, 2007 22:24
Vote:
 
I'm not having much luck implementing this unfortunately :-( Does anyone have a code sample they can point me to, showing how to override child controls of an EPiServer control? Thanks! /\dam
#15399
Jul 04, 2007 13:48
Vote:
 
Nah, you shouldn't have to "override" (technically speaking), rather provide a substitue control to take care of the rendering of another control. Check out the MSDN documentation on Control Adapters. If I can get them time, I'll try and see if I can hack a small sample for you. /johan
#15400
Jul 04, 2007 14:03
Vote:
 
Ok, heres a small sample showing how to overide default rendering of XFormStatistics. 1) Compile the below code to an assembly and put it in the EPiServer's /bin directory Note, you'll need to add references to the following assemblies: EPiServer.dll, EPiServer.XForms.dll andd EPiServer.BaseLibrary.dll using System; using System.Web; using System.Web.UI; using System.Web.UI.Adapters; using System.Web.UI.WebControls; using EPiServer; using EPiServer.WebControls; using EPiServer.XForms; using EPiServer.XForms.WebControls; namespace XFormX { public class RenderSample : ControlAdapter { protected override void CreateChildControls() { XFormStatistics xformStat = Control as XFormStatistics; xformStat.Controls.Add( new LiteralControl("

This is rendered using a ControlAdapter

")); foreach(XFormData formData in xformStat.Statistics) { xformStat.Controls.Add( new LiteralControl(String.Format( "Dateposted: {0}
", formData.DatePosted))); } xformStat.Controls.Add( new LiteralControl( "

" ) ); } } }
2) Then, save the below xml into a file named 'something'.browser into the folder App_Browsers of your EPiServer directory. Create the App_Browsers directory if it doesnt alread exist. Now, all rendering of XFormStatistics is done through our controladapter, which simply lists the dateposted for every post of the form - you may want to change this logic :) Regards, Johan Olofsson EPiServer AB
#15401
Jul 04, 2007 14:29
Vote:
 
This is incredibly helpful, thank you very much for taking the time to post an example! /\dam
#15402
Jul 05, 2007 10:30
Vote:
 
I can pretty much do what I need to do now, so thanks again. I was a little surprised at the internal data structure of XFormStatistics though. From the name, I expected it would store *totals* rather than individual responses. To output the results I am therefore looping through each FormData object, populating a SortedList as I go, and then outputting the totals from my SortedList. Is this a reasonable way of doing it, or am I missing a data structure hidden away somewhere in XFormStatistics?! :-) /\dam
#15403
Jul 05, 2007 13:25
Vote:
 
Yes, thats how XFormStatistics work its magic too :) It however internally uses an dictionary of FormFieldStatistic objects to keep track of votes. Below is a slight modification of the controladapter that presents the vote count for each field in the form: using System; using System.Web; using System.Web.UI; using System.Web.UI.Adapters; using System.Web.UI.WebControls; using System.Collections.Generic; using EPiServer; using EPiServer.WebControls; using EPiServer.XForms; using EPiServer.XForms.WebControls; namespace XFormX { public class RenderSample : ControlAdapter { protected override void CreateChildControls() { XFormStatistics xformStat = Control as XFormStatistics; Dictionary formFields = new Dictionary(); foreach(XFormData d in xformStat.Statistics) { foreach(System.Xml.XmlNode n in d.Data.GetElementsByTagName( "instance" )[0].ChildNodes) { String name = n.LocalName; String val = HttpContext.Current.Server.HtmlEncode( n.InnerText ); if(!formFields.ContainsKey( name )) { FormFieldStatistic tmpStatistic = new FormFieldStatistic( name ); tmpStatistic.AddEmptyVote( val ); formFields.Add( n.LocalName, tmpStatistic ); } ( (FormFieldStatistic)formFields[name] ).AddVote( val ); } } // do something with foreach(string key in formFields.Keys) { FormFieldStatistic ffs = formFields[key]; Control.Controls.Add( new LiteralControl(String.Format("{0} : {1} votes
", ffs.FieldName, ffs.Votes.Count ))); } } } }
/johan
#15404
Jul 05, 2007 14:11
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.