Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Nik Wahlberg 639 posts 1237 karma points MVP
    Mar 17, 2010 @ 14:42
    Nik Wahlberg
    0

    Adding Contour form in XSLT

    Hi, I feel like this should be answered somewhere already but I couldn't find it on the forum. 

    How does one display a Contour form based on Form Picker in XSLT? So, I have a Document Type that has a Form Picker property on it. There doesn't seem to be a function in the umbraco.contour list to accomplish this?

    Thanks,
    Nik

  • Comment author was deleted

    Mar 17, 2010 @ 14:55

    Hi NIk rendering .net controls from xslt will not work.

  • Nik Wahlberg 639 posts 1237 karma points MVP
    Mar 17, 2010 @ 15:55
    Nik Wahlberg
    0

    Duh! I should have thought of that. Thanks for confirming that I am an idiot :) 

  • Sebastiaan Janssen 5045 posts 15476 karma points MVP admin hq
    Nov 01, 2010 @ 13:46
    Sebastiaan Janssen
    0

    Hmm... so what's the alternative? I've tried adding a richtext editor and inserting the contour form in there, but it doesn't render anything. Is there no way to do this? The contour form has to be rendered from the template? Any hacks you can think of? I suppose I could put it in an iframe or something.. 

  • Harald Ulriksen 207 posts 249 karma points
    Nov 01, 2010 @ 13:56
    Harald Ulriksen
    0

    Sebastiaan - rendering from a richtext editor (on a content page) should work just fine. Have you checked your trace using  umbdebugshowtrace=true?

    H.

  • Sebastiaan Janssen 5045 posts 15476 karma points MVP admin hq
    Nov 01, 2010 @ 14:03
    Sebastiaan Janssen
    0

    Oh.. really? Just looked at the source, this is what it outputs: 

    <p>&nbsp;</p>
     <?UMBRACO_MACRO macroAlias="umbracoContour.RenderForm" formguid="8cb1c04c-586e-458d-a1cb-5ca2dfb6f2ce" />
    <p>&nbsp;</p>
    <p>&nbsp;</p>

    No errors found  (obviously, because it "works").

  • Harald Ulriksen 207 posts 249 karma points
    Nov 01, 2010 @ 14:23
    Harald Ulriksen
    0

    What happens with other macros you put in that field? 

    When you write "I've tried adding a richtext editor and inserting the contour form in there" I assume you mean richtext editor on a content page in Umbraco and that you insert the macro on that page as you would with any other macro for use with the editor  [1]

    As Tim wrote you cannot render .net controls from XSLT. What I've done before is re-writing the xslt to a .net control, I've done this task for a few others here on the forum, using repeater and binding to a xpath query it's really not that bad. You loose some flexibility, but a lot of the output can be customized by editing the ascx page, http://our.umbraco.org/projects/developer-tools/user-control-file-editor. How long this takes and if it's a viable option for you really depends on the size and structure of your xslt. 

    H.


    [1]
    This is one my setups

    Umbraco4.0.4.2
    Contour 1.1.3.
    Runway

    Create Runway Textpage
    Insert macro - Insert form from Umbraco Countour - select form
    Save + publish

    The form is rendered as expected.

  • Comment author was deleted

    Nov 01, 2010 @ 14:25

    @Seb, I guess in the case where it doesn't work you are outputting the rte field from an xslt macro?

  • Sebastiaan Janssen 5045 posts 15476 karma points MVP admin hq
    Nov 01, 2010 @ 14:57
    Sebastiaan Janssen
    0

    Harald: Interesting aproach, must think about that one!

    Tim: Yup, I have some iteims that I need to be able to order differently at will, one of them is a form. I suppose I'm going to have the same problem with any old .net form that I want to output through an XSLT macro (unless it's a plain HTML form that posts to .net)?

  • Comment author was deleted

    Nov 02, 2010 @ 08:36

    @Seb, yup that's true

  • Niels Kristiansen 166 posts 382 karma points
    Nov 14, 2010 @ 23:40
    Niels Kristiansen
    0

    Hi Tim

    Could it be possible to make some kind of a .net usercontrol as a standard for contour to ex. place a form in a sidebar or another location, when it's not possible with XSLT at all?

    I need to use Contour more and more to make sidebar forms, or place a form where I normally would use the XSLT to make reusable content.

    Is it not possible at all in XSLT, what so ever, to make a form, or is it not possible with Contour?
    I mean, can't you render the form before it renders the XSLT, so that the XSLT only shows a "flat" HTML for the form - instead of a dynamically build one?

     

    Kind regards,

    Niels Kristiansen

  • Sebastiaan Janssen 5045 posts 15476 karma points MVP admin hq
    Nov 15, 2010 @ 08:31
    Sebastiaan Janssen
    0

    @Niels: You don't have to use only XSLT macro's in your sidebar right? You could just as easily add a usercontrol macro in there.

    If need be, you could even create a usercontrol that renders several XSLT macro's and your contour form. I have sample code if you need it.

  • Comment author was deleted

    Nov 15, 2010 @ 08:42

    @Niels, sounds like the macro container datatype would be usefull in your case

  • Niels Kristiansen 166 posts 382 karma points
    Nov 15, 2010 @ 12:21
    Niels Kristiansen
    0

    @Sebastiaan, that would be so nice with some sample code, if it's possible.

    @Tim, no problem making the reusable stuff with XSLT (except forms), but with the Macro Container Datatype it's not possible to set some HTML around the Contour form, without using some .net, and I'm not a .Net ninja, unfortunately. Mostly Frontend developer :)

    Thank you so much for the fast answers for both of you.

  • Sebastiaan Janssen 5045 posts 15476 karma points MVP admin hq
    Nov 17, 2010 @ 18:09
    Sebastiaan Janssen
    2

    Sorry for the late reply. So here's what I needed: I have a sidebar with "Widgets" in them. Some widgets are XSTL macro's, but I also needed to render 1 contour form in there (this is important, I can only do 1 because I can only do 1 <form runat="server">, also, another widget uses a normal HTML form, so I can't surround the whole sidebar with a <form runat="server">)

    The code below is what I came up with (the important bit here is RenderContourWidget and RenderXsltWidget). I'm sure this could be improved (and I'm open to suggestions), but it's working fine for me at the moment :-)

    WidgetContainer.ascx

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WidgetContainer.ascx.cs" Inherits="CompanyNameReplaced.UserControls.WidgetContainer" %>
    <%@ Register TagPrefix="umbraco" Namespace="umbraco.presentation.templateControls" %> <asp:PlaceHolder ID="widgetContainer" runat="server"></asp:PlaceHolder>

    WidgetContainer.ascx.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Xml.XPath;
    using umbraco.presentation.nodeFactory;
    using umbraco.presentation.templateControls;
    
    namespace CompanyNameReplaced.UserControls
    {
        public partial class WidgetContainer : UserControl
        {
            protected override void OnPreRender(EventArgs e)
            {
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
                var currentNode = Node.GetCurrent().Id;
                var startNode = currentNode > 0 ? string.Format("//node[@id = {0}]/ancestor-or-self::node//node", currentNode) : "";
    
                var sourceNodes = GetCategories(currentNode);
                if (sourceNodes.Count == 0)
                    sourceNodes.Add(currentNode.ToString());
    
                var currentWidgets = new List<string>();
                if (sourceNodes.Count > 0)
                    currentWidgets = GetWidgetsForCategories(sourceNodes);
    
                //Get global widgets if there are no widgets linked to this category
                if (currentWidgets.Count() == 0)
                {
                    var iterator = umbraco.library.GetXmlNodeByXPath(startNode + "[@nodeName = 'Widgets']/node [data [@alias = 'showGlobal'] = 1]");
                    while (iterator.MoveNext())
                    {
                        currentWidgets.Add(iterator.Current.GetAttribute("id", ""));
                    }
                }
    
                var allWidgets = GetAllWidgets();
                var sortedWidgets = SortWidgets(currentWidgets, allWidgets);
                var distinctWidgets = sortedWidgets.Distinct();
    
                foreach (var widgetId in distinctWidgets)
                {
                    var node = widgetId != "" ? string.Format("//node[@id = {0}]", widgetId) : "";
                    if (widgetId == "") continue;
    
                    var iterator = umbraco.library.GetXmlNodeByXPath(node);
                    while (iterator.MoveNext())
                    {
                        var macroType = iterator.Current.GetAttribute("nodeTypeAlias", "");
                        if (macroType == "PollWidget")
                        {
                            RenderPollWidget(iterator);
                        }
                        else
                        {
                            RenderXsltWidget(iterator, macroType);
                        }
                    }
                }  
            }
    
            private void RenderContourWidget(XPathNodeIterator iterator)
            {
                var formId = iterator.Current.SelectSingleNode("data [@alias = 'pollPicker']");
                var macro = new Macro { Alias = "umbracoContour.RenderForm" };
                macro.MacroAttributes.Add("formguid", formId);
                widgetContainer.Controls.Add(new Literal { Text = "<div class=\"block poll\"><div class=\"block-title\"><strong><span>Enquete</span></strong></div><div class=\"block-content\">" });
                widgetContainer.Controls.Add(macro);
                widgetContainer.Controls.Add(new Literal { Text = "</div></div>" });
            }
    
            private void RenderPollWidget(XPathNodeIterator iterator)
            {
                var formId = iterator.Current.SelectSingleNode("data [@alias = 'pollPicker']");
                var macro = new Macro { Alias = "Poll" };
                macro.MacroAttributes.Add("pollnodeid", formId.ToString());
                macro.MacroAttributes.Add("displayonly", "0");
                macro.MacroAttributes.Add("submitonselect", "0");
                macro.MacroAttributes.Add("hidesubmit", "0");
                macro.MacroAttributes.Add("sortresults", "0");
                macro.MacroAttributes.Add("widthtotalvotes", "0");
                macro.MacroAttributes.Add("hidequestion", "0");
                macro.MacroAttributes.Add("randompoll", "0");
                var formContainer = new HtmlForm();
                widgetContainer.Controls.Add(formContainer);
                formContainer.Controls.Add(new ScriptManager());
                formContainer.Controls.Add(new Literal { Text = "<div class=\"block poll\"><div class=\"block-title\"><strong><span>Enquete</span></strong></div><div class=\"block-content\">" });
                formContainer.Controls.Add(macro);
                formContainer.Controls.Add(new Literal { Text = "</div></div>" });
            }
    
            private void RenderXsltWidget(XPathNodeIterator iterator, string macroType)
            {
                var nodeId = iterator.Current.GetAttribute("id", "");
                var macro = new Macro { Alias = "Widget" };
                macro.MacroAttributes.Add("type", macroType);
                macro.MacroAttributes.Add("nodeid", nodeId);
                widgetContainer.Controls.Add(macro);
            }
    
            private static List<string> GetCategories(int currentNode)
            {
                var node = currentNode > 0 ? string.Format("//node[@id = {0}]", currentNode) : "";
                var iterator = umbraco.library.GetXmlNodeByXPath(node);
                var categoryList = new List<string>();
    
                while (iterator.MoveNext())
                {
                    var category = iterator.Current.SelectSingleNode("data [@alias = 'categoryPicker']");
                    if (category == null || category.ToString() == "") continue;
    
                    categoryList.AddRange(category.ToString().Split(','));
                }
                return categoryList;
            }
    
            private static List<string> GetWidgetsForCategories(IEnumerable<string> categories)
            {
                var widgetsList = new List<string>();
                foreach (var category in categories)
                {
                    var node = category != "" ? string.Format("//node[@id = {0}]", category) : "";
                    if (node == "") continue;
    
                    var iterator = umbraco.library.GetXmlNodeByXPath(node);
                    while (iterator.MoveNext())
                    {
                        var widgets = iterator.Current.Select("data [@alias = 'widgetLinks']/content/id");
                        while (widgets.MoveNext())
                            widgetsList.Add(widgets.Current.ToString());
                    }
                }
    
                return widgetsList;
            }
    
            private static List<string> GetAllWidgets()
            {
                const string node = "//node[@nodeName = 'Widgets']/node";
                var iterator = umbraco.library.GetXmlNodeByXPath(node);
                var widgetList = new List<string>();
                while (iterator.MoveNext())
                {
                    widgetList.Add(iterator.Current.GetAttribute("id", ""));
                }
    
                return widgetList;
            }
    
            private static List<string> SortWidgets(IEnumerable<string> categoryWidgets, IEnumerable<string> allWidgets)
            {
                var sortedWidgetList = new List<string>();
                foreach (var widget in allWidgets)
                {
                    var w = widget;
                    if (categoryWidgets.Contains(w))
                        sortedWidgetList.Add(w);
                }
    
                return sortedWidgetList;
            }
        }
    }
  • Carlos 338 posts 472 karma points
    Dec 30, 2010 @ 21:00
    Carlos
    0

    @Sebastiaan

    How did you get a contour form to render in your Rich Text Editor? I has the same issue where the HTML is outputting

    <?UMBRACO_MACRO
    formguid="b8159c9c-1a23-4a0a-b618-1022d5a180a5"
    macroAlias="umbracoContour.RenderForm" />
    

    I am just inserting a simple contact form inside of an my Rich Text Editor via a custom property that renders text inside the Macro.
    I tried putting the Umbraco Contour form Macro. wrapped the whole macro like this in the template

     <form ID="GeneralContactForm" runat="server">
      <umbraco:Macro Alias="ScienceAccordian" runat="server"></umbraco:Macro>
    </form>

    And that didn't work. But when I tried adding it to the default Umbraco bodyText rich text editor that is directly inside the template the form rendered fine. But not from within my Macro of ScienceAccordian which has it's own Rich Text Editor in the XSLT.

    Any help is very appreciated.

     

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Jul 10, 2013 @ 09:50
    Jeroen Breuer
    6

    Just a little update on this post. I'm on 4.7.1 and I think I found a way for XSLT to work with a Contour form. The following doesn't work like Sebastiaan said:

    Outputting an RTE which has the Contour macro:

    <xsl:value-of select="$currentPage/pageContent" disable-output-escaping="yes" />

    But I found out that rendering the Umbraco item does seem to work. So if you do this it will work:

    <xsl:value-of select="umbraco.library:Item($currentPage/@id,'pageContent')" />

    So it is possible to render a Contour form from XSLT :-).

    Jeroen

  • Comment author was deleted

    Jul 10, 2013 @ 09:52

    Nice find :)

  • David Conlisk 432 posts 1008 karma points
    Jul 30, 2013 @ 10:57
    David Conlisk
    0

    Jeroen, that works perfectly! Saved me rewriting my xslt as a user control. #h5yr

  • Niels Kristiansen 166 posts 382 karma points
    Jun 16, 2014 @ 21:53
    Niels Kristiansen
    0

    The code Jeroen wrote, will also work using the Macro Container Data Type. Not only in the RTE.

  • Kim Hansen 63 posts 144 karma points
    Jun 26, 2014 @ 14:06
    Kim Hansen
    0

    How Niels?

  • Niels Kristiansen 166 posts 382 karma points
    Jun 26, 2014 @ 20:56
    Niels Kristiansen
    0

    Hi Kim,

    Sorry for the not so informative post from my side. Here is a walkthrough:

    1. Of course, we need Contour to be installed :-)
       
    2. Next we create a Data Type under Developer (This is an example):
      Name: Macro Container
      Property editor: Macro Container
      Allowed Macros: Insert form from Umbraco Contour (Checkmark both Razor and Usercontrol)
       
    3. Save the Data Type
       
    4. Go to Settings> Document Types > Find the document type you want to have this form placed on

    5. Add a New property under Generic properties. (This is an example):
      Name: Macro Container
      Alias: mainMacroContainer
      Type: Macro Container (The one we build at 2)
      Tab: Generic Properties
       
    6. Save the Document Type
       
    7. To make it work we move over to the Content section and find the document type with the new property. I will recommend you to choose Insert form from Umbraco Contour as Razor, because then you don't have to place the runat="server" in the master page.
       
    8. Now it's time for the pretty simple XSLT magic 
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [
      <!ENTITY nbsp "&#x00A0;">
    ]>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxml="urn:schemas-microsoft-com:xslt"
        xmlns:umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="msxml umbraco.library">
    
    
      <xsl:output method="xml" omit-xml-declaration="yes"/>
    
      <xsl:param name="currentPage"/>
    
      <xsl:template match="/">
      <div class="contourForm">
          <h2>Here comes the Contour Form</h2>
          <xsl:value-of select="umbraco.library:Item($currentPage/@id,'mainMacroContainer')" />
      </div>
    
      </xsl:template>
    
    </xsl:stylesheet>
    That's it, there is really not much more in it. You can of course place the code where ever you want to in your own XSLT, but again, remember to choose Razor when you insert the form to make it less painfull.
    /Niels
  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Jul 15, 2014 @ 15:41
    Jeroen Breuer
    0

    I've upgraded an old Umbraco 4.0.3 website all the way to 7.1.4 and somehow the umbraco.library:Item trick isn't working. Maybe because it's still using legacy xslt or maybe it just doesn't work anymore in v7. I did found another way of solving this.

    From xslt it's possible to call other macros. So I've created a partial view macro file and I'm calling that from my xslt. 

    Here is the partial view macro file (called RenderRteWithMacro.cshtml):

    @inherits Umbraco.Web.Macros.PartialViewMacroPage
    @Umbraco.Field(Model.MacroParameters["propertyAlias"].ToString())

    In the macro I've added a parameter called propertyAlias.

    Here is the xslt:

    <xsl:value-of select="umbraco.library:RenderMacroContent('&lt;?UMBRACO_MACRO macroAlias=&quot;RenderRteWithMacro&quot; propertyAlias=&quot;fullText&quot; &gt;&lt;/?UMBRACO_MACRO&gt;', $currentPage/@id)" disable-output-escaping="yes" />

    So it's actually working like this now: webform masterpage -> xslt marco -> razor partial view macro -> umbraco item (called Umbraco.Field in razor).

    This again proves how flexible Umbraco is :).

    Jeroen

Please Sign in or register to post replies

Write your reply to:

Draft