rniemeyer / knockout-jqAutocomplete

knockout-jqAutocomplete is a Knockout.js plugin designed to work with jQuery UI's autocomplete widget.
MIT License
49 stars 20 forks source link

Using plugin from Knockout custom component #25

Closed berlaga closed 8 years ago

berlaga commented 8 years ago

Hi, I'm trying to use plugin from inside Knockout custom component.

Template component-auto-complete.html

`

<input style="margin-bottom:5px;"
       placeholder="3 letters minimum to search"
       class="form-control"
       id="tags"
       data-bind="jqAuto: { value: myValue(), source: getOptions, inputProp: 'FullName', valueProp: 'Id', labelProp: 'FullName', options: { minLength: 3, delay: 800} }" />
<span style="margin-top:5px;" data-bind="text: 'Person\'s id: ' + myValue(), visible: myValue()"></span>

`

Model component-auto-complete.js

` define(['knockout', 'jquery'], function (ko, $) {

function AutoCompleteWidgetViewModel(params) {
    this.myValue = ko.observable();

}

AutoCompleteWidgetViewModel.prototype.getOptions = function (searchTerm, callback) {
    $.ajax({
        dataType: "json",
        url: params.serviceUrl,
        data: {
            query: searchTerm
        },
        beforeSend: function (xhr) {
            $("#tags").val("Loading data..");
        }
    })
    .done(callback)
    .always(function () {
        $("#tags").val(searchTerm);
    });

};
return AutoCompleteWidgetViewModel;

}); `

Component is loaded using Require JS loader. ` require.config({ paths: { 'jquery': '/scripts/jquery-1.9.1', 'knockout': '/scripts/knockout-3.4.0', 'text': '/scripts/text', 'jquery-ui/autocomplete': '/scripts/jquery-ui-1.11.4', 'autocomplete-plugin': 'scripts/knockout-jqAutocomplete' }

    });

   require(["knockout", "jquery", "jquery-ui/autocomplete", "text", 'autocomplete-plugin'], function () { });

`

Component registration

ko.components.register('super-auto-complete', { viewModel: { require: 'app/components/auto-complete-widget/component-auto-complete' }, template: { require: 'text!app/components/auto-complete-widget/component-auto-complete.html' } });

Component usage

<div data-bind='component: { name: "super-auto-complete", params: { serviceUrl: serviceLocation } }'></div>

Now, problem is plugin is not working. I have a suspicion it's because component is loaded using AMD.

Any help?

rniemeyer commented 8 years ago

@berlaga - Not quite sure, but I would be happy to help investigate. Is it possible for you to send me a sample that I can run either zipped up or pushed up to GH? rniemeyer at gmail dot com

berlaga commented 8 years ago

Hi Ryan,

Thanks for getting back to me. Attached is VS solution. Should work in VS 2013 and 2015. It's a bit messy, I used it to play with Knockout JS components and AMD loading. The idea was to integrate auto complete plugin as a Knockout component, so I can reuse it later.

Look at default1.aspx. This is my attempt to do the encapsulation.

https://drive.google.com/folderview?id=0B5cQV9MQUlS5bDgwamVXck1SbFk&usp=sharing

Thanks in advance, Alex

On Sun, Jul 3, 2016 at 4:02 PM, Ryan Niemeyer notifications@github.com wrote:

@berlaga https://github.com/berlaga - Not quite sure, but I would be happy to help investigate. Is it possible for you to send me a sample that I can run either zipped up or pushed up to GH? rniemeyer at gmail dot com

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rniemeyer/knockout-jqAutocomplete/issues/25#issuecomment-230172324, or mute the thread https://github.com/notifications/unsubscribe/ATB7jByqF6TuwZPDSKNbOdy3E6g6osEvks5qSBVggaJpZM4JD7-Y .

rniemeyer commented 8 years ago

@berlaga - I figured out what is going on here. The jqAuto binding is getting attached to the Knockout instance loaded via require.js. Your start-up code is using the Knockout that is loaded from the script tag (placed on window.ko). So, there are two instances of KO in play.

You would want to remove your Knockout script reference and move your start up code into the callback from your main require statement. Using the "ko" instance that would be coming in as the first argument.

It looks like perhaps you have some additional code issues with your usage of autocomplete, but this should allow you to troubleshoot those errors now. Thanks!

berlaga commented 8 years ago

Hi Ryan,

Is till can't make it work. May you can put together an example? After all using require js for AMD loading is a recommended way from Knockout web site.

Thanks, Alex

On Mon, Jul 4, 2016 at 5:47 PM, Ryan Niemeyer notifications@github.com wrote:

Closed #25 https://github.com/rniemeyer/knockout-jqAutocomplete/issues/25.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rniemeyer/knockout-jqAutocomplete/issues/25#event-712398511, or mute the thread https://github.com/notifications/unsubscribe/ATB7jNp4Lgs_le3xht_evURSa9Ph_cOmks5qSX95gaJpZM4JD7-Y .

rniemeyer commented 8 years ago

@berlaga - I can try to take a closer look at your component code tomorrow. To get past the AMD issue, here are the steps to take in your code:

1- Comment out or delete the script tag that references knockout directly that is towards the top of default1.aspx 2- Take the code that creates your component and applies bindings and move it from being in its own script tag to being in the callback for your require call. So, it would be like:

require(["knockout", "jquery", "jquery-ui/autocomplete", "text", 'autocomplete-plugin'], function(ko) {

            function AssembleServiceUrl(api) {
                return window.location.protocol + "//" + window.location.host + "/" + api;
            }

            ko.components.register('super-auto-complete', {
                viewModel: { require: 'app/components/auto-complete-widget/component-auto-complete' },
                template: { require: 'text!app/components/auto-complete-widget/component-auto-complete.html' }
            });

            function myViewModal() {
                var self = this;

                self.serviceLocation = AssembleServiceUrl("api/people");

                self.value = "125";

                self.serachValue = ko.observable();
            }

            ko.applyBindings(new myViewModal());
});
berlaga commented 8 years ago

Ryan, thank a lot. It works now :) Make sense too..

On Tue, Jul 5, 2016 at 12:09 AM, Ryan Niemeyer notifications@github.com wrote:

@berlaga https://github.com/berlaga - I can try to take a closer look at your component code tomorrow. To get past the AMD issue, here are the steps to take in your code:

1- Comment out or delete the script tag that references knockout directly that is towards the top of default1.aspx 2- Take the code that creates your component and applies bindings and move it from being in its own script tag to being in the callback for your require call. So, it would be like:

require(["knockout", "jquery", "jquery-ui/autocomplete", "text", 'autocomplete-plugin'], function(ko) {

        function AssembleServiceUrl(api) {
            return window.location.protocol + "//" + window.location.host + "/" + api;
        }

        ko.components.register('super-auto-complete', {
            viewModel: { require: 'app/components/auto-complete-widget/component-auto-complete' },
            template: { require: 'text!app/components/auto-complete-widget/component-auto-complete.html' }
        });

        function myViewModal() {
            var self = this;

            self.serviceLocation = AssembleServiceUrl("api/people");

            self.value = "125";

            self.serachValue = ko.observable();
        }

        ko.applyBindings(new myViewModal());

});

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rniemeyer/knockout-jqAutocomplete/issues/25#issuecomment-230383849, or mute the thread https://github.com/notifications/unsubscribe/ATB7jAHJ7Ds6Y4ZETklivNAdmzNHEfoHks5qSdjjgaJpZM4JD7-Y .

berlaga commented 8 years ago

Here is a full example code on Plunker https://plnkr.co/5hQNurIXpDEWg8Qf5pxI