fast icon indicating copy to clipboard operation
fast copied to clipboard

fix: fluentSelect unable to set selected option on load

Open iamjanit opened this issue 3 years ago • 5 comments

We are using fluent ui's control via @microsoft/fast-react-wrapper npm package, and when trying to render the FluentSelect with FluentOptions programmatically and setting the selected attribute to conditionally true, it doesn't work. Below is the code snippet we are using :-

import { FluentSelect, FluentOption } from "./fluent-component-wrapper";

interface LocationData {
    defaultSelection?: number,
    dropDownData: any[];
    onLocationChange: Function;
}
const LocationComboBox = (props: LocationData) => {
    const drpdownselect = (e: any) => {
        props.onLocationChange(e.target.value);
    }

    const renderSelect = () => {
        return (<>
            <FluentSelect id="locationDdl" className="fluent-select" onInput={drpdownselect}>
                {
                    props.dropDownData.map((item: any) => <FluentOption selected={item.id === props.defaultSelection} key={item.id} value={item.id}>{item.name}</FluentOption>)
                }
            </FluentSelect>
        </>);

    }
    return (
        <div className="locationcombobox">
            <div className="form-label" id="locationDdlLbl">Your location</div>
            {renderSelect()}
        </div>
    );
}

Expected Behaviour: Should set the options as selected when condition item.id === props.defaultSelection is true

Current Behaviour: Shows the first element in the list as selected

Our package.json dependencies :

"dependencies": { "@fluentui/web-components": "^2.5.3", "@microsoft/fast-element": "^1.10.3", "@microsoft/fast-foundation": "^2.46.10", "@microsoft/fast-react-wrapper": "^0.3.11", "@microsoft/mgt-element": "^2.5.2", "@microsoft/mgt-msal2-provider": "^2.5.2", "@microsoft/mgt-react": "^2.5.2", "@microsoft/microsoft-graph-client": "^3.0.2", "@microsoft/microsoft-graph-types": "^2.22.0", "@microsoft/teams-js": "^1.6.0", "@reduxjs/toolkit": "^1.8.3", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6", "@types/react-redux": "^7.1.24", "@types/redux": "^3.6.0", "@types/underscore": "^1.11.4", "axios": "^0.27.2", "bootstrap": "^5.1.3", "cross-env": "^7.0.3", "moment": "^2.29.4", "moment-timezone": "^0.5.34", "newTeamsjs": "npm:@microsoft/teams-js@^2.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.2", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", "reactstrap": "^9.1.1", "redux": "^4.2.0", "redux-persist": "^6.0.0", "typescript": "^4.7.4", "underscore": "^1.13.4", "web-vitals": "^2.1.4" }

iamjanit avatar Aug 12 '22 09:08 iamjanit

@EisenbergEffect Any workaround solution for this?

apanwar22i avatar Aug 17 '22 11:08 apanwar22i

@radium-v Do you have some time to look into this? At one point in time I think there was an issue with setting the initially selected item. Do you recall anything like that? The React wrapper literally just sets the value of the selected property on the FluentOption element. You have a lot more knowledge of the internals of our select so I thought I'd check with you first.

EisenbergEffect avatar Aug 17 '22 17:08 EisenbergEffect

I'm not familiar with how React rendering handles nested elements, but my first guess is that it could be a pacing condition where the select is created, then the options are added after the select has already initialized. This might cause the select to take the first option as the default selected option.

@iamjanit When you inspect the rendered DOM, does the desired option have the selected attribute?

radium-v avatar Aug 18 '22 17:08 radium-v

@radium-v When in inspect window, the selected class is only assigned to the first option. However, I will look into the pacing condition and let you know the outcome.

iamjanit avatar Aug 19 '22 04:08 iamjanit

@radium-v I was able to solve it by using useEffect hook dependent on the default selection. So , it runs after the DOM is painted and is able to set the correct option as selected.

import { useEffect, useState } from "react";
import _ from "underscore";
import { FluentSelect, FluentOption } from "./fluent-component-wrapper";

interface LocationData {
    defaultSelection?: string | number,
    dropDownData: any[];
    onLocationChange: Function;
}

const LocationComboBox = (props: LocationData) => {
    const [defaultSelected, setDefaultSelected] = useState<string | number>();
    useEffect(() => {
        setDefaultSelected(props.defaultSelection);
    }, [props.defaultSelection]);
    const drpdownselect = (e: any) => {
        props.onLocationChange(e.target.value);
    }

    return (
        <div className="locationcombobox">
            <div className="form-label" id="locationDdlLbl">Your location</div>
            <FluentSelect id="locationDdl" className="fluent-select" aria-labelledby="locationDdlLbl" onInput={drpdownselect}>
                {
                    props.dropDownData.map((item: any) => <FluentOption selected={item.id === Number(defaultSelected)} key={item?.id} value={item?.id}>{item?.name}</FluentOption>)
                }
            </FluentSelect>
        </div>
    );
}

export default LocationComboBox;

iamjanit avatar Aug 19 '22 07:08 iamjanit

closing per the above response

chrisdholt avatar Dec 20 '22 22:12 chrisdholt