I've implemented the logic of auto-expanding the height of a textarea on the keyup event. However, I want the textarea to also initialise its height once the value is bound to the textarea via a knockout custom binding. Any solutions? (With the use of only KnockoutJS, without using jQuery or any other library.)
Asked
Active
Viewed 1,581 times
2 Answers
6
I'd strongly advice against using an event to trigger the resize. Instead, you can use the textInput
binding to keep track of the input in an observable and subscribe to changes there.
Here's an example:
<textarea data-bind="textInput: value, autoResize: value"></textarea>
ko.bindingHandlers.autoResize = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.computed(function() {
ko.unwrap(valueAccessor());
resizeToFitContent(element);
})
}
};
This works because:
- The
textInput
binding writes any input change to an observablevalue
variable. - The
computed
uses this value to trigger a resize. This creates a subscription automatically.
This is better than a keydown
approach because it deals with stuff like Right Mouse Button > cut
Example showing the event
equivalent as well:
var resizeToFitContent = function(el) {
// http://stackoverflow.com/a/995374/3297291
el.style.height = "1px";
el.style.height = el.scrollHeight + "px";
}
ko.bindingHandlers.autoResize = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.computed(function() {
ko.unwrap(valueAccessor());
resizeToFitContent(element);
})
}
};
ko.applyBindings({
value: ko.observable("Test"),
onKey: function(data, event) {
resizeToFitContent(event.target);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<textarea data-bind="textInput: value, autoResize: value"></textarea>
<textarea data-bind="event: { keyup: onKey }"></textarea>

user3297291
- 22,592
- 4
- 29
- 45
0
You can create custom binding that will apply autoresize()
to all textareas:
ko.bindingHandlers.jqAutoresize = {
init: function(element, valueAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
$(element).autoResize(options);
}
};
Update your view like this:
<div data-bind="foreach: Rows" >
<textarea data-bind="jqAutoresize: {}, value: RowText" ></textarea>
</div>
-
Thank you so much for replying my question, I am new to knockout js. its not working, how to create custom binding on autoresize()? would you mind if you could set it in JSfiddle, please? – user2235768 Feb 17 '17 at 11:02
-
using a binding handler is definitely the way to do it in knockout. to actually check if the text area needs resizing is trickier, you would need to get the value of the text area and check the length of the string. Then you would probably need to make an informed decision about when to grow the size of the textarea. Basically you will need to compare the ```textarea.value.length``` to ```textarea.rows``` – dpix Feb 17 '17 at 11:17