Dynamic Dropdown (ChoiceFieldElement) in Custom Module - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

Dynamic Dropdown (ChoiceFieldElement) in Custom Module

  • Dynamic Dropdown (ChoiceFieldElement) in Custom Module
  • Hey all,

    I've placed a dropdown list in my custom module following:

    this thread


    And what I initially wanted was to simply fill the dropdown dynamically with published names from my images.  So, you add a new image, it'll show up in that list next time you edit the custom module item.

    Got the dropdown list working fine.  Using fluent, I can fill it with my image names.  Only problem is, Sitefinity is caching that list.   Adding new images, deleting images, do not change the list unless i restart IIS.

    Is there some way to force a ChoiceFieldElement to always refresh itself and dynamically grab data?

    Thanks

    - William
  • Hi William,

    Could you check whether CreateChildControls where you create each ChoiceItem is called on each request?

    All the best,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi William,

    Also we use a service to make the call and this might be the problem. The better option is using the library item ID (Guid) as a value of the ChoiceItem, so that you will not get wrong results when you save the content item.

    Best wishes,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hey Ivan,

    Can you tell me where that would go?  Intellisence isn't revealing that attribute anywhere I can see in my code for ChoiceElements or fields 

    Here are some snippets of code based on that linked post that I'm using in the Definitions file.

    This is just in testing, so ignore the namings of variables in this.

    var minutesLinkField = new ChoiceFieldElement(mainSection.Fields)
        ID = "minutesLinkFieldControl",
        DataFieldName = "MinutesLink",
        DisplayMode = displayMode,
        Title = Res.Get<MeetingsResources>().MinutesLink,
        ResourceClassId = typeof(MeetingsResources).Name,
        MutuallyExclusive = false,
        RenderChoiceAs = RenderChoicesAs.DropDown,
        FieldName = "minutesLink",
        FieldType = typeof(ChoiceField)
    ;

    // Get all images in album
    try
        App.WorkWith()
            .Album(AlbumGuid)
            .Images()
            .Publihed()
            .OrderBy(t => t.Title)
            .ForEach(t => AddChoiceItemToDropdown(minutesLinkField, t.Title, t.UrlName));
    catch
     
    // Add to main section
    mainSection.Fields.Add(minutesLinkField);

    // Adds a choice to a dropdown
    public static void AddChoiceItemToDropdown(ChoiceFieldElement IN_ChoiceElement, string IN_Text, string IN_Value)
        IN_ChoiceElement.ChoicesConfig.Add(new ChoiceElement(IN_ChoiceElement.ChoicesConfig)
        
            Text = IN_Text,
            Value = IN_Value
        );

    Thanks much

    - William
  • Hello William,

    You can create a control that inherits from the ChoiceField and populate it as shown below. Then you can add it as a ChiceFieldElement

    public class ChoiceFieldCustom : ChoiceField
       
            public ChoiceFieldCustom()
           
                this.RenderChoicesAs = Sitefinity.Web.UI.Fields.Enums.RenderChoicesAs.DropDown;
           

            protected override void CreateChildControls()
           

                var librariesManager = LibrariesManager.GetManager();
                var albums = librariesManager.GetAlbums();
                foreach (Album alb in albums)
               
                    if (alb.Items.Count > 0)
                   
                        foreach (MediaContent img in alb.Items)
                       
                            ChoiceItem ci = new ChoiceItem();
                            ci.Text = img.Title;
                            ci.Value = img.Title;
                            this.Choices.Add(ci);
                       
                   
               
                base.CreateChildControls();
                this.DropDown.Attributes.Add("onchange", "ddChanged(this)");
           

            protected override string LayoutTemplateName
           
                get
               
                    return ChoiceFieldCustom.layoutTempalte;
               
           



            public override IEnumerable<System.Web.UI.ScriptDescriptor> GetScriptDescriptors()
           
                var descriptors = base.GetScriptDescriptors();

                var descriptor = (ScriptControlDescriptor)descriptors.Last();
                descriptor.Type = typeof(ChoiceField).FullName;

                return descriptors;
           

            private const string layoutTempalte = "Telerik.Sitefinity.Samples.Resources.ChoiceField.ascx";
       

    Regards,
    Ivan Dimitrov
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
  • That looks intriguing , Ivan.

    In this case, what would Telerik.Sitefinity.Samples.Resources.ChoiceField.ascx look like then?  I'm assuming you'd need to include that as well.

    Thanks

    - William
  • Hi William,

    Here is the template

    <%@ Control Language="C#" %>
     
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %>
     
    <sf:ConditionalTemplateContainer ID="conditionalTemplate" runat="server">
        <Templates>
            <sf:ConditionalTemplate ID="ConditionalTemplate1" Left="DisplayMode" Operator="Equal" Right="Read" runat="server">
                <sf:SitefinityLabel id="titleLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtLbl" />
                <sf:SitefinityLabel id="read" runat="server" WrapperTagName="div" HideIfNoText="false" />
            </sf:ConditionalTemplate>
            <sf:ConditionalTemplate ID="ConditionalTemplate2" Left="RenderChoicesAs" Operator="Equal" Right="CheckBoxes" runat="server">
                <sf:SitefinityLabel id="titleLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtLbl" />
                <asp:CheckBoxList ID="checkBoxes" runat="server" RepeatLayout="Flow" CssClass="sfCheckListBox sfFieldWrp"></asp:CheckBoxList>
            </sf:ConditionalTemplate>
            <sf:ConditionalTemplate ID="ConditionalTemplate3" Left="RenderChoicesAs" Operator="Equal" Right="DropDown" runat="server">
                <asp:Label ID="titleLabel" runat="server" CssClass="sfTxtLbl" AssociatedControlID="dropDown"></asp:Label>
                <span class="sfDropdownList sfFieldWrp"><asp:DropDownList ID="dropDown" runat="server"></asp:DropDownList></span>
            </sf:ConditionalTemplate>
            <sf:ConditionalTemplate ID="ConditionalTemplate4" Left="RenderChoicesAs" Operator="Equal" Right="ListBox" runat="server">
                <asp:Label ID="titleLabel" runat="server" CssClass="sfTxtLbl" AssociatedControlID="listBox"></asp:Label>
                <asp:ListBox ID="listBox" runat="server"></asp:ListBox>
            </sf:ConditionalTemplate>
            <sf:ConditionalTemplate ID="ConditionalTemplate5" Left="RenderChoicesAs" Operator="Equal" Right="RadioButtons" runat="server">
                <sf:SitefinityLabel id="titleLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtLbl" />
                <asp:RadioButtonList ID="radioButtons" runat="server"
                                     RepeatLayout="Flow"
                                     RepeatDirection="Vertical"
                                     CssClass="sfRadioList sfFieldWrp">
                </asp:RadioButtonList>
            </sf:ConditionalTemplate>
            <sf:ConditionalTemplate ID="ConditionalTemplate6" Left="RenderChoicesAs" Operator="Equal" Right="HorizontalRadioButtons" runat="server">
                <sf:SitefinityLabel id="titleLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtLbl" />
                <asp:RadioButtonList ID="radioButtons" runat="server"
                                     RepeatLayout="Flow"
                                     RepeatDirection="Horizontal"
                                     CssClass="sfRadioList sfFieldWrp">
                </asp:RadioButtonList>
            </sf:ConditionalTemplate>
            <sf:ConditionalTemplate ID="ConditionalTemplate7" Left="RenderChoicesAs" Operator="Equal" Right="SingleCheckBox" runat="server">
                <sf:SitefinityLabel id="titleLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfTxtLbl" />
                <asp:CheckBox ID="singleCheckBox" runat="server" />
            </sf:ConditionalTemplate>
        </Templates>       
    </sf:ConditionalTemplateContainer>
    <sf:SitefinityLabel id="descriptionLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfDescription" />
    <sf:SitefinityLabel id="exampleLabel" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfExample" />


    Greetings,
    Ivan Dimitrov
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
  • Ivan,

    Awesome.  Works perfectly.  Thank you!

    - William
  • Hi Ivan,

    I've used the same class you provided except that I inherited from FormChoiceField instead of ChoiceField cos' I'm creating as custom form control.

    [DatabaseMapping(UserFriendlyDataType.ShortText)]
    public class CountryDropdownlist : FormChoiceField

    Also, I can't use .Last() as you've done in the GetScriptDescriptors()
    var descriptor = (ScriptControlDescriptor)descriptors.Last();

    I'm not sure which assembly/namespace is missing cos' the intellicense is not picking up for that.
    So I changed it to the following:
    public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
     
     var descriptors = new List<ScriptDescriptor>(base.GetScriptDescriptors());
     
                var descriptor = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID);
                descriptor.AddComponentProperty("dropDown", this.DropDown.ClientID);
                descriptors.Add(descriptor);
     
                return descriptors;
     

    I'm binding the country list as follow:
    protected override void CreateChildControls()
            
                if (!Page.IsPostBack)
                
                    this.Choices.Clear();
                    // Add default null field
                    ChoiceItem ciNull = new ChoiceItem();
                    ciNull.Text = "-- Select Country --";
                    ciNull.Value = string.Empty;
                    this.Choices.Add(ciNull);
                    // Add country lsit
                    foreach (string country in GetCountries())
                    
                        ChoiceItem ci = new ChoiceItem();
                        ci.Text = country;
                        ci.Value = country;
                        this.Choices.Add(ci);
                    
     
                    base.CreateChildControls();
                    this.DropDown.AppendDataBoundItems = false;
                    this.DropDown.Attributes.Add("onchange", "ddChanged(this)");
                
            

    The list is displaying fine but when I submit a form, it's throwing the following error:

    Key cannot be null.
    Parameter name: key

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

    Exception Details: System.ArgumentNullException: Key cannot be null.
    Parameter name: key


    Any idea what I might have missed?
    Also in the admin edit form page, I can't edit anything and can't publish or go back to forms at all. The whole page seems to be disabled.

    Appreciate your help, thanks.
  • Could you also explain a abit on what this statement means:
    this.DropDown.Attributes.Add("onchange", "ddChanged(this)");
    what's "ddChanged"? Is that a control name? where can I find it?
  • Hello? anybody help please?
  • @Mayvelous,

    >>this.DropDown.Attributes.Add("onchange", "ddChanged(this)");
    This statement creates the onchange attribute for the dropdownbox and attaches the ddChanged function written on JavaScript  to the onchange event. In the plain HTML it looks like:
    <input type="select" name="....." ....... onchange="ddChanged(this)" />

    When you select another item in the dropdownbox the onchange event will be fired. So, you need to define somewhere the JS function something like this:
    function ddChanged(el)

    alert('Item changed');


    I hope this helps,
    Anton
  • 375805_Error.png
    Hi Ivan,
    I have taken your code "Dynamic Dropdown (ChoiceFieldElement) in Custom Module" and modified code and RenderChoicesAs class property as "checkboxes" so that i can have a custom field in module for choice selection.

    Its getting me error says Expecting state 'Element'.. Encountered 'Text'  with name '', namespace ''  when i select only one item in checkbox list and publish the module. Published successfully when number of selected items are two or more than it. See attached image.

    Please help.

    Thanks
    Vishwaraj Malik






     


     

  • Hi Ivan,
    I have taken your code "Dynamic Dropdown (ChoiceFieldElement) in Custom Module" and modified code and RenderChoicesAs class property as "checkboxes" so that i can have a custom field in module for choice selection.

    Its getting me error says Expecting state 'Element'.. Encountered 'Text'  with name '', namespace ''  when i select only one item in checkbox list and publish the module. Published successfully when number of selected items are two or more than it. See attached image.

    Please help.

    Thanks
    Vishwaraj Malik