abinavseelan / react-input-trigger

React component for handling character triggers inside textareas and input fields. 🐼
MIT License
88 stars 20 forks source link

Doesn't work with MaterialUI TextFields #10

Open dominikbulaj opened 5 years ago

dominikbulaj commented 5 years ago

Hi,

I wanted to implement react-input-trigger to project I work on. There I use MaterialUI and TextFields. However react-input-trigger fails with onStart

Uncaught TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.

My component is as simple as:

const TextFieldComponent = ({ input, meta: { touched, error }, ...custom }) => {

  const isError = Boolean(touched && error)
  let helperText = custom.label !== custom.helperText ? custom.helperText : undefined
  if (!helperText && error) {
    helperText = error
  }

  return <InputTrigger
    trigger={{
      keyCode: 51,// hash code
      shiftKey: true,
    }}
    onStart={(metaData) => { console.log(metaData) }}
  >
    <TextField
      error={isError}
      {...input}
      {...custom}
      helperText={helperText}
      variant="outlined"
      margin="normal"
    />
  </InputTrigger>
}

Seems error comes from dependency textarea-caret-position https://github.com/component/textarea-caret-position/blob/master/index.js#L71

Any idea how to make it work? It seems to me that it works only with html tags (textarea or input) and not React components, am I right?

charly-palencia commented 5 years ago

@abinavseelan branch bugfix/broken-ref is working perfectly for me with Material UI 🎉 !


    <InputTrigger
      trigger={{
        keyCode: 50,
        shiftKey: true,
      }}
      onStart={handleMention}
    >
      {setRef => {
        return <TextInputWithError {...props} inputRef={setRef} />; //wrapper for material ui text-field
      }}
    </InputTrigger>

Could you give some update about this Branch and when it'll be merged with master? I tried to work with an npm github reference but it didn't work properly. I had to copy your index.js and utils.js and that's how I know it's working. Thanks! 🙏

Notes: the only warning that I noticed for this branch is this one Warning: Failed prop type: Invalid propchildrenof typefunctionsupplied toInputTrigger, expected a single ReactElement. And it's a simple ProptyType issue :)

TonisPiip commented 5 years ago

The reason github ref doesn't work is because the built files aren't included in the github repo, They're somehow built inside npm's servers, I'm not too familiar with their system.

However if you use the branch with the following: git://github.com/abinavseelan/react-input-trigger.git#bugfix/broken-ref thenrun npm install; npm run build inside .../yourproject/node_modules/react-input-trigger you might be able to get it working without making a fork. Might want to add it to your build scripts to make sure it's updated and built on new installs... but not ideal...

charly-palencia commented 5 years ago

@CylonOven Thanks for the reply. Unfortunately, this is not a personal project and I won't be able to include an extra step such a npm run build for the team in this case. I would like that use this component because is really awesome but the only way for me now is that this broken-ref branch will be up soon. Thanks again

TonisPiip commented 5 years ago

One other option, in the case that this project isn't going to respond to any of their PRs / issues is to create a new file that imports this component, then over-rides the methods that have been updated / you have problems with, with working methods, then re-export it, and input this new component rather than the original .

I'm using the quilll editor, which required a lot of hacking inside this package due to it's not a normal HTML element, and if I didn't have an option to use own own fork of the project that's what I would do.

charly-palencia commented 5 years ago

@CylonOven Yeah, that sounds like a good idea, Thanks man! ⭐️

charly-palencia commented 5 years ago

@CylonOven draft version for my InputTrigger extension

import React from "react";
import PropTypes from "prop-types";

import ReactInputTrigger from "react-input-trigger";

// CUSTOM function override of react-input-trigger,https://github.com/abinavseelan/react-input-trigger
/* eslint-disable */
class InputTrigger extends ReactInputTrigger {
  /*
   * Those changes have been made by the repository owner in branch bugfix/broken-ref. this file should be REMOVE once this PR will be merged with master.
   * */
  constructor(args) {
    super(args);

    this.setRef = this.setRef.bind(this);
    this.element = null;
  }

  setRef(element) {
    if (element && Object.hasOwnProperty.call(element, "current")) {
      this.element = element.current;
    } else {
      this.element = element;
    }
  }

  render() {
    const {
      children,
      endTrigger,
      onCancel,
      onStart,
      onType,
      trigger,
      ...rest
    } = this.props;

    return (
      <div
        role="textbox"
        tabIndex={-1}
        onKeyDown={this.handleTrigger}
        {...rest}
      >
        {children(this.setRef)}
      </div>
    );
  }
}

InputTrigger.propTypes = {
  ...InputTrigger.propTypes,
  children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
};

InputTrigger.defaultProps = {
  trigger: {
    keyCode: null,
    shiftKey: false,
    ctrlKey: false,
    metaKey: false,
  },
  onStart: () => {},
  onCancel: () => {},
  onType: () => {},
  endTrigger: () => {},
};

export default InputTrigger;

Hopefully, @abinavseelan will see this and he would like to merge his changes to master 🤞 .

rheaditi commented 5 years ago

@charly-palencia, @dominikbulaj So sorry about not being able to respond to these issues earlier! Work has been 🤯 💥 😅 !

We've published a beta version ~react-input-trigger@2.0.0-beta-0~ react-input-trigger@2.0.0-beta-1 with the changes from bugfix/broken-ref. We'd love if you could try it out and let us know if it works for you. We'll test it out for a couple more use cases and publish a major version soon.

npm install react-input-trigger@2.0.0-beta-1

Thanks a lot for your support!

abinavseelan commented 5 years ago

We're still updating the docs to reflect this change before we publish the release. Meanwhile, in order to test this out please use the following steps 🙂 :

If using React 16+:

class DemoComponent extends React.Component {
    constructor() {
        // Other code

        this.inputElement = React.createRef(); // Set up a ref
    }

    render() {
        return (
            <InputTrigger
                trigger={{
                    keyCode: 51, // hash code
                    shiftKey: true,
                }}
                onStart={(metaData) => { console.log(metaData) }}

                inputRef={() => this.inputElement} // Important(New prop): Must be a function that returns the element's ref.
            >
                <textarea ref={this.inputElement} />
            </InputTrigger>
        )
    }
}

If using React 15+:

class DemoComponent extends React.Component {
    constructor() {
        // Other code

        this.inputElement = React.createRef(); // Set up a ref
    }

    render() {
        return (
            <InputTrigger
                trigger={{
                    keyCode: 51, // hash code
                    shiftKey: true,
                }}
                onStart={(metaData) => { console.log(metaData) }}

                inputRef={() => this.inputElement} // Important(New prop): Must be a function that returns the element's ref.
            >
                <textarea ref={(el) => { this.inputElement = el; }} />
            </InputTrigger>
        )
    }
}

As highlighted in the issue, the existing version of react-input-trigger does not work when using non-native input and textarea elements, for example Material UI's TextField.

The following is how the new version plans to solve this, with the new inputRef prop in <InputTrigger />

import TextField from 'material-ui/core/TextField';

class DemoComponent extends React.Component {
    constructor() {
        // Other code

        this.inputElement = React.createRef(); // Set up a ref
    }

    render() {
        return (
            <InputTrigger
                trigger={{
                    keyCode: 51, // hash code
                    shiftKey: true,
                }}
                onStart={(metaData) => { console.log(metaData) }}

                inputRef={() => this.inputElement} // Important(New prop): Must be a function that returns the element's ref.
            >
                <TextField
                    inputRef={this.inputElement} // This is a prop provided by Material UI to get the ref to the input element.
                />
            </InputTrigger>
        )
    }
}

Let us know if there are any issues 🙂 !

tylertyssedal commented 5 years ago

Do we have an idea of when the new release featuring inputRef will be out?

Thanks.

mckenzieja commented 4 years ago

Any update on this @abinavseelan ?

rameshjanjyam commented 3 years ago

thank you for that material ui textfield example above. adding input ref is working but I am seeing this warning in console

 react-input-trigger: selectionStart/selectionEnd is missing in element ref. Please ensure the ref returned from
      'inputRef' is a valid input or textarea element

by the way I am using version 2.0.0-beta-1. how can I fix that warning