Pole menu przechowuje ciąg znaków jako wartość i ciąg znaków jako tekst. Wartość jest kluczem niezależnym od języka, który będzie używany do uzyskiwania dostępu do tekstu i nie będzie tłumaczony, gdy Blockly będzie przełączany między językami. Tekst to zrozumiały dla człowieka ciąg znaków, który będzie wyświetlany użytkownikowi.
Pole rozwijane

Pole rozwijane z otwartym edytorem

Pole wyboru w zwiniętym bloku

na podstawie trendów
Konstruktor menu przyjmuje generator menu i opcjonalny walidator. Generator menu to tablica opcji (gdzie każda opcja zawiera czytelną dla człowieka część i ciąg znaków niezależny od języka) lub funkcja, która generuje tablicę opcji. Część każdej opcji czytelna dla człowieka może być ciągiem znaków, obrazem lub elementem HTML, a tablica może zawierać mieszankę opcji różnych typów.
Proste menu tekstowe

JSON
{
  "type": "example_dropdown",
  "message0": "drop down: %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FIELDNAME",
      "options": [
        [ "first item", "ITEM1" ],
        [ "second item", "ITEM2" ]
      ]
    }
  ]
}
JavaScript
Blockly.Blocks['example_dropdown'] = {
  init: function() {
    this.appendDummyInput()
        .appendField('drop down:')
        .appendField(new Blockly.FieldDropdown([
            ['first item', 'ITEM1'],
            ['second item', 'ITEM2']
        ]), 'FIELDNAME');
  }
};
Oddzielenie informacji czytelnych dla człowieka od klucza niezależnego od języka umożliwia zachowanie ustawień menu w różnych językach. Na przykład angielska wersja bloku może definiować [['left', 'LEFT'], ['right',
'RIGHT]], a niemiecka wersja tego samego bloku może definiować [['links',
'LEFT'], ['rechts', 'RIGHT]].
Menu obrazów
Opcje w menu rozwijanym mogą być obrazami, które są reprezentowane jako obiekty z właściwościami src, width, height i alt.

JSON
{
  "type": "image_dropdown",
  "message0": "flag %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FLAG",
      "options": [
        ["none", "NONE"],
        [{"src": "canada.png", "width": 50, "height": 25, "alt": "Canada"}, "CANADA"],
        [{"src": "usa.png", "width": 50, "height": 25, "alt": "USA"}, "USA"],
        [{"src": "mexico.png", "width": 50, "height": 25, "alt": "Mexico"}, "MEXICO"]
      ]
    }
  ]
}
JavaScript
Blockly.Blocks['image_dropdown'] = {
  init: function() {
    var input = this.appendDummyInput()
        .appendField('flag');
    var options = [
        ['none', 'NONE'],
        [{'src': 'canada.png', 'width': 50, 'height': 25, 'alt': 'Canada'}, 'CANADA'],
        [{'src': 'usa.png', 'width': 50, 'height': 25, 'alt': 'USA'}, 'USA'],
        [{'src': 'mexico.png', 'width': 50, 'height': 25, 'alt': 'Mexico'}, 'MEXICO']
    ];
    input.appendField(new Blockly.FieldDropdown(options), 'FLAG');
  }
};
Menu HTML
Opcją może być dowolny element HTML, o ile nie jest zbyt duży i nie próbuje obsługiwać zdarzeń myszy ani klawiatury. (Obowiązek przestrzegania tych reguł spoczywa na Tobie – Blockly nie wymusza ich stosowania).
Gdy menu się otworzy, na liście pojawi się element HTML. Gdy jest zamknięta, a element jest wybraną opcją, lista wyświetla (w kolejności od najbardziej preferowanych) atrybut title elementu, jego atrybut aria-label lub jego właściwość innerText.

JSON
{
  "type": "flags_with_text_dropdown",
  "message0": "flag with text %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FLAG_WITH_TEXT",
      "options": [
        ["x", "X"], // Placeholder. An empty array throws an exception.
      ]
    }
  ],
  // Use an extension to add the HTML element options.
  "extensions": ["flag_with_text_extension"]
}
Blockly.Extensions.register('flag_with_text_extension',
  function() {
    function createFlagWithTextDiv(text, src) {
      const div = document.createElement('div');
      div.setAttribute('style', 'width: 75px;');
      div.setAttribute('title', text);
      const img = document.createElement('img');
      img.setAttribute('src', src);
      img.setAttribute('style', 'height: 25px; display: block; margin: auto;');
      div.appendChild(img);
      const para = document.createElement('p');
      para.innerText = text;
      para.setAttribute('style', 'text-align: center; margin: 5px;');
      div.appendChild(para);
      return div;
    }
    const canadaDiv = createFlagWithTextDiv('Canada', 'canada.png');
    const usaDiv = createFlagWithTextDiv('USA', 'usa.png');
    const mexicoDiv = createFlagWithTextDiv('Mexico', 'mexico.png');
    const options = [
      ['none', 'NONE'],
      [canadaDiv, 'CANADA'],
      [usaDiv, 'USA'],
      [mexicoDiv, 'MEXICO']
    ];
    this.getField('FLAG_WITH_TEXT').setOptions(options);
  });
Odbywa się to za pomocą rozszerzenia JSON.
JavaScript
function createFlagWithTextDiv(text, src) {
  const div = document.createElement('div');
  div.setAttribute('style', 'width: 75px;');
  div.setAttribute('title', text);
  const img = document.createElement('img');
  img.setAttribute('src', src);
  img.setAttribute('style', 'height: 25px; display: block; margin: auto;');
  div.appendChild(img);
  const para = document.createElement('p');
  para.innerText = text;
  para.setAttribute('style', 'text-align: center; margin: 5px;');
  div.appendChild(para);
  return div;
}
const canadaDiv = createFlagWithTextDiv('Canada', 'canada.png');
const usaDiv = createFlagWithTextDiv('USA', 'usa.png');
const mexicoDiv = createFlagWithTextDiv('Mexico', 'mexico.png');
Blockly.Blocks['flags_with_text_dropdown'] = {
  init: function() {
    const input = this.appendDummyInput()
        .appendField('flag with text');
    const options = [
        ['none', 'NONE'],
        [canadaDiv, 'CANADA'],
        [usaDiv, 'USA'],
        [mexicoDiv, 'MEXICO']
    ];
    input.appendField(new Blockly.FieldDropdown(options), 'FLAG_WITH_TEXT');
  }
};
Dynamiczne menu

JSON
{
  "type": "dynamic_dropdown",
  "message0": "day %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "DAY",
      "options": [
        ["x", "X"], // Placeholder. An empty array throws an exception.
      ]
     }
  ],
  // Use an extension to set the menu function.
  "extensions": ["dynamic_menu_extension"]
}
Blockly.Extensions.register('dynamic_menu_extension',
  function() {
    this.getField('DAY').setOptions(
      function() {
        var options = [];
        var now = Date.now();
        for(var i = 0; i < 7; i++) {
          var dateString = String(new Date(now)).substring(0, 3);
          options.push([dateString, dateString.toUpperCase()]);
          now += 24 * 60 * 60 * 1000;
        }
        return options;
      });
  });
Odbywa się to za pomocą rozszerzenia JSON.
JavaScript
Blockly.Blocks['dynamic_dropdown'] = {
  init: function() {
    var input = this.appendDummyInput()
      .appendField('day')
      .appendField(new Blockly.FieldDropdown(
        this.generateOptions), 'DAY');
  },
  generateOptions: function() {
    var options = [];
    var now = Date.now();
    for(var i = 0; i < 7; i++) {
      var dateString = String(new Date(now)).substring(0, 3);
      options.push([dateString, dateString.toUpperCase()]);
      now += 24 * 60 * 60 * 1000;
    }
    return options;
  }
};
Menu rozwijane może też zawierać funkcję zamiast listy statycznych opcji, co umożliwia dynamiczne wyświetlanie opcji. Funkcja powinna zwracać tablicę opcji w takim samym formacie [human-readable-value, language-neutral-key]
jak opcje statyczne. Za każdym razem, gdy klikniesz menu, funkcja zostanie uruchomiona, a opcje zostaną przeliczone.
Separatory
Użyj ciągu znaków 'separator', aby dodać linię między opcjami w menu.

JSON
{
  "type": "separator_dropdown",
  "message0": "food %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FOOD",
      "options": [
        ["water", "WATER"],
        ["juice", "JUICE"],
        "separator",
        ["salad", "SALAD"],
        ["soup", "SOUP"],
      ]
    }
  ]
}
JavaScript
Blockly.Blocks["separator_dropdown"] = {
  init: function() {
    var input = this.appendDummyInput()
        .appendField("food1");
    var options = [
        ["water", "WATER"],
        ["juice", "JUICE"],
        "separator",
        ["salad", "SALAD"],
        ["soup", "SOUP"],
    ];
    input.appendField(new Blockly.FieldDropdown(options), "FOOD");
  }
};
Publikacja w odcinkach
JSON
Kod JSON pola menu wygląda tak:
{
  "fields": {
    "FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
  }
}
gdzie FIELDNAME to ciąg znaków odwołujący się do pola menu, a wartość to wartość, którą należy zastosować w polu. Wartość powinna być kluczem opcji niezależnym od języka.
XML
Kod XML pola wyboru wygląda tak:
<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>
Gdy atrybut name pola zawiera ciąg znaków odwołujący się do pola menu, a tekst wewnętrzny jest wartością, którą należy zastosować w polu. Tekst wewnętrzny powinien być prawidłowym kluczem opcji niezależnym od języka.
Dostosowywanie
Strzałka w dół
Właściwość Blockly.FieldDropdown.ARROW_CHAR może służyć do zmiany znaku Unicode reprezentującego strzałkę menu.

Właściwość ARROW_CHAR ma domyślnie wartość \u25BC (▼) na Androidzie i \u25BE (▾) w innych przypadkach.
Jest to właściwość globalna, więc po jej ustawieniu wszystkie pola menu zostaną zmodyfikowane.
Wysokość menu
Właściwość Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH może służyć do zmiany maksymalnej wysokości menu. Jest on określany jako procent wysokości widocznego obszaru, czyli okna.
Właściwość MAX_MENU_HEIGHT_VH ma domyślnie wartość 0,45.
Jest to właściwość globalna, więc po jej ustawieniu wszystkie pola menu zostaną zmodyfikowane.
Dopasowywanie prefiksów i sufiksów
Jeśli wszystkie opcje w menu mają wspólny prefiks lub sufiks, te słowa są automatycznie wyodrębniane i wstawiane jako tekst statyczny. Oto 2 sposoby utworzenia tego samego bloku (pierwszy bez dopasowywania sufiksów, a drugi z nim):
Bez dopasowywania sufiksów:
JSON
{
  "type": "dropdown_no_matching",
  "message0": "hello %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "MODE",
      "options": [
        ["world", "WORLD"],
        ["computer", "CPU"]
      ]
    }
  ]
}
JavaScript
Blockly.Blocks['dropdown_no_matching'] = {
  init: function() {
    var options = [
      ['world', 'WORLD'],
      ['computer', 'CPU']
    ];
    this.appendDummyInput()
        .appendField('hello')
        .appendField(new Blockly.FieldDropdown(options), 'MODE');
  }
};
Z dopasowaniem sufiksu:
JSON
{
  "type": "dropdown_with_matching",
  "message0": "%1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "MODE",
      "options": [
        ["hello world", "WORLD"],
        ["hello computer", "CPU"]
      ]
    }
  ]
}
JavaScript
Blockly.Blocks['dropdown_with_matching'] = {
  init: function() {
    var options = [
      ['hello world', 'WORLD'],
      ['hello computer', 'CPU']
    ];
    this.appendDummyInput()
        .appendField(new Blockly.FieldDropdown(options), 'MODE');
  }
};

Zaletą tego podejścia jest to, że blok łatwiej przetłumaczyć na inne języki. W poprzednim kodzie występują ciągi znaków 'hello', 'world' i 'computer', a w zmienionym – ciągi znaków 'hello world' i 'hello computer'. Tłumaczom znacznie łatwiej jest tłumaczyć frazy niż pojedyncze słowa.
Kolejną zaletą tego podejścia jest to, że kolejność słów często zmienia się w zależności od języka. Wyobraź sobie język, w którym używa się symboli 'world hello' i 'computer hello'.
Algorytm dopasowywania sufiksów wykryje wspólny sufiks 'hello' i wyświetli go po menu.
Czasami jednak dopasowywanie prefiksu lub sufiksu się nie udaje. W niektórych przypadkach dwa słowa powinny zawsze występować razem, a przedrostek nie powinien być wyodrębniany.
Na przykład w przypadku wartości 'drive red car' i 'drive red truck' należy prawdopodobnie wyłączyć tylko wartość 'drive', a nie 'drive red'. Zamiast zwykłej spacji można użyć spacji nierozdzielającej Unicode '\u00A0', aby wyłączyć dopasowywanie prefiksów i sufiksów. Powyższy przykład można poprawić za pomocą znaczników 'drive red\u00A0car' i 'drive red\u00A0truck'.
Dopasowywanie prefiksów i sufiksów nie działa też w przypadku języków, w których poszczególne słowa nie są oddzielane spacjami. Dobrym przykładem jest język chiński. Ciąg znaków
'訪問中國' oznacza 'visit China'. Zwróć uwagę na brak spacji między wyrazami.
Ostatnie 2 znaki ('中國') razem oznaczają 'China', ale rozdzielone oznaczają odpowiednio 'centre' i 'country'. Aby dopasowywanie prefiksów i sufiksów działało w językach takich jak chiński, wystarczy wstawić spację w miejscu, w którym ma nastąpić podział. Na przykład '訪問 中國' i '訪問 美國' dałyby w wyniku "visit [China/USA]", a '訪問 中 國' i '訪問 美 國' – "visit [centre/beautiful] country".
Tworzenie weryfikatora menu
Wartość pola menu to ciąg znaków niezależny od języka, więc wszystkie walidatory muszą akceptować ciąg znaków i zwracać ciąg znaków będący dostępną opcją, null lub undefined.
Jeśli walidator zwróci coś innego, działanie Blockly jest nieokreślone i program może się zawiesić.
Możesz na przykład zdefiniować pole wyboru z 3 opcjami i walidatorem w ten sposób:
validate: function(newValue) {
  this.getSourceBlock().updateConnections(newValue);
  return newValue;
},
init: function() {
  var options = [
   ['has neither', 'NEITHER'],
   ['has statement', 'STATEMENT'],
   ['has value', 'VALUE'],
  ];
  this.appendDummyInput()
  // Pass the field constructor the options list, the validator, and the name.
      .appendField(new Blockly.FieldDropdown(options, this.validate), 'MODE');
}
validate zawsze zwraca przekazaną wartość, ale wywołuje funkcję pomocniczą updateConnection, która dodaje lub usuwa dane wejściowe na podstawie wartości menu:
updateConnections: function(newValue) {
  this.removeInput('STATEMENT', /* no error */ true);
  this.removeInput('VALUE', /* no error */ true);
  if (newValue == 'STATEMENT') {
    this.appendStatementInput('STATEMENT');
  } else if (newValue == 'VALUE') {
    this.appendValueInput('VALUE');
  }
}

