1

I've set up my Knockout bindings to have a keypress event because I wish to detect Enter key event on an input field. its working fine at sometimes only, not at all the times.

Code:

<input name="" id="txtSearch" placeholder="" value="" type="search" data-bind="event: { keypress: $root.SendMsg }" />

Viewmodel:

self.SendMsg = function (data, event) {
try {
 if (event.which == 13) {
  var SearchText = $("#txtSearch").val();
                $(".divLoading").show();
                 $.ajax({
                    url: 'http://localhost/api/contacts/search',
                    type: 'GET',
                    dataType: 'jsonp',
                    data: { Text: SearchText },
                    context: this,
                    success: function (result) {

                        self.Contacts(result);                        


                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        $(".divLoading").hide();
                        alert(errorThrown);
                    },
                    complete: function () {
                        $('#ListSearch').listview('refresh');                           
                    }
                });
                return false;
            }
            return true;
        }
        catch (e)
        {
            alert(e);
        }
    }
};

Data are coming from api successfully but text enter is working sometimes and not working sometimes. If we refresh the page then its working fine. I don't know why. Please help me friends

Paul
  • 26,170
  • 12
  • 85
  • 119
  • I can't tell you exactly why it may be getting quirky for you, but I would recommend that you create a custom binding handler for the enter press to fire an event, and debug that event separately. To set the binding handler up check this question - http://stackoverflow.com/questions/15258367/how-to-detect-a-mouse-click-enter-key-or-tabbed-item-on-drop-down-list-box-in-k – PW Kad Aug 16 '13 at 13:51
  • Is there possible to re-order this code and make it working? –  Aug 16 '13 at 13:58
  • I will attempt to post an answer for your question but please recognize that I don't use jQuery mobile and therefore I can't ensure the code is going to be compilable for you and you may need to adjust it. – PW Kad Aug 16 '13 at 14:05
  • Alright I have finished my answer, it should suit your needs... – PW Kad Aug 16 '13 at 14:17
  • I added your code. but it stopped worked other things.. it showing below error "Uncaught SyntaxError: Unexpected end of input "..why its coming? may i know the reason? how to fix this? –  Aug 16 '13 at 14:34
  • It has something to do with exactly what it is stating - somewhere your code is not properly ending a line or something. As I stated before I attempted to answer you need a basic understanding of Knockout and also need to be able to implement this code into your solution, I can't show you how to do that... – PW Kad Aug 16 '13 at 14:37
  • it showing error in the line like this localhost/:1.. i don't know why it showing like this –  Aug 16 '13 at 14:41
  • Could you please provide link for better understanding from scratch for me? Because i'm not know much about Knockout js. so please do me a favour –  Aug 16 '13 at 14:48

1 Answers1

0

Add a custom binding handler to your bindings -

ko.bindingHandlers.returnAction = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = ko.utils.unwrapObservable(valueAccessor());

        $(element).keydown(function (e) {
            if (e.which === 13) {
                value(viewModel);
            }
        });
    }
};

In your view change your element to use the binding handler and directly tie it's value to an observable. I also added a searching now... span, I am not sure what element you are currently using but look at how it is only visible when the observable isSearching is visible... Saves from having to do DOM manipulation from your view model -

<div><span data-bind="visible: isSearching">Searching now...</span></div>
<input id="txtSearch" data-bind="value: searchText, returnAction: sendSearch" />

And your view model add two observables, one for searchText and the other for isSearching. This prevents you from having to go get the value with jQuery... -

self.searchText = ko.observable();
self.isSearching = ko.observable(false);

self.sendSearch= function (sender) {
    isSearching(true);  // Show your searching now text
    $.ajax({
        url: 'http://localhost/api/contacts/search',
        type: 'GET',
        dataType: 'jsonp',
        data: { Text: searchText() },
        context: this,
        success: function (result) {   
             self.Contacts(result);                        
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert(errorThrown);
        },
        complete: function () {
            $('#ListSearch').listview('refresh');
            isSearching(false);  // Hide searching now...
        }
    });
}

Now, when a user presses the enter key inside of your search input box it will fire searchSend and perform the AJAX call. There is no need for a try catch here as AJAX will return success or failure. If there is a problem you get an alert, if not life goes on. If it is successful, feel free to throw a console.log in there to see what you are getting back...

What's next?

Remember that you aren't fully utilizing Knockout.js for what it's worth. jQuery has an approach that varies greatly from Knockouts. The goal is to remove as much of the direct DOM manipulation from the view model as possible, and let the view handle itself. Take advantage of the bindings that are natively available as much as possible for hiding and showing objects, binding click events and button clicks, and anywhere else you can find to.

jQuery serves a great purpose but the approach is a bit antiquated, especially if you are using a binding library such as Knockout which takes care of these concerns for you, and more eloquently.

PW Kad
  • 14,953
  • 7
  • 49
  • 82