From a2d76216b2d2def2a62a2f77981048612502fe54 Mon Sep 17 00:00:00 2001 From: RoboErikG Date: Thu, 17 Apr 2025 12:03:35 -0700 Subject: [PATCH] Feature: Add a dropdown options setter (#8833) * Feature: Add a setOptions method to field_dropdown * add test for changing droopdown options * split out setOptions tests into their own test suite * Add additional tests * auto format files --- core/field_dropdown.ts | 39 ++++++++++++++----------- tests/mocha/field_dropdown_test.js | 46 ++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/core/field_dropdown.ts b/core/field_dropdown.ts index bc2d2856f..cd8119af8 100644 --- a/core/field_dropdown.ts +++ b/core/field_dropdown.ts @@ -136,26 +136,11 @@ export class FieldDropdown extends Field { // If we pass SKIP_SETUP, don't do *anything* with the menu generator. if (menuGenerator === Field.SKIP_SETUP) return; - if (Array.isArray(menuGenerator)) { - this.validateOptions(menuGenerator); - const trimmed = this.trimOptions(menuGenerator); - this.menuGenerator_ = trimmed.options; - this.prefixField = trimmed.prefix || null; - this.suffixField = trimmed.suffix || null; - } else { - this.menuGenerator_ = menuGenerator; - } - - /** - * The currently selected option. The field is initialized with the - * first option selected. - */ - this.selectedOption = this.getOptions(false)[0]; + this.setOptions(menuGenerator); if (config) { this.configure_(config); } - this.setValue(this.selectedOption[1]); if (validator) { this.setValidator(validator); } @@ -414,6 +399,28 @@ export class FieldDropdown extends Field { return this.generatedOptions; } + /** + * Update the options on this dropdown. This will reset the selected item to + * the first item in the list. + * + * @param menuGenerator The array of options or a generator function. + */ + setOptions(menuGenerator: MenuGenerator) { + if (Array.isArray(menuGenerator)) { + this.validateOptions(menuGenerator); + const trimmed = this.trimOptions(menuGenerator); + this.menuGenerator_ = trimmed.options; + this.prefixField = trimmed.prefix || null; + this.suffixField = trimmed.suffix || null; + } else { + this.menuGenerator_ = menuGenerator; + } + // The currently selected option. The field is initialized with the + // first option selected. + this.selectedOption = this.getOptions(false)[0]; + this.setValue(this.selectedOption[1]); + } + /** * Ensure that the input value is a valid language-neutral option. * diff --git a/tests/mocha/field_dropdown_test.js b/tests/mocha/field_dropdown_test.js index 61deaf47f..84ce92e28 100644 --- a/tests/mocha/field_dropdown_test.js +++ b/tests/mocha/field_dropdown_test.js @@ -195,6 +195,52 @@ suite('Dropdown Fields', function () { assertFieldValue(this.field, 'B', 'b'); }); }); + suite('setOptions', function () { + setup(function () { + this.field = new Blockly.FieldDropdown([ + ['a', 'A'], + ['b', 'B'], + ['c', 'C'], + ]); + }); + test('With array updates options', function () { + this.field.setOptions([ + ['d', 'D'], + ['e', 'E'], + ['f', 'F'], + ]); + assertFieldValue(this.field, 'D', 'd'); + }); + test('With generator updates options', function () { + this.field.setOptions(function () { + return [ + ['d', 'D'], + ['e', 'E'], + ['f', 'F'], + ]; + }); + assertFieldValue(this.field, 'D', 'd'); + }); + test('With trimmable options gets trimmed', function () { + this.field.setOptions([ + ['a d b', 'D'], + ['a e b', 'E'], + ['a f b', 'F'], + ]); + assert.deepEqual(this.field.prefixField, 'a'); + assert.deepEqual(this.field.suffixField, 'b'); + assert.deepEqual(this.field.getOptions(), [ + ['d', 'D'], + ['e', 'E'], + ['f', 'F'], + ]); + }); + test('With an empty array of options throws', function () { + assert.throws(function () { + this.field.setOptions([]); + }); + }); + }); suite('Validators', function () { setup(function () {