• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by spitz7 · Dec 17, 2015 at 09:58 AM · valuedropdown

How to create a dropdown without having an item selected?

Hi all,

I created a dropdown and populated it with several country names for the user to choose from. The dropdown's value starts at 0, so the first country is already selected. I want the caption text to initially be "Country" and not "Afghanistan" so I manually changed it:

 CountryDropdown.captionText.text = "Country";

This works fine almost always, but if the user chooses "Afghanistan" the caption text does not change and stays "Country" and onValueChanged doesn't trigger. This happens because the value was and still is 0.

I tried to set the value property of the dropdown to -1 but Unity treats it as 0. Apparently, it's also not possible to choose a value bigger than the last item on the list. I know I can just add a country to the top of the list and call it "Country" but it seems like an ugly solution.

Is there a way to do what I want?

Thanks for the help!

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Rajeesh_AR · Dec 18, 2015 at 05:39 AM 0
Share

@spitz7 Does it works for you >?

avatar image Riderfan · Feb 17, 2016 at 12:01 PM 1
Share

I ran into a similar problem. Not exactly the same, but similar.

In my case I have a collection of possible values the user can select from, save and change later on when they reload the game. This was all working fine however when I created the content for the drop down list, I would also set the CaptionText to the value the user had previously selected and saved. However as you've also found out, the value on the list would always be 0. $$anonymous$$eaning the user could never select the first item on the list. Hopefully I've explained that well enough.

I really do consider this a bug and have submitted a bug report. We should be able to set a default value of -1 OR if we are setting the captiontext to the same text thats in the drop list, the value should default to that item. That's how other drop down list components work.

At any rate, I created a little routine that would itterate through all the items on the list and do a text match. This is a pretty brute force way to do it, but my list of options is quite small (about 6) and it's a UI component where speed isn't really a concern.

 SetDropValue($$anonymous$$yDropList, DesiredCaptionString);
 
         /// <summary>
         /// Sets the caption text and selected item index to the specified string.
         /// </summary>
         /// <param name="_DropDown">The dropdown list we want to update</param>
         /// <param name="_CaptionText">The caption we want to set. $$anonymous$$ust be an item on the list.</param>
         private void SetDropValue(Dropdown _DropDown, string _CaptionText)
         {
             string Caption = _CaptionText.ToUpper();
 
             //Set the caption we want
             _DropDown.captionText.text = Caption;
 
             //Now we have to hack our way through and set the value based on the caption.
             for (int OptIndex = 0; OptIndex <= (_DropDown.options.Count - 1); OptIndex++)
             {
                 if (_DropDown.options[OptIndex].text.ToUpper() == Caption)
                 {
                     _DropDown.value = OptIndex;
                     break; //don't bother checking the rest
                 }
             }
         }

So now, anytime I need to set a preselected value for a drop list, I just call that function. There's no error handling and doesn't handle cases where the caption is for an item that is not on the list (so your problem may still occur).

Hope that helps someone.

10 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by Gnaarf · Jun 23, 2017 at 01:13 PM

Kind of old topic, but I just had a similar Problem and found that ISelectHandler triggers at the right time.

I adjusted my code a little to fit your problem. Just add it to the GameObject with the Dropdown-Component:

 using UnityEngine;
 using UnityEngine.EventSystems;
 using UnityEngine.UI;
 
 [RequireComponent(typeof(Dropdown))]
 public class DropdownWithTitle : MonoBehaviour, ISelectHandler
 {
     [SerializeField] Dropdown.OptionData title;
 
     bool wasNeverSelected = true;
 
     Dropdown dropdown;
 
     void Start()
     {
         dropdown = GetComponent<Dropdown>();
 
         dropdown.options.Insert(dropdown.value, title);
         dropdown.RefreshShownValue();
     }
 
     public void OnSelect(BaseEventData eventData)
     {
         if (wasNeverSelected)
             RemoveTitle();
 
         wasNeverSelected = false;
     }
 
     private void RemoveTitle()
     {
         dropdown.options.RemoveAt(dropdown.value);
         dropdown.RefreshShownValue();
     }
 }
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Rob-Meade · May 22, 2018 at 03:23 PM 1
Share

Hey @Gnaarf,

This is very useful, thank you.

The only $$anonymous$$or issue I've spotted is that it doesn't fire an onValueChanged event.

As an example;

  • the title is displayed

  • the dropdown is selected

  • the title is removed from the list

  • the next option is immediately "ticked" and is now the default value

..but if I click away from the dropdown menu, it looks as if that item is selected but it didn't fire the onValueChanged event, so anything relying on it doesn't know the value has changed from "title" to the new value.

If the user doesn't click away, where-by the control loses focus, and clicks on the option with the tick then it behaves as expected.

     private void RemoveTitle()
     {
         dropdown.options.RemoveAt(dropdown.value);
         dropdown.onValueChanged.Invoke(dropdown.value);
         dropdown.RefreshShownValue();
     }

Could probably do with a little validation, to check that there are actually items in the list and so on, but this seemed to work.

Rob

avatar image GimpMaster · Oct 10, 2018 at 08:31 PM 1
Share

Thanks @Gnaarf and @Rob-$$anonymous$$eade

I wanted $$anonymous$$e to be programatically changed and not necessarily on Start(). Here is my version.

 using UnityEngine;
 using UnityEngine.EventSystems;
 using UnityEngine.UI;
 
 [RequireComponent(typeof(Dropdown))]
 public class DropdownWithTitle : $$anonymous$$onoBehaviour, ISelectHandler
 {
     [SerializeField] Dropdown.OptionData title;
 
     bool wasNeverSelected = true;
 
     Dropdown dropdown;
 
     public void SetTitleAndReset(string newTitle)
     {
         dropdown = GetComponent<Dropdown>();
         wasNeverSelected = true;
         title.text = newTitle;
         dropdown.options.Insert(dropdown.value, title);
         dropdown.RefreshShownValue();
     }
 
     public void OnSelect(BaseEventData eventData)
     {
         if (wasNeverSelected)
             RemoveTitle();
 
         wasNeverSelected = false;
     }
 
     private void RemoveTitle()
     {
         dropdown.options.RemoveAt(dropdown.value);
         dropdown.onValueChanged.Invoke(dropdown.value);
         dropdown.RefreshShownValue();
     }
 }
avatar image
0

Answer by naviln · Feb 26, 2020 at 01:43 AM

So I've spent some time battling this problem, because I have been trying to achieve the same thing. I want a placeholder text, that is removed once a real option is selected.

I was messing around with this for a long time, and inspired by a post from Ali Kanat (thanks!) here: https://stackoverflow.com/questions/55297626/disable-an-options-in-a-dropdown-unity

I was finally able to put a robust solution together that I was happy with.


The core idea of this solution is to:

  • Utilize a GridLayout Group on the template content GameObject - this helps you to collapse and hide content.

  • Add a hidden 'placeholder' item to your TMP options

  • And finally, use a 'ToggleCheck' Start script on the Item in the TMP dropdown template, this helps you identify your placeholder and disable (HIDE) it.

  • (A disabled object inside a GridLayoutGroup is 'collapsed' and hidden.)


The GridLayout script will ensure that the placeholder always remains hidden, and now you get the benefit of OnValueChanged firing properly (since the hidden default value is picked first!).

I'll put my steps and scripts here, in case anyone wants to try my idea.


First, in the template of your dropdown, add a GridLayoutGroup Script to the Content GameObject. Give it a fixed width that you like (or if you want more flexibilty, you can add your own grid resize controller script and have it resized to match its parent. for the purpose of this example, im just going to use a fixed width of 400).

Screenshot of where to add this:

alt text


Now, in your dropdown initialization, insert a 'placeholder' item. Give it a unique name that no one will use (I went with {{placeholder.com.data}}):

 var ddl = new List<TMP_Dropdown.OptionData>();            
 //lets first insert a 'placeholder' option
 ddl.Add(new TMP_Dropdown.OptionData("{{placeholder.com.data}}"));
 
 //then fill out your usual entries in the dropdown, as you normally would
 //...
 
 //After that is done, insert these options to your dropdown
 dropdownTMP.options.Clear();
 dropdownTMP.options = ddl;
 //and IMPORTANT - force set the choice to the first item (the placeholder)
 dropdownTMP.value = 0;



Next, the onDropdownValueChange method can now do what it normally does, in addition just add a step to turn the placeholder text label you have off:

   public void OnDropdownValueChange()
     {           
         //turn the placeholder off now, or remove its text (or both)
         TMPPlaceholderText.text = "";
         TMPPlaceholderText.gameObject.SetActive(false);
         //and turn the dropdown label on
         dropdownLabelTMP.gameObject.SetActive(true);
     }

And finally - how to turn the placeholder off on intialization. This you can now achieve by adding a "ToggleCheck" script to the 'Item' GameObject inside the dropdown template. Screenshot of where to add the script:

alt text


And here is the content - you want to catch the name of the 'placeholder' toggle, if it matches the placeholder text you specified, hide it (and make it un-interactable too). NOTE: The name will have the text "Item 0:" prefixed to it, as it was the first option you inserted to the TMP OptionData.

     public class ToggleCheck : MonoBehaviour
     {
         //This script should be attached to Item
         void Start()
         {           
             Toggle toggle = gameObject.GetComponent<Toggle>();            
             if (toggle != null && toggle.name == "Item 0: {{placeholder.com.data}}")
             {
                 toggle.interactable = false;
                 toggle.gameObject.SetActive(false);
                 //and resize the grid layout if you want, since this is the first item, and you only need to do this once.
                 //gameObject.GetComponentInParent<GridResizeController>().ApplyGridResize();
             }
         }
     }
 

This ensures that the placeholder is selected first, allowing OnDropdownValueChange to fire when it is changed for the first time to a real value.


Obviously you should add additional placeholder validation, if someones tries to use item 0, etc. And you could be even smarter with the ToggleCheck script (read the placeholder from some internal lookup table, hide the name etc). It enables a lot more cool customization, potentially. You can decide how you want to implement those things.


Bonus: Here is a method you can use to resize the GridLayoutGroup width to match its parent:

     private void ApplyGridResize(GridLayoutGroup gridLayout)
     {
         // grab the width of my parent
         var width = gameObject.transform.parent.GetComponent<RectTransform>().rect.width;
         Vector2 newSize = new Vector2(width, gridLayout.cellSize.y);            
         gridLayout.cellSize = newSize;
     }



If there is an easier way to achieve this in Unity 2019 and onwards I'd love to hear it! But for now this works really well for me.


gridlayoutgroup.png (131.1 kB)
togglecheck.png (262.1 kB)
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by jason416 · Mar 12, 2020 at 03:09 PM

Well it's 2020 now, this is how I'm doing it. Drop this script on the same GO as the Dropdown. It will just overwrite the caption text onEnable, this does not actually change the underlying value of the dropdown. If you want the label to return to the default after selection then add a call to the method again on your click events.

 using UnityEngine;
 using UnityEngine.UI;
 
 public class DefaultDropdown : MonoBehaviour
 {
     public string DefaultText;
     Dropdown dropdown;
 
     private void Awake()
     {
         dropdown = gameObject.GetComponent<Dropdown>();
     }
 
     private void OnEnable()
     {
         SetDefaultText();
     }
 
     public void SetDefaultText()
     {
         dropdown.captionText.text = DefaultText;
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by tcz8 · Jun 05, 2020 at 06:00 AM

Here's another one:

 [SerializeField] string defaultText = "Default Text";    // We use public to much
 bool init = true;
 
 void OnGUI() {    // Runs right when drawing the UI, nothing can stop my default text now!
     if init {
         init = false;
         dropdownMenu.captionText.text = defaultText;
     }
 }
 
 void OnDisable() {
     init = true;
 }


How I use it:
I load data into my dropdown on Start() and the dropdown gets displayed as a result of enabling it's game object. When it's game object is disabled the default text is reset and will appear again the next time it's enabled.

Why OnGui ?
Because it's the very last moment before the UI gets drawn. This way nothing gets the chance to override your default text.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by XAFAX · Nov 10, 2021 at 03:30 PM

In case anyone is still wondering how to add a preface text, here's how you do it:

1) Add a placeholder to the Dropdown Component.

2) Set the Dropdown value to -1 (see code below).

 private void BuildDropdown()
 {
     _dropdown.options = CreateOptions(); // Create some options (optional)
     _dropdown.SetValueWithoutNotify(-1); // Set dropdown value to -1, so that the placeholder is displayed.
     _dropdown.onValueChanged.AddListener(SomeListener); // Add some functionality (optional)
 }

Now the placeholder will be displayed first.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • ‹
  • 1
  • 2

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

TextMeshPro dropdown default value change 0 Answers

How to make dropdown start at value on click 0 Answers

Vector3 List Find Contains Specific X Coordinate Value and Remove 0 Answers

c# problem with changing value with button click 3 Answers

Change value when swiping on mobile 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges