Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Adam Gajdečka:30.1.2019 23:09

Potřebuji zavolat focus z rodičovské komponenty. Problémem je, že používám https://www.npmjs.com/…t-input-mask

a metoda focus() je dostupná ne přes ref, ale přes inputRef. Když zavolám focus(); tak objekt input je null. Stejným způsobem mám napsané ostatní podobné komponenty, ale tam je to vždy přes ref a funguje to.

Díky

React 16.7 + Typescript

Zkusil jsem:

import * as React from 'react';
import InputMask, { ReactInputMask } from 'react-input-mask';
import IInputField from '../Input/IInputField';

interface IProps {
    required?: boolean;
    icon?: string;
    placeholder?: string;
    label: string;
    value: string;
    onChange: Function,
}

interface IState {
    errors: Array<string>,
}

export default class InputTelephone extends React.Component<IProps, IState> implements IInputField{

    private input: React.RefObject<HTMLInputElement>;

    constructor(props: IProps) {
        super(props);

        this.input = React.createRef();

        this.state = {
            errors: [],
        };
    }


    focus() {
        this.input.current.focus(); //toto je celé NULL
    }

    isValid() {
        return this.getErrors().length == 0;
    }


    getErrors(value = this.props.value) {
        let errors = [];
        if (this.props.required && value.includes("_")) {
            errors.push("Toto pole je povinné");
        }
        return errors;
    }

    validate(value = this.props.value) {
        this.setState({
            errors: this.getErrors(value),
        })
    }

    handleChange(e: any) {
        this.validate(e.target.value);
        this.props.onChange(e.target.value);
    }

    renderError() {
        if (this.state.errors.length == 0) { return; }

        return (
            <ul className="parsley-errors-list filled" id="parsley-id-5">
                <li className="parsley-required">{this.state.errors[0]}</li>
            </ul>
        )
    }

    renderInput() {
        return (
            <InputMask
                inputRef={this.input}
                mask="+(999) 999 999 999"
                className={`form-control ${this.state.errors.length === 0 ? '' : 'parsley-error'}`}
                placeholder={this.props.placeholder}
                value={this.props.value}
                onChange={this.handleChange.bind(this)}
            />
        );
    }

    renderLabel() {
        return (
            <label className="form-control-label">
                {this.props.label} {this.props.required ? <span className="tx-danger">*</span> : null}
            </label>
        );
    }

    render() {
        if (this.props.icon) {
            return this.renderWithIcon();
        }

        return (
            <div className="form-group">
                {this.renderLabel()}
                {this.renderInput()}
                {this.renderError()}
            </div>
        );
    }

    renderWithIcon() {
        return (
            <div>
                {this.renderLabel()}
                <div className="input-group">
                    <div className="input-group-prepend">
                        <span className="input-group-text">
                            <i className="icon ion-email tx-16 lh-0 op-6"></i></span>
                    </div>
                    {this.renderInput()}
                </div>
                {this.renderError()}
            </div>
        );
    }
}

Chci docílit: Zavolat focus()

Zapomněl jsem napsat celý nadpis, nejde již upravit. :-( To se omlouvám

Editováno 30.1.2019 23:12
 
Odpovědět
30.1.2019 23:09
Avatar
Patrik Smělý
Tvůrce
Avatar
Odpovídá na Adam Gajdečka
Patrik Smělý:31.1.2019 0:36

Ahoj, vypadá to že ten NPM balíček nepodporuje "moderní" implementaci referencí v Reactu. inputRef je totiž prop do kterého musíš dát funkci, která v prvním argumentu obdrží právě danou referenci přímo na input. Viz: zde.

v konstruktoru přepiš

this.input = React.createRef();

Na

this.input = null;

A finálně u InputMask komponentu dej do propu inputRef funkci, která nastaví input na tu referenci co přijde v prvním argumentu. Třeba takhle:

inputRef={r => this.input = r}

Ukázka

Editováno 31.1.2019 0:37
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
31.1.2019 0:36
Avatar
Patrik Smělý
Tvůrce
Avatar
Patrik Smělý:31.1.2019 0:45

Jo a focus voláš bez current, jelikož je to přímo cesta k té referenci. Takže jen

this.input.focus();
 
Nahoru Odpovědět
31.1.2019 0:45
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:31.1.2019 7:52

google = focus input React example
-> https://stackoverflow.com/…after-render

class App extends React.Component{
  componentDidMount(){
    this.nameInput.focus();
  }
  render() {
    return(
      <div>
        <input
          defaultValue="Won't focus"
        />
        <input
          ref={(input) => { this.nameInput = input; }}
          defaultValue="will focus"
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

<input autoFocus type="text" />


componentDidMount() {
this.refs.lin­kInput.focus()
}


render: function() {
  return (
    <TextInput
      ref={function(input) {
        if (input != null) {
          input.focus();
        }
      }} />
    );
  },

-----

render: function() {
  return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
  this._input.focus();
},

---

<input ref={ function(component){ React.findDOMNode(component).focus();} } />

---

const focusUsernameInputField = input => {
  if (input) {
    setTimeout(() => {input.focus()}, 100);
  }
};

return (
  <TextField
    hintText="Username"
    floatingLabelText="Username"
    ref={focusUsernameInputField}
  />
);
Editováno 31.1.2019 7:53
 
Nahoru Odpovědět
31.1.2019 7:52
Avatar
Odpovídá na Patrik Smělý
Adam Gajdečka:31.1.2019 8:37

díky moc. Teprve s Reactem začínám :-) Funguje to skvěle, jen nevím, jaký datový typ tomu přiřadit. Bez něj mi to nejde, tak jsem dal any.

private input:any;
 
Nahoru Odpovědět
31.1.2019 8:37
Avatar
Patrik Smělý
Tvůrce
Avatar
Odpovídá na Adam Gajdečka
Patrik Smělý:31.1.2019 9:46

Můžeš tomu dát přímo typ HTMLInputElement.

 
Nahoru Odpovědět
31.1.2019 9:46
Avatar
 
Nahoru Odpovědět
31.1.2019 9:48
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.