4

Anyone have suggestions on how to focus a button in react DetailsList? Refs seem like the way to go, and I'd like to do something like this:

        findDOMNode<HTMLButtonElement>(this.refs.mybutton).focus()

But I haven't been able to get a ref handle on the button element.

One approach I've tried is in my DetailsList:

        <DetailsList
            onRenderItemColumn={this.renderItemColumn}
            ref={(list) => {this.detailsList = list;}}
            ....
        />

And the button I want to focus (coming from renderItemColumn):

                <PrimaryButton
                    onClick={() => this.handleActionSelection(fieldContent)}
                    ariaDescription={buttonText}
                    text={buttonText}
                    ref={"ButtonIWantToFocus"}
                />

In didComponentMount() I can now get access to the DetailList, but I'm not sure how to get the button ref to focus.

Alternatively I can define the button as:

                    <PrimaryButton
                        disabled={true}
                        ariaDescription={buttonText}
                        text={buttonText}
                        ref={(button) => {this.focusButton = button;}}
                    />

This give me a handle to the button, but it has no focus(), function.

Thanks for your ideas.

Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
Lars
  • 9,976
  • 4
  • 34
  • 40

1 Answers1

7

I think you are not referencing the ref correctly (you don't need findDOMNode).
After you set and attach your ref to the class instance using the this key word you just reference it using the this key word.

Here is a small example:

class App extends React.Component {

  focusBtn = () => {
    this.btn.focus();
  };

  render() {
    return (
      <div>
        <div onClick={this.focusBtn}>click here to focus the button below</div>
        <hr/>
        <button ref={ref => {this.btn = ref}}>im a button</button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Edit
Sorry i just noticed you were talking about a component (not just a component but a library component of fabric-ui).
After doing some reading on their github page i found out you should use the prop componentRef instead of ref.
Here is the relevant example with fabric-ui:

class App extends React.Component {

  focusBtn = () => {
    this.btn.focus();
  };

  render() {
    return (
      <div>
        <div onClick={this.focusBtn}>click here to focus the button below</div>
        <hr/>
        <Fabric.PrimaryButton componentRef={ref => {this.btn = ref}}>im a button</Fabric.PrimaryButton>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
button.ms-Button.ms-Button--primary.css-32:focus{
  border: 2px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-js/1.4.0/css/fabric.min.css">
<link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-js/1.4.0/css/fabric.components.min.css">
<script type="text/javascript" src="//unpkg.com/office-ui-fabric-react/dist/office-ui-fabric-react.min.js"></script>
<div id="root"></div>
Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
  • Thanks for the quick reply. I think the issue is related to OfficeFabric. The PrimaryButton element has no focus() function. The only way I've been able to focus it (when not in a table) is via: findDOMNode(this.refs.doneExtractingButton).focus(); – Lars Oct 12 '17 at 19:07
  • sorry just noticed you are using a component and not a dom element. after short reading you should use their `prop` `componentRef` instead of `ref`. i will update my example – Sagiv b.g Oct 12 '17 at 19:17
  • Fantastic. Much appreciated. – Lars Oct 12 '17 at 21:05
  • @Lars no problems. Did it fixed your problem? – Sagiv b.g Oct 12 '17 at 21:26
  • So slightly more complicated the DetailsList property "onRenderItemColumn" function (which is what creates the Button) is only called *after* componentDidUpdate() is called - so there's nothing to trigger the focus off of. I was able to work around it by setting a delay with a 500ms timer. Not pretty but it works. – Lars Oct 12 '17 at 22:15