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

Forums / Developing with Sitefinity / Need help with LibrarySelector in control designer

Need help with LibrarySelector in control designer

22 posts, 0 answered
  1. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    18 Oct 2012
    Link to this post
    Last time I created one of these was back in 4x and it worked for me, but I am missing something here so any help would be appreciated.

    I want to have a library selector for images in my widget designer.  Right now I get an error saying "cannot call method 'apply' of undefined".  This happens when I go to click edit on the widget to get the designer to display.

    I am doing this as an MVC widget.
    Model:
    public class ImageSliderModel
    {
        /// <summary>
        /// Gets or sets the message.
        /// </summary>
        public string Album { get; set; }
    }

    Designer (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" %>
    <%@ Register Assembly="Telerik.Sitefinity" TagPrefix="designers" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI" %>
     
    <sitefinity:ResourceLinks ID="resourcesLinks" runat="server">
        <sitefinity:ResourceFile Name="Styles/Ajax.css" />
    </sitefinity:ResourceLinks>
    <div class="sfContentViews sfSingleContentView" style="max-height: 400px; overflow: auto; ">
    <ol>       
        <li class="sfFormCtrl">
            <asp:Label runat="server" AssociatedControlID="Album" CssClass="sfTxtLbl">Album</asp:Label>
            <asp:TextBox ID="Album" CssClass="sfTxt" runat="server" ClientIDMode="Static" />
            <designers:LibrarySelector
                ID="Selector"          
                runat="server"
                TitleText="Choose an album"
                BindOnLoad="true"
                SearchBoxTitleText="Narrow by typing"
                ItemsName="images"
                ItemName="image"
                ItemType="Telerik.Sitefinity.Libraries.Model.Album"
                ServiceUrl="~/Sitefinity/Services/Content/AlbumService.svc/" >
            </designers:LibrarySelector>
        </li>
         
    </ol>
    </div>

    Designer (.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.Modules.Libraries.Web.UI;
     
    namespace SitefinityWebApp.WidgetDesigners.ImageSlider
    {
        /// <summary>
        /// Represents a designer for the <typeparamref name="SitefinityWebApp.Mvc.Controllers.ImageSliderController"/> widget
        /// </summary>
        public class ImageSliderDesigner : ControlDesignerBase
        {
            #region Properties
            /// <summary>
            /// Gets the layout template path
            /// </summary>
            public override string LayoutTemplatePath
            {
                get
                {
                    return ImageSliderDesigner.layoutTemplatePath;
                }
            }
     
            /// <summary>
            /// Gets the layout template name
            /// </summary>
            protected override string LayoutTemplateName
            {
                get
                {
                    return String.Empty;
                }
            }
     
            protected override HtmlTextWriterTag TagKey
            {
                get
                {
                    return HtmlTextWriterTag.Div;
                }
            }
            #endregion
     
            #region Control references
            /// <summary>
            /// Gets the control that is bound to the Message property
            /// </summary>
            protected virtual LibrarySelector Selector
            {
                get
                {
                    return this.Container.GetControl<LibrarySelector>("selector", true);
                }
            }
     
            #endregion
     
            #region Methods
            protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
            {
                // Place your initialization logic here
            }
            #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("selector", this.Selector.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(ImageSliderDesigner.scriptReference));
                return scripts;
            }
            #endregion
     
            #region Private members & constants
            public static readonly string layoutTemplatePath = "~/WidgetDesigners/ImageSlider/ImageSliderDesigner.ascx";
            public const string scriptReference = "~/WidgetDesigners/ImageSlider/ImageSliderDesigner.js";
            #endregion
        }
    }

    Designer (.js):
    Type.registerNamespace("SitefinityWebApp.WidgetDesigners.ImageSlider");
     
    SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner = function (element) {
        this._selector = null;
        this._doneSelectingLibraryDelegate = null;
        this._selectedAlbum = null;
     
        SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner.initializeBase(this, [element]);
    }
     
    SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner.prototype = {
        /* --------------------------------- set up and tear down --------------------------------- */
        initialize: function () {
            /* Here you can attach to events or do other initialization */
            SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner.callBaseMethod(this, 'initialize');
            this._doneSelectingLibraryDelegate = Function.createDelegate(this, this._selectLibrary);
            this._selector.add_doneClientSelection(this._doneSelectingLibraryDelegate);
        },
        dispose: function () {
            /* this is the place to unbind/dispose the event handlers created in the initialize method */
            SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner.callBaseMethod(this, 'dispose');
            this._selector.remove_doneClientSelection(this._doneSelectingLibraryDelegate);
            if (this._doneSelectingLibraryDelegate) {
                delete this._doneSelectingLibraryDelegate;
            }
        },
     
        /* --------------------------------- public methods ---------------------------------- */
     
        findElement: function (id) {
            var result = jQuery(this.get_element()).find("#" + id).get(0);
            return result;
        },
     
         
        _selectLibrary: function (items) {
            var selectedItems = this.get_selector().getSelectedItems();
            if (selectedItems != null) {
                if (selectedItems.length > 0) {
                    var selectedTitle = selectedItems[0].Title;
     
                    this.set_selectedAlbum(selectedTitle);
                    jQuery("#Album").val(selectedTitle);
                }
            }
        },
         
     
        /* 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().Settings; /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
     
            /* RefreshUI Message */
            /* jQuery(this.get_selector()).val(controlData.Album); */
            jQuery("#Album").val(controlData.Album);
        },
     
        /* 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().Settings;
     
            /* controlData.Album = jQuery(this.get_selector()).val(); */
            controlData.Album = this.get_selectedAlbum();
        },
     
     
        /* --------------------------------- properties -------------------------------------- */
     
        /* Message properties */
        get_selector: function () { return this._selector; },
        set_selector: function (value) { this._selector = value; },
     
        get_selectedAlbum: function () { return this._selectedAlbum; },
        set_selectedAlbum: function (value) { this._selectedAlbum = value; }
    }
     
    SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner.registerClass('SitefinityWebApp.WidgetDesigners.ImageSlider.ImageSliderDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);


  2. Stanislav Velikov
    Stanislav Velikov avatar
    1113 posts
    Registered:
    08 Dec 2016
    23 Oct 2012
    Link to this post
    Hi,

    When the error is "cannot call method 'apply' of undefined" then the ScriptDescriptors in the DesignerClass are incorrect or the Namespace in the javascript file doesn`t  reflect the correct namespace needed to resolve the applyChanges function form the javascript file.

    The easiest way I can reccomend is to use Sitefinity tunder ability to automatically generate MVC widget with designer and designers with content selectors to automate the process.

    Greetings,
    Stanislav Velikov
    the Telerik team
    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 Public Issue Tracking system and vote to affect the priority of the items
  3. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    02 Nov 2012 in reply to Stanislav Velikov
    Link to this post
    Stanislav,

    I guess I did not mention, but this widget was created with Thunder so I do not think it has anything to do with my namespace.  What I did was to create a widget with Thunder and then remove the Hello World stuff that it throws in.  I then added in the logic that I had posted because I cannot find a better way to automate adding a library selector to a widget.

    I have tried using the "add widget designer" part of thunder, but it never finds a list of controls for me to select.  It will sit at the select a control to add a designer to window indefinitely (I let it go for 10 minutes without a response).  I even removed the widget designer that gets installed thinking that Thunder will only show controls that do not have a designer file associated with them....no luck either.

    I do feel it has something to do with the ScriptDescriptors and particularly this line.
    descriptor.AddComponentProperty("selector", this.Selector.ClientID);

    I have tried using .AddElementProperty as well, but I get another error.  I just do not know what to do about it.  


    Note:  I also do not think it is the namespace because I can remove all my selector code and revert this widget back to the hello world text box and it will work just fine.  Somewhere along the line of dropping in the selector and properties for it I am messing up.

    Attached is a screenshot of the create designer window that I reference.
  4. Stephen2
    Stephen2 avatar
    94 posts
    Registered:
    05 Feb 2012
    04 Nov 2012 in reply to Stacey
    Link to this post
    I've not used a LibrarySelector control before in a widget, but I noticed two things that looked out of place to me:

    1. .GetControl = "selector", whilst the ASCX ID is "Selector".  Is this case sensitive?
    2. I think your commented out line "/* controlData.Album = jQuery(this.get_selector()).val(); */" is correct
    Other than that, my usual method (it's always the javascript, or the AddElementProperty instead of AddComponentProperty thing) - is to put console.logs everywhere inside the javascript file.

  5. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    05 Nov 2012 in reply to Stephen2
    Link to this post
    Stephen,

    Thanks for the comments.  I though .GetControl needed to be case sensitive to what I am sending over with the script descriptors?  I will have to check into this.
  6. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    06 Nov 2012 in reply to Stacey
    Link to this post
    I tried to use "Selector" in the .GetControl line and that had not effect so it does not look like that is the issue.
  7. Terry
    Terry avatar
    1 posts
    Registered:
    30 Nov 2012
    07 Dec 2012
    Link to this post
    I'm working through similar issues right now myself... try this:

    - Do you have an "Album" property in your controller?
    - in the javascript applyChanges and refreshUI functions, use the following:
    //in applyChanges, change to this:
    controlData.Album = this.get_selectedAlbum().get_value(); //probably want to do a .join() too, since it is probably giving you a list of values

    //in refreshUI, change to this:
    this.get_selectedAlbum().set_value(controlData.Album); //probably should do controlData.Album.split(",")


    Hope that helps.
  8. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    17 Dec 2012 in reply to Terry
    Link to this post
    Terry said:I'm working through similar issues right now myself... try this:

    - Do you have an "Album" property in your controller?
    - in the javascript applyChanges and refreshUI functions, use the following:
    //in applyChanges, change to this:
    controlData.Album = this.get_selectedAlbum().get_value(); //probably want to do a .join() too, since it is probably giving you a list of values

    //in refreshUI, change to this:
    this.get_selectedAlbum().set_value(controlData.Album); //probably should do controlData.Album.split(",")


    Hope that helps.


    I do have an "Album" property in my model.  The reason I am using the property along with the LibrarySelector is that I have not been able to set a selected property on the selector during refreshUI.  I am not even sure if that LibrarySelector has a client side selected items method to use so I prefer to take the selected album name and output it to the textbox so the user knows what the current selection is.

    I have been able to get this working again with the following changes.

    protected virtual LibrarySelector Selector
            {
                get
                {
                    return this.Container.GetControl<LibrarySelector>("Selector", true);
                }
            }
     
            protected virtual Control Album
            {
                get
                {
                    return this.Container.GetControl<Control>("Album", true);
                }
            }

    It turns out those container calls are case sensitive and I also added in the reference to "Album".

    In GetScriptDescriptors() I have these two lines
    descriptor.AddComponentProperty("selector", this.Selector.ClientID);
    descriptor.AddElementProperty("album", this.Album.ClientID);


    In the designer.js I have the following changes.
    refreshUI: function () {       
            var controlData = this._propertyEditor.get_control().Settings; /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
     
            jQuery(this.get_album()).val(controlData.Album); /* I have AllowMultipleSelection set to false on the library selector so no need to split */
        },
     
        /* 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().Settings;
     
     
            controlData.Album = this.get_selectedAlbum(); /* No need to call .val() here because this is a string property and not a full blown object of LibrarySelector */
        },


    If anyone knows how to set a selected state on the LibrarySelectors please let me know.
  9. Basem
    Basem avatar
    131 posts
    Registered:
    22 Dec 2010
    22 Apr 2013 in reply to Stacey
    Link to this post
    Did you ever get this working? I even tried using Thunder's designer wizard with a web form control, but there's no album selector available - only images, videos, docs, pages, and dynamic.
  10. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    22 Apr 2013 in reply to Basem
    Link to this post
    Basem,

    yes, I did get it working. 

    One thing to note is that when you select the album and click done you will not instantly see that the selection took.  If you save the widget settings and then come back in you will see that it does in fact grab the album.  I need to work on getting the UI to refresh after the selected album event runs, but I have not had time to look into it.
    <%@ 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" %>
    <%@ Register Assembly="Telerik.Sitefinity" TagPrefix="designers" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI" %>
     
    <sitefinity:ResourceLinks ID="resourcesLinks" runat="server">
        <sitefinity:ResourceFile Name="Styles/Ajax.css" />
    </sitefinity:ResourceLinks>
    <div class="sfContentViews sfSingleContentView" style="max-height: 400px; overflow: auto; ">
    <ol>       
        <li class="sfFormCtrl">
            <asp:Label ID="Label1" runat="server" AssociatedControlID="Library" CssClass="sfTxtLbl">Library</asp:Label>
            <asp:TextBox ID="Library" runat="server" CssClass="sfTxt" ClientIDMode="Static" />
            <designers:LibrarySelector
                ID="Selector"          
                runat="server"
                TitleText="Choose a library"
                BindOnLoad="true"
                SearchBoxTitleText="Narrow by typing"
                ItemsName="images"
                ItemName="image"
                ItemType="Telerik.Sitefinity.Libraries.Model.Album"
                ServiceUrl="~/Sitefinity/Services/Content/AlbumService.svc/"
                AllowMultipleSelection="false" >
            </designers:LibrarySelector>
        </li>
         
    </ol>
    </div>


    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.Modules.Libraries.Web.UI;
     
    namespace SitefinityWebApp.WidgetDesigners.Orbit
    {
        /// <summary>
        /// Represents a designer for the <typeparamref name="SitefinityWebApp.Mvc.Controllers.OrbitController"/> widget
        /// </summary>
        public class OrbitDesigner : ControlDesignerBase
        {
            #region Properties
            /// <summary>
            /// Gets the layout template path
            /// </summary>
            public override string LayoutTemplatePath
            {
                get
                {
                    return OrbitDesigner.layoutTemplatePath;
                }
            }
     
            /// <summary>
            /// Gets the layout template name
            /// </summary>
            protected override string LayoutTemplateName
            {
                get
                {
                    return String.Empty;
                }
            }
     
            protected override HtmlTextWriterTag TagKey
            {
                get
                {
                    return HtmlTextWriterTag.Div;
                }
            }
            #endregion
     
            #region Control references
            /// <summary>
            /// Gets the control that is bound to the Selector property
            /// </summary>
            protected virtual LibrarySelector Selector
            {
                get
                {
                    return this.Container.GetControl<LibrarySelector>("Selector", true);
                }
            }
     
            /// <summary>
            /// Gets the control that is bound to the Library property
            /// </summary>
            protected virtual Control Library
            {
                get
                {
                    return this.Container.GetControl<Control>("Library", true);
                }
            }
     
            #endregion
     
            #region Methods
            protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
            {
                // Place your initialization logic here
            }
            #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("selector", this.Selector.ClientID);
                descriptor.AddElementProperty("library", this.Library.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(OrbitDesigner.scriptReference));
                return scripts;
            }
            #endregion
     
            #region Private members & constants
            public static readonly string layoutTemplatePath = "~/WidgetDesigners/Orbit/OrbitDesigner.ascx";
            public const string scriptReference = "~/WidgetDesigners/Orbit/OrbitDesigner.js";
            #endregion
        }
    }


    Type.registerNamespace("SitefinityWebApp.WidgetDesigners.Orbit");
     
    SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner = function (element) {
        this._selector = null;
        this._library = null;
        this._doneSelectingLibraryDelegate = null;
        this._selectedLibrary = null;
     
        SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner.initializeBase(this, [element]);
    }
     
    SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner.prototype = {
        /* --------------------------------- set up and tear down --------------------------------- */
        initialize: function () {
            /* Here you can attach to events or do other initialization */
            SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner.callBaseMethod(this, 'initialize');
     
                this._doneSelectingLibraryDelegate = Function.createDelegate(this, this._selectLibrary);
                this._selector.add_doneClientSelection(this._doneSelectingLibraryDelegate);
        },
        dispose: function () {
            /* this is the place to unbind/dispose the event handlers created in the initialize method */
            SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner.callBaseMethod(this, 'dispose');
     
                this._selector.remove_doneClientSelection(this._doneSelectingLibraryDelegate);
                if (this._doneSelectingLibraryDelegate) {
                    delete this._doneSelectingLibraryDelegate;
                }
        },
     
        /* --------------------------------- public methods ---------------------------------- */
     
        findElement: function (id) {
            var result = jQuery(this.get_element()).find("#" + id).get(0);
            return result;
        },
     
        _selectLibrary: function (items) {
            var selectedItems = this.get_selector().getSelectedItems();
            if (selectedItems != null) {
                if (selectedItems.length > 0) {
                    var selectedTitle = selectedItems[0].Title;
                    this.set_selectedLibrary(selectedTitle);
                }
            }
        },
     
        /* 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().Settings; /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
     
            /* RefreshUI Message */
            jQuery(this.get_library()).val(controlData.Library);
        },
     
        /* 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().Settings;
     
            controlData.Library = this.get_selectedLibrary();
        },
     
     
        /* --------------------------------- properties -------------------------------------- */
     
        /* Message properties */
        get_library: function () { return this._library; },
        set_library: function (value) { this._library = value; },
     
        get_selector: function () { return this._selector; },
        set_selector: function (value) { this._selector = value; },
     
        get_selectedLibrary: function () { return this._selectedLibrary; },
        set_selectedLibrary: function (value) { this._selectedLibrary = value; }
     
    }
     
    SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner.registerClass('SitefinityWebApp.WidgetDesigners.Orbit.OrbitDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
  11. Basem
    Basem avatar
    131 posts
    Registered:
    22 Dec 2010
    22 Apr 2013 in reply to Stacey
    Link to this post
    Thanks for this! I will try this out and have a look at that issue.
  12. Basem
    Basem avatar
    131 posts
    Registered:
    22 Dec 2010
    24 Apr 2013 in reply to Basem
    Link to this post
    I struggled a bit with this so I went another direction... I used Thunder to create a "Designer for existing widget" and added a Dynamic Content Selector for my Guid property. Then I modified the designer from there:

    Template:
    Change Title.Value to Title in FlatSelector's DataMembersInfo
    Change ItemType to "Telerik.Sitefinity.Libraries.Model.Album"
    Change ServiceUrl to "~/Sitefinity/Services/Content/AlbumService.svc/" 

    Class:
    Comment this.AlbumIdItemSelector.ConstantFilter = "Visible=true" in InitializeControls

    JS:
    Replace selectedItem.OriginalContentId to selectedItem.Id

    Works perfectly and no issue about the selection not showing the first time. I think this would work the same way for other types too if not offered directly in Thunder.

    Also since Thunder cannot find MVC widgets, I would create a dummy User Control, use Thunder with the above steps on it, then add the designer attribute on the MVC widget class.

  13. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    24 Apr 2013 in reply to Basem
    Link to this post
    Basem,

    Thanks for posting your solution.  I tried it out and I do like how it handles the selection process.  The biggest issue as I mentioned was that with my LibrarySelector was the UI was not refreshing after the done selecting event of the button so even though the users clicked done they did not have any visual feedback that it was in fact selected.  The other issue was that there were two scroll bars (one for the library selector and one for the overall widget designer) that made this process very painful.

    With what you posted the UI starts off minimalist until the point a user needs to select a new library.  I like how the FlatSelector switches visibility of panels instead of forcing a lot of scrolling.

    Thanks again for posting this.  I think I will be playing with this more in some of my widgets.
  14. codicezerouno
    codicezerouno avatar
    21 posts
    Registered:
    02 Feb 2009
    21 May 2013 in reply to Stacey
    Link to this post
    Hi guys,
    I follow your solution and I get it working but how do you select nested libraries?
  15. Marin Atanasov
    Marin Atanasov avatar
    62 posts
    Registered:
    24 Sep 2012
    24 May 2013
    Link to this post
    Hello guys,

    Also since Thunder cannot find MVC widgets, I would create a dummy User Control, use Thunder with the above steps on it, then add the designer attribute on the MVC widget class.
    Thunder should be able to find MVC controllers. Attached is a screenshot of the designer wizard showing the found MVC controller.
    1. Create your MVC controller. You can use Thunder for this.
    2. If you have used Thunder for step 1, delete the designer and remove the ControlDesigner attribute from the controller.
    3. Build your project. This is mandatory because we scan the assembly, not the files in the project.

    I follow your solution and I get it working but how do you select nested libraries?
    Nested libraries have been added in Sitefinity 6.0. To make a selector for them, you can make a dynamic content selector and follow these steps:

    Template:
    Change the FlatSelector to FolderSelector but keep its ID:
    <sitefinity:FolderSelector ID="Flat Selector ID" runat="server"
        AllowMultipleSelection="false"
        BindOnLoad="false"
        AllowSearch="true"
        ShowButtonsArea="false"
        WebServiceUrl="~/Sitefinity/Services/Content/AlbumService.svc/folders/" />
    Replace "Flat Selector ID" with the ID of your FlatSelector.

    - For a video library selector, replace WebServiceUrl with "~/Sitefinity/Services/Content/VideoLibraryService.svc/folders/".
    - For a document library selector, replace WebServiceUrl with "~/Sitefinity/Services/Content/DocumentLibraryService.svc/folders/".

    Class:
    - Change the type of the selector in the return type of the property and the GetControl method inside it from FlatSelector to FolderSelector.
    - Go to InitializeControls and remove the UICulture logic for the FlatSelector because FolderSelector does not have that property.

    JavaScript:
    - Change .OriginalContentId to .Id
    - Comment itemSelector._selectorSearchBox.get_binderSearch()._multilingual = false;

    Attached is a sample widget designer that has an album selector for the AlbumId widget property.

    Please let me know if I can be of further help.

    All the best,
    Marin Atanasov
    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 Public Issue Tracking system and vote to affect the priority of the items
  16. Stacey
    Stacey avatar
    291 posts
    Registered:
    18 Oct 2012
    09 Sep 2013 in reply to Marin Atanasov
    Link to this post
    I updated one of my older slideshow widgets to use this selector over the flat selector, but I had trouble getting the guid to persist from the designer to the control.  After changing these two lines it started working for me.

    refreshUI: function () {
            var controlData = this._propertyEditor.get_control().Settings; //Added the .Settings
     
    .......
     
     applyChanges: function () {
            var controlData = this._propertyEditor.get_control().Settings; //Added the .Settings
     
    ....
  17. Roberto Modica
    Roberto Modica avatar
    146 posts
    Registered:
    08 Feb 2008
    30 Dec 2013
    Link to this post
    Thanks to everyone in this thread, and great Job Basem!

    Does anyone know how to get the library title to appear instead of the GUID in the selector?
  18. Stanislav Velikov
    Stanislav Velikov avatar
    1113 posts
    Registered:
    08 Dec 2016
    02 Jan 2014
    Link to this post
    Hi,

    To control what will be the selected value from the selector change the property retrieved upon selection in the javascript component of the control, I refer to the control sample attached by Marin in a post above, the highlighted property is retrieving the Id of the selected library, change the property to Title to save titles for libraries.

        /* 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();
     
            var selectedAlbumId = this.get_AlbumIdSelectedItems()[0];
            if (selectedAlbumId != null) {
                controlData.AlbumId = selectedAlbumId.Id;
            }
        },


    Regards,
    Stanislav Velikov
    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 Public Issue Tracking system and vote to affect the priority of the items
  19. Roberto Modica
    Roberto Modica avatar
    146 posts
    Registered:
    08 Feb 2008
    06 Jan 2014 in reply to Stanislav Velikov
    Link to this post
    Hi Stanislav,

    Not sure if i am understanding correctly.  I still want to select the GUID, i just want to show the title in the UI instead of an ugly GUID.  Will this code change the selection process? (i.e. select a title used to query for a library instead of a GUID) as that's not what i want to do.

    I simply want to select a GUID as it is, but in the UI just show the title of the library selected.  Do i need another property in my user control (LibraryTitle) and i also set that and use that in the designer, is that how it works?

    Thanks,

    Rob
  20. Stanislav Velikov
    Stanislav Velikov avatar
    1113 posts
    Registered:
    08 Dec 2016
    09 Jan 2014
    Link to this post
    Hi,

    If you are using the sample widget designer with library selector attached by Marin Atanasov add updates in the AlbumWidgetDesigner.js in the private function change the selectedItem.Title property to be loaded in the selector label once a user selects a library
    _AlbumIdDoneSelecting: function (sender, args) {
            var selectedItem = this.get_AlbumIdSelectedItems()[0];
            if (selectedItem != null) {
                this.get_selectedAlbumId().innerHTML = selectedItem.Title;
                this.get_selectButtonAlbumId().innerHTML = '<span class=\"sfLinkBtnIn\">Change</span>';
            }
            this._selectAlbumIdDialog.dialog("close");
            jQuery("#designerLayoutRoot").show();
            dialogBase.resizeToContent();
        },
    Update the functions refreshUI(fired when you click Edit on the widget to open the designer) and applyChanges (once the designer is saved) by using the property AlbumTitle which is added as additional property in the widget class
    public string AlbumTitle { get; set; }

    The refreshUI and applyChanges updates.
    refreshUI: function () {
            var controlData = this._propertyEditor.get_control(); /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
     
            if (controlData.AlbumId) {
                this.get_selectedAlbumId().innerHTML = controlData.AlbumTitle;
                this.get_selectButtonAlbumId().innerHTML = '<span class=\"sfLinkBtnIn\">Change</span>';
            }
        },
     
        applyChanges: function () {
            var controlData = this._propertyEditor.get_control();
     
            var selectedAlbumId = this.get_AlbumIdSelectedItems()[0];
            if (selectedAlbumId != null) {
                controlData.AlbumId = selectedAlbumId.Id;
                controlData.AlbumTitle = selectedAlbumId.Title;
            }
        },
    In the Widget class refer to the attached Widgets.zip that contains the whole implementation of the control and the designer.

    Here is a video of the result.

    Regards,
    Stanislav Velikov
    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 Public Issue Tracking system and vote to affect the priority of the items
  21. Anup
    Anup avatar
    3 posts
    Registered:
    24 Jun 2014
    22 Aug 2014 in reply to Stanislav Velikov
    Link to this post

    How to get PageId of a page  in a module using Javascript & display all related items except the page which i clicked upon in a flat selector..

  22. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    08 Dec 2016
    27 Aug 2014
    Link to this post
    Hello,

    For future questions not related to an already opened thread, please, open a new one. This way the responses and the thread could be easily found when someone else looks for assistance in the forum regarding the same topic.

    Depending on the way you present the items in the flat selector you should be able to get the item's id. Moreover, the objects data is returned from the binder and Id is available property in the item. Then the related data could be retrieved using the service: /restapi/sitefinity/related-data/child-items?take={Number: int}&ParentItemId={ParentItemId:Guid}&ParentItemType={ItemType: Telerik.Sitefinity.Pages.Model.PageNode}&ParentProviderName={Provider}&FieldName={FieldName}&Status=&skip=0
    Instance:
    http://localhost:60876/restapi/sitefinity/related-data/child-items?take=10&ParentItemId=36cb9531-42a6-6e3b-a242-ff000028b6c9&ParentItemType=Telerik.Sitefinity.Pages.Model.PageNode&ParentProviderName=OpenAccessDataProvider&FieldName=PressReleases&Status=&skip=0

    You can create the request using jQuery ajax calls.

    Regards,
    Nikola Zagorchev
    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
     
22 posts, 0 answered