Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Cannot set pickListDefaults on a SelectItem

    I am trying to create a SelectItem subclass with some customized pickList properties. According to documentation pickList is an AutoChild so something like this should work:

    Code:
    isc.defineClass("MyMultiSelectItem", "SelectItem")
    isc.MyMultiSelectItem.addProperties({multiple: true});
    isc.MyMultiSelectItem.changeDefaults("pickListDefaults", {"bodyBackgroundColor":"red"});
    
    isc.DynamicForm.create({
        ID:"exampleForm",
        width:450,
        fields: [
            {
                type:"select",
                title:"Select",
                editorType: "MyMultiSelectItem",
    
                valueMap: {
                    "US" : "United States",
                    "CH" : "China",
                    "JA" : "Japan",
                    "IN" : "India",
                    "GM" : "Germany",
                    "FR" : "France",
                    "IT" : "Italy",
                    "RS" : "Russia",
                    "BR" : "Brazil",
                    "CA" : "Canada",
                    "MX" : "Mexico",
                    "SP" : "Spain"
                }
            },
        ]
    });
    But my custom bodyBackgroundColor isn't getting applied.

    This can be tested on https://smartclient.com/smartclient/...id=multiSelect. SmartClient versions:
    • v14.1p_2026-01-10/AllModules Development Only
    • v13.1p_2026-01-14/AllModules Development Only

    #2
    You're right - the pickList is constructed in a special way and doesn't appear to pick up pickListDefaults.
    You can set pickListProperties and things should work, or you can define a subclass of PickListMenu and apply that using pickListConstructor.

    We'll revisit this with our development team.

    One more note: The bodyBackgroundColor may not be the best test to quickly see if customization worked, since default pickList styling will typically have background color specified for each cell, meaning the underlying color only shows through if there is empty space below the last row - rare for a pickList which sizes to its content.

    Edited to add: Just for context, SmartClient has a number of multi-pickers for different situations, including the standard SelectItem with multiple:true, the MultiComboBoxItem, the SetFilterItem and the MultiPickerItem. If your goal is to create a multi-picker to support behavior that isn't available out of the box, please let us know what you're missing in case it's already supported in some way

    Regards
    Isomorphic Software
    Last edited by Isomorphic; 16 Jan 2026, 15:27.

    Comment


      #3
      Thanks for looking into this. I used bodyBackgroundColor for my example because it is visible in online showcase, just enough to show the issue.

      My picker customization is pretty simple:
      • I add a workaround for selected records being lost when dataSource contains over ~100 items
      • when pick list uses checkboxes I make item labels clickable so that users aren't required to click on small boxes
      The entire class looks currently like this:

      Code:
      declare namespace isc {
        // TODO: patch smartclient.d.ts, SelectItem should inherit form FormItem, but it doesn't
        class MultiSelectItem extends SelectItem {}
      }
      
      isc.defineClass("MultiSelectItem", "SelectItem").addProperties({
      
        multiple: true,
        defaultPickListProperties: {
          // dataFetchMode:basic is required so that, with a long value list, we won't remove a previously selected
          // item that isn't currently fetched (i.e. frontend doesn't know about it)
          dataFetchMode: "basic",
      
          recordClick(_viewer, record, _recordNum, field, _fieldNum, _value, _rawValue) {
            if (this.selectionAppearance === "checkbox" && !this.isCheckboxField(field)) {
              if (this.isSelected(record)) {
                this.deselectRecord(record);
              } else {
                this.selectRecord(record);
              }
            }
            return this.Super("recordClick", arguments);
          }
        },
      
        init() {
          // this should be done with isc.MultiSelectItem.changeDefaults("pickListDefaults", ...) but it doesn't seem to work:
          // https://forums.smartclient.com/forum/technical-q-a/277011-cannot-set-picklistdefaults-on-a-selectitem
          this.pickListProperties = isc.addProperties({}, this.defaultPickListProperties, this.pickListProperties)
          this.Super("init", arguments)
        },
      
        transformInput: (_form, _item, value, _oldValue) => {
          // SelectItem with multiple:true can sometimes return 'null' when no item was selected, which would get changed
          // to en empty string, and then converted to an array with an empty string, and we don't want that
          return value == null ? [] : value
        }
      });

      Comment


        #4
        Hi Crack
        We're quickly following up on this:

        I add a workaround for selected records being lost when dataSource contains over ~100 items
        This absolutely should not be required. A databound SelectItem with multiple:true should behave correctly out of the box no matter how many records you have in your data set. You can try this out by pasting the following code into the showcase (for example here: https://smartclient.com/smartclient/...boListComboBox)

        Code:
        isc.DynamicForm.create({
            width: 500,
            numCols: 4,
            isGroup: true,
            groupTitle: "List - ComboBox",
            wrapItemTitles: false,
            fields : [{
                name: "itemName", title: "Item Name", editorType: "SelectItem", multiple:true,
                optionDataSource: "supplyItem", pickListWidth: 250
            }]
        });
        This data set has ~4000 records and you can select items from anywhere in the list without losing the selection.
        If you have a case where this is broken we would be interested to see what's going on for you.

        Regards
        Isomorphic Software

        Comment


          #5
          Check with this code:
          Code:
          isc.DynamicForm.create({
              ID: "comboForm",
              width: 500,
              numCols: 4,
              isGroup: true,
              groupTitle: "List - ComboBox",
              wrapItemTitles: false,
              fields : [{
                  name: "itemName", title: "Item Name", editorType: "SelectItem", multiple:true,
                  optionDataSource: "supplyItem", pickListWidth: 250,
                  valueField: "itemName"
              }]
          });
          comboForm.setValues({itemName: ["Adding Machine Roll 57x57mm Standard", "Pens Uniball Ub157 Eye Fine 0.7mm Light Green", "Glue Stick Pen Sponge Tip Marbig"]});
          This will use values from the beginning, middle and end of the list. Now:
          1. comboForm.getValues() returns all three items - correct.
          2. Expand SelectItem and add click checkbox next to the second item on the list.
          3. comboForm.getValues() returns only the two items that you saw on screen, but it should return all four.

          Comment


            #6
            Thanks for the test case - we'll take a look
            Also we've modified the codebase to support pickListDefaults for SelectItems and ComboBoxItems and ported the change back to 13.1 so this pattern should work for you with nightly builds going forward (Jan 21 and above)

            Regards
            Isomorphic Software

            Comment


              #7
              Hi Crack
              A quick follow up on the "lost values issue"
              The fundamental issue with having a multi-select with a large data set that may not be fully loaded is that if the value has already been set to include some value(s) that are not in the data set, it is impossible for a user to clear those values. At best the user would have to scroll and search for the values in later pages of data, and at worst the pickListCriteria might be configured such that the previous values are not present at all, making it truly impossible to clear them.

              Therefore when the user changes selection, the item will update to match what's actually selected in the list rather than adding to the previous selection (including values that don't map to any loaded record in the pick list).

              Turning off data paging for the item at the application level to ensure the entire data set is loaded in this scenario makes sense, assuming you can assert that the data set will not be unmanageably large.

              As a more general pattern we recommend using the MultiPickerItem instead of a SelectItem when you have a very large data set and need multi selection as this component has been designed to handle this and provides a better user experience.

              We will update the documentation to make this clearer and we'll ensure a warning is logged in the case where a SelectItem with multiple:true has its value set to something that isn't in the data set and so will be dropped when the user updates the pickList selection.

              Regards
              Isomorphic Software

              Comment

              Working...
              X