Reputation: 681
It is a MERN stack app. I tried to make the height of a textarea responsive to the content using this script.
It looks like the external javascript file is working because I tried putting alert
in the for loop and it did work. So I tried putting alert inside the OnInput()
function but the alert
was not called. Therefore, I think something is wrong with this function.
index.html
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/main.js"></script>
</body>
main.js
var tx = document.getElementsByClassName('comment-area-responsive');
for (var i = 0; i < tx.length + 1; i++) {
// alert(i);
tx[i].setAttribute(
'style',
'height:' + tx[i].scrollHeight + 'px;overflow-y:hidden;'
);
tx[i].addEventListener('change', OnInput, false);
}
function OnInput() {
this.style.height = 'auto';
alert('hi2');
this.style.height = this.scrollHeight + 'px';
}
page
<textarea
className='comment-area-responsive'
name='title'
placeholder='What do you think?'
value={text} onChange={e => setText(e.target.value)}
required
/>
Upvotes: 2
Views: 1298
Reputation: 6904
The script works as intended after removing a few problems from your code -
Instead of change
event, you should listen to the textarea's input
event.
textarea
is a container, so you close it using a closing tag </textarea>
and not a self closing tag. Read more
Maybe you're using some other library, so make sure that you really need value={text}
and onChange={e => setText(e.target.value)}
attributes on the textarea. If you added them only for the purpose of this script, then they're not needed as you can see in the code below.
Run the snippet below to check that it works correctly after fixing all the above problems
var tx = document.getElementsByClassName('comment-area-responsive');
for (var i = 0; i < tx.length; i++) {
tx[i].setAttribute('style', 'height:' + (tx[i].scrollHeight) + 'px;overflow-y:hidden;');
tx[i].addEventListener("input", OnInput, false);
}
function OnInput() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
}
<div>
<textarea
class='comment-area-responsive'
name='title'
placeholder='What do you think?'
required
></textarea>
</div>
Update : For getting it to work with React, since React treats onChange
and onInput
in the same way, you can do it inside your onChange
handler, like -
const setText = (val) => {
this.setState({text: val});
var tx = document.getElementsByClassName('comment-area-responsive');
for (var i = 0; i < tx.length; i++) {
tx[i].setAttribute('style', 'height:' + (tx[i].scrollHeight) + 'px;overflow-y:hidden;');
}
}
...
<textarea
className='comment-area-responsive'
name='title'
placeholder='What do you think?'
value={text} onChange={e => setText(e.target.value)}
required>
</textarea>
Here's a working Stackblitz to play around.
Update 2: For getting it to work with React using some component lib like antd without changing the native component implementation, just add all the code logic inside the useEffect:
// You'll need to pick `value` for useEffect's dependencies array
function TextAreaComponent({ value, ...props }) {
const innerRef = useRef(null)
useEffect(() => {
// default antd ref doesn't stores the `textarea` element itself
// instead, you need to get it from inner ref prop
// (this is a lib specific approach)
const textarea = innerRef.current?.resizableTextArea?.textArea
const onType = (e: Event) => {
const target = e.target
target.style.height = 'auto'
target.style.height = `${target.scrollHeight}px`
}
if (textarea) {
textarea.setAttribute(
'style',
'height:' + textarea.scrollHeight + 'px;overflow-y:hidden;'
)
textarea.addEventListener('input', onType, false)
}
return () => {
if (textarea) {
textarea.removeEventListener('input', onType)
}
}, [value])
return (
<Input.TextArea ref={innerRef} value={value} {...props} />
)
}
Extra: If you need to pass any external ref to your component and keep using innerRef
as shown above, take a look into the useImperativeHandle hook doc.
Upvotes: 2
Reputation: 34297
I think the issue lies with your textarea.
<textarea
className='comment-area-responsive'
name='title'
placeholder='What do you think?'
value={text} onChange={e => setText(e.target.value)}
required
/>
The textarea
tag must be implicitly closed.
<textarea
className='comment-area-responsive'
name='title'
placeholder='What do you think?'
value={text} onChange={e => setText(e.target.value)}
required
></textarea>
Can you try and see if this fixes your issue?
Upvotes: 0