Reputation: 281
I'm writing a small chat client/server app with KnockoutJS and Node.js, everything is good, except for the fact, that after I send a message, I lose focus on the message field, and users have to reclick it everytime they want to type (very annoying). Do you guys know what I can do? Here is the template:
<script type="text/html" id="chatRoom">
<div id="chatContainer" class="chatContainer">
<div class="chatFrom">
<i id="chatClose" class="chatSprite chatClose" data-bind='click: function() { server.removeChat(this) }'></i>
</div>
<div class="chatMessages">
<ul id="chatHolder">
{{each messages()}}
<li><div class="chatFromText">From: ${ from }</div>
<div class="chatTime">${ time }</div><div class="chatMsg">${ text }</div></li>
{{/each}}
</ul>
</div>
<div class="chatControls">
<form data-bind="submit: function() { send($('#'+channel).val()); $('#'+channel).focus(); }">
<input type="text" id="${ channel }" name="message" class="chatText" style="color: #999;" value="Message Here" data-bind='click: function() {
$("#"+channel).val("").css("color", "#000");
}' />
<i class="chatSprite chatSend" data-bind="click: function() { $('.chatSend').parent().submit() }"></i>
</form>
</div>
</div>
</script>
As you can see I have tried every possible way of focusing the field, but none seem to work. Any suggestions?
Upvotes: 12
Views: 6615
Reputation: 18041
Combining Aran's and Arun's answers, the easiest way that works for me is:
<input id="channel" type="text" data-bind="hasfocus: true" />
Upvotes: 2
Reputation: 11
The reason is that your send function being asynchronous,
Either set async = false
, if you are using ajax
Alternately,
you can use a view model property to hold a boolean
value and use the hasfocus
binding
function chatVM()
{
this.focus = ko.observable(true);
}
var vm = new chatVM();
And then inside your submit function
set vm.focus(true);
OR
set hasfocus
of your message box to true always.
div class="msgbox" data-bind="hasfocus: ko.observable(true)"></div>
Upvotes: 1
Reputation: 114792
I think that your issue is likely that your "send" method does an asynchronous post back to the server, in the success callback it probably pushes the message to your messages observableArray. When this happens your template is re-rendered and your focus is lost. So, this happens after your $('#'+channel).focus()
call, because the send completes asynchronously.
Can't be sure without seeing your send function.
One option would be to pass "channel" as another parameter to your "send" function, then in the success callback for your AJAX request after pushing the message to your messages observableArray set the focus based on channel.
Sample here: http://jsfiddle.net/rniemeyer/h2A6p/
Upvotes: 12