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

Forums / Sitefinity SDK / Filter Custom Image Selector by Album?

Filter Custom Image Selector by Album?

10 posts, 1 answered
  1. William
    William avatar
    108 posts
    Registered:
    15 Feb 2011
    22 Mar 2011
    Link to this post
    Hey Telerik folks (specifically Ivan),

    Really enjoyed this post and am happily moving along with images in both blogs and news.  I was wondering, though, if there was an easy method of filtering those images shown by album.  In other words, I have tens of images in the system and don't really want or need to see them when picking an image for blog or news posts.  All I really need is to be able to see images from a particular album in the picker.

    Anyway, any easy method for implementing that? 

    Thanks

    - William

  2. William
    William avatar
    108 posts
    Registered:
    15 Feb 2011
    22 Mar 2011
    Link to this post
    I'm assuming, perhaps, this is a FilterExpression applied to the GenericCollectionBinder that specifies an album filter on the image side.  Just don't know what the filter should look like.

    Thanks!
  3. William
    William avatar
    108 posts
    Registered:
    15 Feb 2011
    22 Mar 2011
    Link to this post
    I got it:

    FilterExpression="Visible = true AND Status = Live AND Album.Id={6DB14A9E-880C-4C8C-9FAF-06D7D71EC6FC}"

    Powerful stuff, though it seems a bit fragile.  Is there a better way to handle this filtering?

    Thanks.

    - William
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    22 Mar 2011
    Link to this post
    Hi William,

    If you use the property from the designer, this is the only way to do it. We are going to create a topic about how to use this property FilterExpression, because currently it is not officially documented and there are only samples on the forums.

    Regards,
    Ivan Dimitrov
    the Telerik team
    Answered
  5. William
    William avatar
    108 posts
    Registered:
    15 Feb 2011
    22 Mar 2011
    Link to this post
    Thanks, Ivan.

    For now, that approach works for me.  Looking forward to the continuation of your blog posts, though. 

    Great stuff!

    - William
  6. Drew Greenwell
    Drew Greenwell avatar
    66 posts
    Registered:
    11 Feb 2010
    23 Mar 2011
    Link to this post
    hey guys,

    I went through the Custom Image selector and added the option to filter by album. I default to showing the selected image and a drop down of all albums. Choosing an album hides the selected image and shows all images from that list. i plan to upload it to the marketplace for everyone to get. it currently only supports one instance on the form at a time But i'll give you the basic idea to enable the Image selector to allow filtering by an album. It should be all prettied up and submitted to the marketplace sometime next week, but I hate waiting around indefinitely on stuff so.. here you go

    Please note that I moved everything to the ImageSelector folder and adjusted the namespaces accordingly

    (part of file) SimpleImageField.ascx OnClientShow and OnClientClose were added to the rad window and and a class called txtForImageField was added to textbox.
    <telerik:RadWindowManager ID="windowManager" runat="server" Skin="Sitefinity">
           <Windows>
              <telerik:RadWindow ID="simpleImageSelector" Width="600" Height="400" NavigateUrl="~/Sitefinity/Dialog/SimpleImageSelectorDialog" runat="server" ReloadOnShow="true"
                             Modal="true" VisibleStatusbar="false" Behaviors="Close"
                             OnClientShow="OnImageSelectorClientShow" OnClientClose="OnImageSelectorClientClose" >
                            </telerik:RadWindow>
                        </Windows>
                    </telerik:RadWindowManager>
     
                    <asp:TextBox ID="textBox" runat="server" CssClass="sfTxt txtForImageField" />



    (part of file) SimpleImageField.js  (just appended to end of file)
    $ = jQuery;
    var _previousItem = null;
     
    function OnImageSelectorClientShow(sender, args) {
        if ($(".txtForImageField").length > 0 && $(".txtForImageField").val().length > 0) {
            _previousItem = $(".txtForImageField").val();
        }
        if (_previousItem != null) {
            sender.argument = _previousItem;
        }
    }
    function OnImageSelectorClientClose(sender, args) {
        _previousItem = null;
    }

    (whole file) SimpleImageSelector.ascx added a GenericCollectionBinder a dropdown for albums, and a preview image I defaulted the filterexpression on images to a filter that would show no images and added OnClientDataBound Methods
    <%@ Control Language="C#" AutoEventWireup="true" %>
     
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sitefinity" %>
     
    <sitefinity:ResourceLinks ID="resourcesLinks" runat="server">
        <sitefinity:ResourceFile JavaScriptLibrary="JQuery">
        </sitefinity:ResourceFile>
    </sitefinity:ResourceLinks>
     
    <select name="albumList" id="albumList" class="albumList" runat="server">
    </select><img alt="loading albums.." class="loadingAlbums" src="/images/loading.gif" />
     
    <ul id="imageList" class="imageList" runat="server">
    </ul><img alt="loading images.." class="loadingImages" style="display:none;" src="/images/loading.gif" />
     
    <sitefinity:GenericCollectionBinder ID="albumListBinder" runat="server"
            TargetId="albumList"
            ServiceUrl="~/Sitefinity/Services/Content/AlbumService.svc/"       
            BindOnLoad="false"        
            DataKeyNames="Id"
            DataMembers="Id, Title" OnClientDataBound="OnAlbumsDataBound">
            <Containers>           
                <sitefinity:BinderContainer ID="selectOptionContainer"  runat="server" TemplateHolderTag="Select" RenderContainer="false">
                  <option sys:value="{{Id}}">{{Title}}</option>
                </sitefinity:BinderContainer>
            </Containers>
        </sitefinity:GenericCollectionBinder>
     
    <sitefinity:GenericCollectionBinder ID="imageListBinder" runat="server"
            TargetId="imageList"
            ServiceUrl="~/Sitefinity/Services/Content/ImageService.svc/"
            FilterExpression="Parent.Id == 00000000-0000-0000-0000-000000000000"
            OnClientDataBound = "OnImagesDataBound"
            BindOnLoad="false"        
            DataKeyNames="Id"
            DataMembers="Id, Title, ThumbnailUrl" CssClass="imageListBinder">
            <Containers>           
                <sitefinity:BinderContainer ID="imageTitleContainer" runat="server" RenderContainer="false">
                    <li><div style="float:left; margin: 10px 10px 10px 10px; padding: 10px">
                        <a href="javascript:void(0);" class="sf_binderCommand_selectImage">
                            <img sys:src="{{ThumbnailUrl}}" />
                        </a>
                        <div>{{Title}}</div>
                        </div>
                    </li>               
                </sitefinity:BinderContainer>
            </Containers>
    </sitefinity:GenericCollectionBinder>
    <div class="previewImage" style="display:none;">
        <h3>Current Image</h3>
        <img alt="preview" src="" />
    </div>

    (whole file) SimpleImageselector.js added the albumBinder and appended some jQuery to the end of the file
    Type.registerNamespace("SitefinityWebApp.ImageSelector");
     
    SitefinityWebApp.ImageSelector.SimpleImageSelector = function (element) {
        SitefinityWebApp.ImageSelector.SimpleImageSelector.initializeBase(this, [element]);
     
        this._binder = null;
        this._binderAlbum = null;
        this._onLoadDelegate = null;
        this._onUnloadDelegate = null;
        this._binderCommandDelegate = null;
        this._binderAlbumCommandDelegate = null;
        this._selectedImageUrl = null;
    }
     
    SitefinityWebApp.ImageSelector.SimpleImageSelector.prototype =
    {
        initialize: function () {
            SitefinityWebApp.ImageSelector.SimpleImageSelector.callBaseMethod(this, "initialize");
     
            this._onLoadDelegate = Function.createDelegate(this, this._onLoad);
            Sys.Application.add_load(this._onLoadDelegate);
            this._onUnloadDelegate = Function.createDelegate(this, this._onUnload);
            Sys.Application.add_unload(this._onUnloadDelegate);
            this._binderCommandDelegate = Function.createDelegate(this, this._binderCommand);
            this._binderAlbumCommandDelegate = Function.createDelegate(this, this._binderAlbumCommand);
        },
     
        dispose: function () {
            SitefinityWebApp.ImageSelector.SimpleImageSelector.callBaseMethod(this, "dispose");
     
            Sys.Application.remove_load(this._onLoadDelegate);
            if (this._onLoadDelegate) {
                delete this._onLoadDelegate;
            }
            Sys.Application.remove_load(this._onUnloadDelegate);
            if (this._onUnloadDelegate) {
                delete this._onUnloadDelegate;
            }
        },
     
        /* -------------------- public methods ------------ */
     
        /* -------------------- events -------------------- */
     
        /* -------------------- event handlers ------------ */
     
        _onLoad: function (sender, args) {
            this.get_binder().add_onItemCommand(this._binderCommandDelegate);
            this.get_binderAlbum().add_onItemCommand(this._binderAlbumCommandDelegate);
            this.get_binder().DataBind();
            this.get_binderAlbum().DataBind();
        },
     
        _onUnload: function (sender, args) {
            this.get_binder().remove_onItemCommand(this._binderCommandDelegate);
            this.get_binderAlbum().remove_onItemCommand(this._binderAlbumCommandDelegate);
        },
     
        _binderCommand: function (sender, args) {
            if (args.get_commandName() == "selectImage") {
                var imageUrl = args.get_dataItem().ThumbnailUrl;
                this.set_selectedImageUrl(imageUrl);
                $(".previewImage img").attr("src", imageUrl);
                // remove class from previously selected images
                var selected = jQuery(args.get_itemElement().parentNode).find("li.sf_selectedImage").each(function (index, element) {
                    jQuery(element).removeClass("sf_selectedImage");
                });
                // set class to currently selected image
                jQuery(args.get_itemElement()).addClass("sf_selectedImage");
            }
        },
         _binderAlbumCommand: function (sender, args) {
     
        },
     
        /* -------------------- private methods ----------- */
     
        /* -------------------- properties ---------------- */
     
        get_binder: function () {
            return this._binder;
        },
     
        set_binder: function (value) {
            this._binder = value;
        },
         
        get_binderAlbum: function () {
            return this._binderAlbum;
        },
     
        set_binderAlbum: function (value) {
            this._binderAlbum = value;
        },
     
        get_selectedImageUrl: function () {
            return this._selectedImageUrl;
        },
     
        set_selectedImageUrl: function (value) {
            this._selectedImageUrl = value;
        }
    };
     
     
    SitefinityWebApp.ImageSelector.SimpleImageSelector.registerClass("SitefinityWebApp.ImageSelector.SimpleImageSelector", Sys.UI.Control);
     
     
    $ = jQuery;
    var _theImageBinder = null;
    var _previousItem = null;
     
    function OnAlbumsDataBound(sender, commandArgs) {
        $(".albumList").prepend("<option value=''>Choose an Album</value>")
        $(".albumList").val("");
        $(".loadingAlbums").hide();
    }
     
    function OnImagesDataBound(sender, commandArgs) {
        _theImageBinder = sender;
        $(".loadingImages").hide();
    }
     
    function GetRadWindow() {
        var oWindow = null;
        if (window.radWindow)
            oWindow = window.radWindow;
        else if (window.frameElement.radWindow)
            oWindow = window.frameElement.radWindow;
        return oWindow;
    }
     
    var _initialLoad = true;
    function pageLoad() {
        if (_initialLoad) {
            var currentWindow = GetRadWindow();
            if (currentWindow.argument != null && currentWindow.argument.length > 0) {
                $(".previewImage img").attr("src", currentWindow.argument);
                $(".previewImage").show();
            } else {
                $(".previewImage").hide();
            }
             
            _initialLoad = false;
        }
    }
     
    $(document).ready(function () {
     
        $(".albumList").change(function () {
            if ($(this).val() != "") {
                $(".previewImage").hide();
                $(".loadingImages").show();
                if (_theImageBinder != null) {
                    _theImageBinder.set_filterExpression("Parent.Id == " + $(".albumList").val());
                    _theImageBinder.DataBind();
                    $(".imageList").show();
                } else {
                    alert('Binder not found');
                }
            } else {
                $(".imageList").hide();
                $(".previewImage").show();
            }
        });
    });

    (part of file)SimpleImageSelector.cs  Added the backend logic for the AlbumBinder

        //dg this property is new
        /// <summary>
        /// Gets a reference to the RadListViewBinder control in the template
        /// </summary>      
        protected virtual GenericCollectionBinder BinderAlbum
        {
            get
            {
                return this.Container.GetControl<GenericCollectionBinder>("albumListBinder", true);
            }
        }
    public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            var descriptors = new List<ScriptDescriptor>();
            var descriptor = new ScriptControlDescriptor(typeof(SimpleImageSelector).FullName, this.ClientID);
            //dg Added
            descriptor.AddComponentProperty("binderAlbum", this.BinderAlbum.ClientID);
            descriptor.AddComponentProperty("binder", this.Binder.ClientID);
     
            descriptors.Add(descriptor);
            return descriptors.ToArray();
        }
  7. Slavo
    Slavo avatar
    295 posts
    Registered:
    24 Sep 2012
    31 Mar 2011
    Link to this post
    Hi Drew Greenwell,

    Thanks a lot for sharing this with the community. We may highlight it in a blog post once you've uploaded it to the marketplace. Please update this thread when you do.

    @William Apart from the Filter expression, another way is to change the service URL of the binder, depending on the album. There's a method in the ImageService to get child items. The URL to invoke it is:

    ~/Sitefinity/Services/Content/ImageService.svc/parent/{albumId}

    Just replace {albumId} with the real Guid. You can use the set_serviceBaseUrl() method of the binder for this.

    Regards,
    Slavo
    the Telerik team
  8. Richard Baugh
    Richard Baugh avatar
    201 posts
    Registered:
    22 Aug 2012
    07 Apr 2011
    Link to this post
    I keep getting the following error when using the GenericCollectionBinder to populate the album list:
    'System.Web.UI.HtmlControls.HtmlSelect' does not allow child controls.

    I have also looked at the following page, http://www.sitefinity.com/40/help/developers-guide/deep-dive-client-side-programming-client-binder-controls-generic-collection-binder.html, which also uses a select element to be bound to.

    If I change the select element to a div element and run the control, it will render option elements as child elements of the div element. No other elements are present so I don't understand the error.

    The site is running on version 4.0.1210. Any thoughts??

    Edit::

    Stack Trace if it helps
    [HttpException (0x80004005): 'System.Web.UI.HtmlControls.HtmlSelect' does not allow child controls.]
       System.Web.UI.EmptyControlCollection.ThrowNotSupportedException() +108
       System.Web.UI.EmptyControlCollection.Add(Control child) +4
       Telerik.Sitefinity.Web.UI.Templates.RootBuilder.CreateChildControls(Control parent, Control bindingContainer, PlaceHoldersCollection placeHolders) +579
       Telerik.Sitefinity.Web.UI.Templates.ObjectBuilder.CreateObject(Control bindingContainer, PlaceHoldersCollection placeHolders) +766
       Telerik.Sitefinity.Web.UI.Templates.ControlBuilder.CreateControl(Control bindingContainer, PlaceHoldersCollection placeHolders) +18
       Telerik.Sitefinity.Web.UI.Templates.ControlBuilder.CreateControl(Control bindingContainer) +12
       Telerik.Sitefinity.Web.UI.Templates.RootBuilder.CreateChildControls(Control parent, Control bindingContainer) +269
       Telerik.Sitefinity.Web.UI.StringTemplate.InstantiateIn(Control container, PlaceHoldersCollection placeHolders) +88
       Telerik.Sitefinity.Web.UI.StringTemplate.InstantiateIn(Control container) +7
       Telerik.Sitefinity.Web.UI.SimpleView.CreateContainer(ITemplate template) +35
       Telerik.Sitefinity.Web.UI.SimpleView.get_Container() +33
       Telerik.Sitefinity.Web.UI.SimpleView.CreateChildControls() +46
       System.Web.UI.Control.EnsureChildControls() +102
       System.Web.UI.Control.PreRenderRecursiveInternal() +42
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2496

  9. Slavo
    Slavo avatar
    295 posts
    Registered:
    24 Sep 2012
    13 Apr 2011
    Link to this post
    Hello Richard Baugh,

    Can you ensure that you have runat="server" on the select tag? That's the only thing from the top of my head, I'm not sure why you are getting this error. Please send your whole control (and template) and I'll try to debug it and help more.

    Regards,
    Slavo
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

  10. Richard Baugh
    Richard Baugh avatar
    201 posts
    Registered:
    22 Aug 2012
    13 Apr 2011
    Link to this post
    Yes, it has runat="server" as an attribute. I will open a support ticket to upload the project.
10 posts, 1 answered