Filter Custom Image Selector by Album?

Posted by Community Admin on 05-Aug-2018 06:16

Filter Custom Image Selector by Album?

All Replies

Posted by Community Admin on 22-Mar-2011 00:00

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

Posted by Community Admin on 22-Mar-2011 00:00

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!

Posted by Community Admin on 22-Mar-2011 00:00

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

Posted by Community Admin on 22-Mar-2011 00:00

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

Posted by Community Admin on 22-Mar-2011 00:00

Thanks, Ivan.

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

Great stuff!

- William

Posted by Community Admin on 23-Mar-2011 00:00

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();
    

Posted by Community Admin on 31-Mar-2011 00:00

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

Posted by Community Admin on 07-Apr-2011 00:00

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


Posted by Community Admin on 13-Apr-2011 00:00

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 >>

Posted by Community Admin on 13-Apr-2011 00:00

Yes, it has runat="server" as an attribute. I will open a support ticket to upload the project.

This thread is closed