+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Add Category Selector to custom widget designer

Add Category Selector to custom widget designer

10 posts, 0 answered
  1. Harry
    Harry avatar
    9 posts
    Registered:
    23 Aug 2013
    18 Mar 2014
    Link to this post

    Hi,

     I have a custom widget that displays content based on category. I defined a variable to hold the selected category as:

    public Guid CategoryId {get; set; }

    But I am unable to use Sitefinity Thunder to generate the widget designer with ready-to-use so-called hierarchicalTaxon selector. I read through this topic (http://www.sitefinity.com/developer-network/forums/general-discussions-/taxon-field-examples) but it seems not so comprehensive so I don't have a clue where to begin with.

     Any help will be highly appreciated.

    Thank you,
    Harry

  2. Kaloyan
    Kaloyan avatar
    11 posts
    Registered:
    19 Sep 2016
    21 Mar 2014
    Link to this post
    Hi Harry,

    I have just prepared a simple solution with a custom widget generated using thunder extension. It is using a HierarchicalTaxonField which loads all of the categories defined from the Sitefinity backend. Let me know if this is what you want to achieve.

    Regards,
    Kaloyan
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  3. Dave
    Dave avatar
    22 posts
    Registered:
    05 Nov 2012
    03 Apr 2014 in reply to Kaloyan
    Link to this post

    Kaloyan, 

     

    I am trying to do something similar. I want to add the category selector to the designer; however, your code seems to add it right on the widget itself. 

     Could you post your code with the category selection tool in the designer? 

     Thanks!

     - Dave

  4. Sabrie Nedzhip
    Sabrie Nedzhip avatar
    534 posts
    Registered:
    05 Dec 2016
    08 Apr 2014
    Link to this post
    Hi Dave,

    Please find attached the updated custom widget where the category selector is added to the designer as shown in the screenshot.

    Regards,
    Sabrie Nedzhip
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  5. Dave
    Dave avatar
    22 posts
    Registered:
    05 Nov 2012
    08 Apr 2014 in reply to Sabrie Nedzhip
    Link to this post

    Sabrie, 

     Great! I was able to get the selector to appear. 

    Ok - I was able to get my values to move back and forth (from javascript to control). 

    Updated 4/8/2014 5:50 EST

    I still have 2 issues. 

    1. How do I get the dialog to be bigger? My dialogue is tiny. 

    2. The Category select DONE button is unavailable. How do I enable it? Currently in testing I use Chrome and enable it via CSS... 

    I have it sort of working... I haven't tied in the loading with the other peices yet (basically loading the dynamic content categories)

    SuccessMVC.cs

    using System;
    using System.ComponentModel;
    using System.Linq;
    using System.Web.Mvc;
    using Telerik.Sitefinity.Mvc;
    using SitefinityWebApp.Mvc.Models;
    using Telerik.Sitefinity.Utilities.TypeConverters;
    using Telerik.Sitefinity.DynamicModules.Model;
    using Telerik.Sitefinity.DynamicModules;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.DynamicModules;
    using System.Collections.Generic;
    using Telerik.Sitefinity.Web.UI.Fields;
     
    namespace SitefinityWebApp.Mvc.Controllers
    {
        [ControllerToolboxItem(Name = "SuccessMVC", Title = "SuccessMVC", SectionName = "MvcWidgets"), Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesigner(typeof(SitefinityWebApp.SuccessMVCDesigner))]
        public class SuccessMVCController : Controller
        {
            /// <summary>
            /// Gets or sets the message.
            /// </summary>
      /*      public Guid[] SelectedCategories
            {
                get
                {
                    if (selectedCategories == null) selectedCategories = new Guid[] { };
                    return selectedCategories;
                }
                set { selectedCategories = value; }
            }
            */
            private Guid [] selectedCategories;
             
            public string CategoryValue
            {
                get { return string.Join(",", selectedCategories); }
                set
                {
                    var list = new List<Guid>();
                    if (value != null)
                    {
                        var guids = value.Split(',');
                        foreach (var guid in guids)
                        {
                            Guid newGuid;
                            if (Guid.TryParse(guid, out newGuid))
                                list.Add(newGuid);
                        }
                    }
                    selectedCategories = list.ToArray();
                }
            }
     
            /// <summary>
            /// This is the default Action.
            /// </summary>
            public ActionResult Index()
            {
     
            //    var x = SelectedCategories;
                DynamicModuleManager dmm = DynamicModuleManager.GetManager(string.Empty);
                dmm.Provider.SuppressSecurityChecks = true;
     
                 Type studentSuccessType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.StudentSuccess.StudentSuccess");
                 IQueryable<DynamicContent> myCollection = dmm.GetDataItems(studentSuccessType);
     
                 var listOThings = myCollection.ToList();
     
                     
                 List<SuccessMVCModel> successList = new List<SuccessMVCModel>();
                 myCollection
                     .Where( success => success.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live)
                     .ToList()
                     .ForEach(success => successList.Add(new SuccessMVCModel
                 {
                     Name = success.GetValue("Title").ToString(),
                      URL = success.GetValue("URL").ToString(),
                      Description = success.GetValue("Description").ToString(),
                      PicUrl = ((IEnumerable<Telerik.Sitefinity.Model.ContentLinks.ContentLink>)success.GetValue("DisplayPic")).ToList()[0].ChildItemAdditionalInfo
                 }));
     
                 return View(successList);
     
            }
        }
    }

    SuccessMVCDesigner.cs

     

    using System;
    using System.Linq;
    using System.Web.UI;
    using Telerik.Sitefinity.Web.UI;
    using Telerik.Sitefinity.Web.UI.ControlDesign;
    using System.Collections.Generic;
    using Telerik.Sitefinity.Web.UI.Fields;
    using Telerik.Sitefinity.Taxonomies;
    using Telerik.Sitefinity.Taxonomies.Model;
     
    namespace SitefinityWebApp
    {
        /// <summary>
        /// Represents a designer for the <typeparamref name="SitefinityWebApp.Mvc.Controllers.SuccessMVCController"/> widget
        /// </summary>
        public class SuccessMVCDesigner : ControlDesignerBase
        {
            #region Properties
            /// <summary>
            /// Obsolete. Use LayoutTemplatePath instead.
            /// </summary>
            protected override string LayoutTemplateName
            {
                get
                {
                    return string.Empty;
                }
            }
     
            /// <summary>
            /// Gets the layout template's relative or virtual path.
            /// </summary>
            public override string LayoutTemplatePath
            {
                get
                {
                    if (string.IsNullOrEmpty(base.LayoutTemplatePath))
                        return SuccessMVCDesigner.layoutTemplatePath;
                    return base.LayoutTemplatePath;
                }
                set
                {
                    base.LayoutTemplatePath = value;
                }
            }
     
            protected override HtmlTextWriterTag TagKey
            {
                get
                {
                    return HtmlTextWriterTag.Div;
                }
            }
            #endregion
     
            #region Control references
     
            protected virtual HierarchicalTaxonField CategoriesSelector
            {
                get
                {
                    return this.Container.GetControl<HierarchicalTaxonField>("CategoriesSelector", true);
                }
            }
     
     
            #endregion
     
            #region Methods
            protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
            {
                var taxaList = new List<ITaxon>();
                var manager = TaxonomyManager.GetManager();
                var categoriesTaxonomy = manager.GetTaxonomy(TaxonomyManager.CategoriesTaxonomyId);
                taxaList.AddRange(categoriesTaxonomy.Taxa);
     
                var items = manager.GetTaxa<HierarchicalTaxon>().Where(t => t.Taxonomy.Id == TaxonomyManager.CategoriesTaxonomyId).ToList();
     
     
               CategoriesSelector.TaxonomyId = TaxonomyManager.CategoriesTaxonomyId;
            }
            #endregion
     
            #region IScriptControl implementation
            /// <summary>
            /// Gets a collection of script descriptors that represent ECMAScript (JavaScript) client components.
            /// </summary>
            public override System.Collections.Generic.IEnumerable<System.Web.UI.ScriptDescriptor> GetScriptDescriptors()
            {
                var scriptDescriptors = new List<ScriptDescriptor>(base.GetScriptDescriptors());
                var descriptor = (ScriptControlDescriptor)scriptDescriptors.Last();
     
                descriptor.AddComponentProperty("CategoriesSelector", this.CategoriesSelector.ClientID);
                return scriptDescriptors;
            }
     
            /// <summary>
            /// Gets a collection of ScriptReference objects that define script resources that the control requires.
            /// </summary>
            public override System.Collections.Generic.IEnumerable<System.Web.UI.ScriptReference> GetScriptReferences()
            {
                var scripts = new List<ScriptReference>(base.GetScriptReferences());
                scripts.Add(new ScriptReference(SuccessMVCDesigner.scriptReference));
                return scripts;
            }
            #endregion
     
            #region Private members & constants
            public static readonly string layoutTemplatePath = "~/SuccessMVCDesigner.ascx";
            public const string scriptReference = "~/SuccessMVCDesigner.js";
            #endregion
        }
    }

    SuccessMVCDesigner.js

    Type.registerNamespace("SitefinityWebApp");
     
    SitefinityWebApp.SuccessMVCDesigner = function (element) {
        /* Initialize Message fields */
        this._message = null;
        this._CategoriesSelector = null;
        /* Calls the base constructor */
        SitefinityWebApp.SuccessMVCDesigner.initializeBase(this, [element]);
    }
     
    SitefinityWebApp.SuccessMVCDesigner.prototype = {
        /* --------------------------------- set up and tear down --------------------------------- */
        initialize: function () {
            /* Here you can attach to events or do other initialization */
            SitefinityWebApp.SuccessMVCDesigner.callBaseMethod(this, 'initialize');
        },
        dispose: function () {
            /* this is the place to unbind/dispose the event handlers created in the initialize method */
            SitefinityWebApp.SuccessMVCDesigner.callBaseMethod(this, 'dispose');
        },
     
        /* --------------------------------- public methods ---------------------------------- */
     
        findElement: function (id) {
            var result = jQuery(this.get_element()).find("#" + id).get(0);
            return result;
        },
     
        /* Called when the designer window gets opened and here is place to "bind" your designer to the control properties */
        refreshUI: function () {
            var controlData = this._propertyEditor.get_control(); /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
            var c = this.get_CategoriesSelector();
            var cats = controlData.Settings.CategoryValue;
            if (cats != null)
                c.set_value(controlData.Settings.CategoryValue.split(","));
            /* RefreshUI Message */
             
        },
     
        /* Called when the "Save" button is clicked. Here you can transfer the settings from the designer to the control */
        applyChanges: function () {
            var controlData = this._propertyEditor.get_control();
     
            /* ApplyChanges Message */
            var c = this.get_CategoriesSelector();
            var cats = c.get_value();
            if (cats != null)
                controlData.Settings.CategoryValue = c.get_value().join();
            
        },
     
        /* --------------------------------- event handlers ---------------------------------- */
     
        /* --------------------------------- private methods --------------------------------- */
     
        /* --------------------------------- properties -------------------------------------- */
     
        /* Message properties */
     
        get_CategoriesSelector: function () {
            return this._CategoriesSelector;
        },
        set_CategoriesSelector: function (value) {
            this._CategoriesSelector = value;
        }
         
       
    }
    SitefinityWebApp.SuccessMVCDesigner.registerClass('SitefinityWebApp.SuccessMVCDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);


    SuccessMVCDesigner.ascx

    <%@ Control %>
    <%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" %>
    <%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sitefinity" Namespace="Telerik.Sitefinity.Web.UI" %>
    <%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sfFields" Namespace="Telerik.Sitefinity.Web.UI.Fields" %>
     
    <sitefinity:ResourceLinks ID="resourcesLinks" runat="server">
        <sitefinity:ResourceFile Name="Styles/Ajax.css" />
    </sitefinity:ResourceLinks>
    <div id="designerLayoutRoot" class="sfContentViews sfSingleContentView" style="max-height: 400px; overflow: auto; ">
    <ol>       
        <li class="sfFormCtrl">
            <sitefinity:FormManager ID="formManager" runat="server" />
         <sitefinity:HierarchicalTaxonField ID="CategoriesSelector"
                    DisplayMode="Write"
                    BindOnServer="false"
                    runat="server"
                    WebServiceUrl="~/Sitefinity/Services/Taxonomies/HierarchicalTaxon.svc"
                    Expanded="True"
                    TaxonomyMetafieldName="Category"
                    Title="Categories"
                    AllowMultipleSelection="true"
                    ResourceClassId="TaxonomyResources"
                    HideWhenNoTaxaFound="true"
                    CssClass="sfpostCategoriesWrp" />
        <div class="sfExample"></div>
        </li>
         
    </ol>
    </div>

  6. Dave
    Dave avatar
    22 posts
    Registered:
    05 Nov 2012
    09 Apr 2014 in reply to Dave
    Link to this post

    So I have this hack going in my refreshUI method. 

            $("a[id*='doneButton'").show();

    To get the HierarchicalTaxonField to show a DONE button. 

    Still working on setting that window height !
    Seems to work alright... it's probably not the right way to do things.. 

     

    Here's the rest of my JS file: 

    Type.registerNamespace("SitefinityWebApp");
     
    SitefinityWebApp.SuccessMVCDesigner = function (element) {
        /* Initialize Message fields */
        this._message = null;
        this._CategoriesSelector = null;
        this._CategoriesDialog = null;
        /* Calls the base constructor */
        SitefinityWebApp.SuccessMVCDesigner.initializeBase(this, [element]);
    }
     
    function setWindowDimensions() {
       /* var radWindow = $(".RadWindow")
        radWindow.height("600px");
        radWindow.width("600px");
        $(".RadWindow .rwTable").height("500px");
        */
     
    }
     
    SitefinityWebApp.SuccessMVCDesigner.prototype = {
        /* --------------------------------- set up and tear down --------------------------------- */
        initialize: function () {
            /* Here you can attach to events or do other initialization */
            SitefinityWebApp.SuccessMVCDesigner.callBaseMethod(this, 'initialize');
            dialogBase.setWndHeight("600px");
            dialogBase.setWndWidth("500px");
         
        },
        dispose: function () {
            /* this is the place to unbind/dispose the event handlers created in the initialize method */
            SitefinityWebApp.SuccessMVCDesigner.callBaseMethod(this, 'dispose');
        },
     
        /* --------------------------------- public methods ---------------------------------- */
     
        findElement: function (id) {
            var result = jQuery(this.get_element()).find("#" + id).get(0);
            return result;
        },
     
        /* Called when the designer window gets opened and here is place to "bind" your designer to the control properties */
        refreshUI: function () {
            dialogBase.setWndHeight("600px");
            dialogBase.setWndWidth("500px");
            var controlData = this._propertyEditor.get_control(); /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
            var c = this.get_CategoriesSelector();
            var cats = controlData.Settings.CategoryValue;
            if (cats != null)
                c.set_value(controlData.Settings.CategoryValue.split(","));
            $("a[id*='doneButton'").show();
            /* RefreshUI Message */
          
        },
     
        /* Called when the "Save" button is clicked. Here you can transfer the settings from the designer to the control */
        applyChanges: function () {
     
            dialogBase.setWndHeight("600px");
            dialogBase.setWndWidth("500px");
            var controlData = this._propertyEditor.get_control();
     
            /* ApplyChanges Message */
            var c = this.get_CategoriesSelector();
            var cats = c.get_value();
            if (cats != null)
                controlData.Settings.CategoryValue = c.get_value().join();
            
        },
     
        /* --------------------------------- event handlers ---------------------------------- */
     
        /* --------------------------------- private methods --------------------------------- */
     
        /* --------------------------------- properties -------------------------------------- */
     
        /* Message properties */
     
        get_CategoriesSelector: function () {
            return this._CategoriesSelector;
        },
        set_CategoriesSelector: function (value) {
            this._CategoriesSelector = value;
        }
         
       
    }
    SitefinityWebApp.SuccessMVCDesigner.registerClass('SitefinityWebApp.SuccessMVCDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);

  7. Sabrie Nedzhip
    Sabrie Nedzhip avatar
    534 posts
    Registered:
    05 Dec 2016
    11 Apr 2014
    Link to this post
    Hello Dave,

    I believe we have answered your question in the support ticket you have opened.

    Regards,
    Sabrie Nedzhip
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  8. Mark
    Mark avatar
    147 posts
    Registered:
    01 Jun 2010
    26 Apr 2014
    Link to this post

    It would be great if the Telerik crew could get all of these custom selectors in the documentation!

     

  9. Steve
    Steve avatar
    3037 posts
    Registered:
    03 Dec 2008
    27 Apr 2014 in reply to Mark
    Link to this post

    Screw documentation...lets have it part of the thunder generated designer UI.

     It's pretty painful to get working...but josh's blog post is the best starting point...just needs tweaking beacuse he does string joins and splits where json is way easier

  10. Sabrie Nedzhip
    Sabrie Nedzhip avatar
    534 posts
    Registered:
    05 Dec 2016
    07 May 2014
    Link to this post
    Hello,

    Here is the link to the Josh's blog post providing detailed steps on how you can add selectors for Sitefinity content in your widgets.

    Regards,
    Sabrie Nedzhip
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
10 posts, 0 answered