Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onChange event not triggering on wired-textarea #144

Closed
jrej-dev opened this issue Apr 30, 2020 · 8 comments
Closed

onChange event not triggering on wired-textarea #144

jrej-dev opened this issue Apr 30, 2020 · 8 comments

Comments

@jrej-dev
Copy link

I am using the wired-textarea element in a react application.
The value property does work but it is impossible to update state with a new value as the function does not trigger with onChange. I'll use the regular textarea for now as it is working fine with it.

@apennamen
Copy link
Contributor

Hello Jrejoire,
Can you provide a code sample ?
wired-textarea dispatch a custom element, and react is notorious for not handling those well as React is using its own event system.

You might need to create a ref to the component and addEventListener to this ref.
https://vaadin.com/learn/tutorials/using-web-components-in-react

Regards,
Adrien

@jrej-dev
Copy link
Author

jrej-dev commented Apr 30, 2020

Good afternoon Adrien,

Thank you for your quick response.
I'll look into the use of ref for the issue.
Here's the code sample if needed.

Have a nice day.

Regards,

Jrej


import React, {useState} from 'react';
import StoreContext from '../../stores/AppStore';

import 'wired-elements';

const CommentInput = ({ content }) => {
    const store = React.useContext(StoreContext);
    const permlink = "re-"+ content.permlink + "-" + Date.now();
    const [body, setBody] = useState("");

    const handleReplyChange = (e) => {
        setBody(e.target.value);
    }

    const handleReplySubmit = (author) => {
        //sending data to store function
        store.comment(content.author, content.permlink, author, permlink, "", body, content.json_metadata)
    }

            return (
                <div className="active comment-banner">
 
                            <form onSubmit={(e) => {
                              e.preventDefault(); 
                              handleReplySubmit(store.userDetail.name)}
                             }>
                                <div className="comment-body">
                                    <wired-textarea 
                                    placeholder="Your reply..." 
                                    rows="6" 
                                    onChange={handleReplyChange}
                                    value={body}
                                     />
                                </div>

                                <div className="comment-bottom-banner flex-start pa-hh">
                                    <button type="submit" className="send-btn">Send</button>
                                    <p className="pointer" onClick={() => { 
                                          store.toggleReplyIsActive(content.permlink)}
                                     }>
                                        Cancel
                                    </p>
                                </div>
                            </form>
                    </div>
            )
}

export default CommentInput;

@apennamen
Copy link
Contributor

Not tested, but this is what I would try with useRef hooks:

import React, {useState, useRef} from 'react';
import StoreContext from '../../stores/AppStore';

import 'wired-elements';

const CommentInput = ({ content }) => {
    const store = React.useContext(StoreContext);
    const permlink = "re-"+ content.permlink + "-" + Date.now();
    const [body, setBody] = useState("");
    const textArea = useRef(null);

    const handleReplyChange = (e) => {
        setBody(e.target.value);
    }

    const handleReplySubmit = (author) => {
        //sending data to store function
        store.comment(content.author, content.permlink, author, permlink, "", body, content.json_metadata)
    }

      textArea.addEventListener('change', handleReplyChange);

            return (
                <div className="active comment-banner">
 
                            <form onSubmit={(e) => {
                              e.preventDefault(); 
                              handleReplySubmit(store.userDetail.name)}
                             }>
                                <div className="comment-body">
                                    <wired-textarea 
                                    placeholder="Your reply..." 
                                    rows="6" 
                                    ref={textArea}
                                    value={body}
                                     />
                                </div>

                                <div className="comment-bottom-banner flex-start pa-hh">
                                    <button type="submit" className="send-btn">Send</button>
                                    <p className="pointer" onClick={() => { 
                                          store.toggleReplyIsActive(content.permlink)}
                                     }>
                                        Cancel
                                    </p>
                                </div>
                            </form>
                    </div>
            )
}

export default CommentInput;

@apennamen
Copy link
Contributor

apennamen commented Apr 30, 2020

As it is a custom event*, I don't know exactly if the event would have a target property, but you can console.log the event to see where the value is contained ;) (maybe in event.detail ?)

regards,
AP.

@jrej-dev
Copy link
Author

jrej-dev commented Apr 30, 2020

Oh I see. Thanks for the possible solution. For now I get the "textArea.addEventListener is not a function" error but I'll look more into this. I'll let you know if I come up with an alternative.

@apennamen
Copy link
Contributor

apennamen commented Apr 30, 2020

I had time for a quick test, here is how you can retrieve the value from the event.
The event is a bit weird, because it's a custom event that wraps a native event ;)

useEffect is necessary here as the custom element is mounted once the react component is mounted ("componentDidMount")

import React, {useRef, useEffect} from 'react';
import 'wired-textarea';

function App() {
  const textArea = useRef(null);
  const handleEvent = e => console.log(e.detail.sourceEvent.target.value);
  useEffect(() => {
    textArea.current.addEventListener('input', handleEvent);

    return () => {
      textArea.current.removeEventListener('input', handleEvent)
    }
  }, [])

  return (
        <wired-textarea ref={textArea} elevation="5"></wired-textarea>
  );
}

export default App;

EDIT: cleanup with removeEventListener + more concise example

@jrej-dev
Copy link
Author

Great! It worked. Thanks a ton.
These hand drawn components are so awesome. It would have been a shame not to use them in all occasion. ;-)

@pshihn
Copy link
Contributor

pshihn commented Jun 20, 2020

Thanks @apennamen

@pshihn pshihn closed this as completed Jun 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants