microsoft/azure-devops-extension-sdk

How to size Custom Work Item Form Control (Dropdown) correctly?

georgdrobny opened this issue · 6 comments

Hi,

I've implemented a custom work item form control which just consists of a simple drop-down. The drop down items are bound through code and all works as expected except for the size of the drop-down list. I can specify the size if the control in the extension manifest through the height property. The dropdown list with the available values is sized based on the height property. If the height value is large, the drop-down list is show shown also larger but this has the downside that a lot of empty space is reserved on the work item form for this control. If the value is low (for example 70, which should be sufficient for a simple drop-down) the drop-list is really small (just showing one item).
I can see other built in drop-down list on a work item form which are using minimal space and the drop-down list is expanded and shown as a nice list. I need to know how to achieve this behavior for my custom control as well. Do I need to place specific CSS classes on my HTML elements? I experimented with different styles but none of them seem have an effect. This is my current rendering code:
<div className="flex-item" style={{ margin: "8px", width: "99%"}}>

I tried "flex", "flex-box".
Any hints?
Thanks.
Georg

You can calculated the required space from your extension and call
SDK.resize(undefiend, <yourheighthere>)
after opening and closing the dropdown.

... in render()
<Dropdown
placeholder="Select a Value"
items={this.items}
onSelect={this.onSelect}
selection={this.selection}
onExpand={this.onExpand}
onCollapse={this.onCollapse}
/>
...

private onCollapse() {
  SDK.resize(undefined, 100)
};

private onExpand() {
  SDK.resize(undefined, 300)
};

I tried this one, but it still allocates lot of empty space in work item form. Am I missing something here.
Thank you.

Hi Georg

Yes, I did that change. Control just flashes and then closed. With those changes, its not event allowing us to select the values. It is always re-rendering.

--Chary

Hi Georg

I am somewhat able to achieve the required functionality of auto resizing. Following are steps performed:

  1. Default height in the manifest json file is 50
  2. Added onExpand as mentioned in the previous note i.e. height to 200
  3. Removed onCollapse, as this is causing that dropdown is never loaded. Do not know the reasons for this behavior 
  4. Reducing the control height to 50 upon Item selection or valueUpdate

Issues:

  1. Upon first click, control is not completely expanded in layout. Subsequent clicks don't have any problem.
  2. Once a value is selected and if we re-click the dropdown field is getting expanded but never collapse until we select another/same value
    Can you please let us know at least how to fix these issues.

Thank you
Chary

I'm experiencing the same issue, where the height of the iframe is restricted by the parent component. The parent component provides just enough space to display the dropdown itself, but not the options. When the dropdown expands, the options are hidden.
image

I tried using the SDK.resize() method within the onExpand handler, calculating the height based on the number of options. However, since onExpand is a callback, the resize occurs after the dropdown expands, causing the options to be hidden on the first click and visible only on the second click.

I also raised this issue on the Developer Community, but was directed to seek assistance in the SDK GitHub repo.

const onDropdownExpand = () => {
    const dropdownHeight = Math.min(listData.length * 40, 600);
    SDK.resize(400, dropdownHeight + 100);
  };

const renderDropdown = () => {
    return (
      <Observer selection={dropDownSelection}>
        {() => {
          return (
            <Dropdown
              ariaLabel="Multiselect"
              actions={[
                {
                  className: "bolt-dropdown-action-right-button",
                  disabled: dropDownSelection.selectedCount === 0,
                  iconProps: { iconName: "Clear" },
                  text: "Clear",
                  onClick: async () => {
                    dropDownSelection.clear();
                    await saveSelected([]);
                  },
                  tooltipProps: {
                    text: "Clear",
                  },
                },
              ]}
              className="example-dropdown"
              items={convertItemsToListBoxItems(listData)}
              selection={dropDownSelection}
              onExpand={onDropdownExpand}
              onSelect={handleSelect}
              placeholder="Select an Option"
              showFilterBox={true}
            />
          );
        }}
      </Observer>
    );
  };

useEffect(() => {
    SDK.init({ loaded: false });

SDK.ready().then(async () => {
      SDK.register(SDK.getContributionId(), () => {
        return {};
      });

...

SDK.notifyLoadSucceeded();
    });
  }, []);

return (
    <div>
      {renderDropdown()}
      <div className="error"></div>
    </div>
  );