Knockout: Need a callback event for Knockout-Component when the html has been attached to Dom

Created on 15 Jul 2014  ยท  4Comments  ยท  Source: knockout/knockout

Hi Steve
In ViewModel of Components we need the callback function for telling that the template has been attached to html.
Because in my case I need to call $(element).trigger(โ€œcreateโ€); with jquery mobiles theme

need a call back function

define(['knockout', 'text!./view.html'], function (ko, templateMarkup) {
    function FlightSearchViewModel(params) {

    }

    FlightSearchViewModel.prototype.attachComplete = function (element) {
        $(element).trigger("create");
    }
    // This runs when the component is torn down. Put here any logic necessary to clean up,
    // for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
    FlightSearchViewModel.prototype.dispose = function () {

    };

    return { viewModel: FlightSearchViewModel, template: templateMarkup };

});
///////////////////////////Just For Test///////////////////////////
   cloneTemplateIntoElement(componentName, componentDefinition, element);
                                var componentViewModel = createViewModel(componentDefinition, element, componentParams),
                                    childBindingContext = bindingContext['createChildContext'](componentViewModel);
                                currentViewModel = componentViewModel;
                                ko.applyBindingsToDescendants(childBindingContext, element);

                                //Fire an event attachComplete. Use with some case like initing generate html for jquery-mobile
                                if (componentViewModel.attachComplete) {
                                    componentViewModel.attachComplete(element);
                                }
very few api nice-to-have feature

Most helpful comment

You'd simply create a binding that encapsulates whatever DOM calls you want to make, e.g.,

 ko.bindingHandlers.applyJQueryMobileStuff = {
      init: function(elem) {
          $(elem).trigger("create");
      }
 }

... and then attach that to whatever element it should be called on, e.g.,:

(inside a component template):
<div data-bind="applyJQueryMobileStuff: true">...</div>

This element can be inside or outside a component - it doesn't matter - the binding will be applied when the element is introduced to the document.

I'll close this now as I think it's the right way to handle this scenario, but please reopen with more details if you disagree! Thanks.

All 4 comments

There are already places to hook in logic:

  • If you want to run code over the component's element when its template has been injected and before it is bound, you can use a createViewModel function
  • If you want to run code over the component's element during its binding process, a custom binding is the way to go

Do these cover your use case?

It would probably be quite dangerous to have an event that represents "the first binding has been completed", since it would naturally lead to bugs when subsequent bindings occur and some necessary custom logic does not run. That's why the API makes available the callbacks it does.

hi Steve.
Sorry could you please give me a code demo for this. Because I am building an web app by using jquery mobile.
<div role="main" class="ui-content"> <flight-search></flight-search> </div>

define(['knockout', 'text!./view.html'], function (ko, templateMarkup) {
    function FlightSearchViewModel(params) {

     }

     FlightSearchViewModel.prototype.attachComplete = function (element) {
        $(element).trigger("create");
     }
  // This runs when the component is torn down. Put here any logic necessary to clean up,
  // for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
    FlightSearchViewModel.prototype.dispose = function () {

    };

return { viewModel: FlightSearchViewModel, template: templateMarkup };

});

The jquery-mobile plugins just init one time after document is ready. Because of the flight-search component is lazy loading so that I need to know when the flight-search successful render to call jquery mobile function to init the specific Html like this $(element).trigger("create");

You'd simply create a binding that encapsulates whatever DOM calls you want to make, e.g.,

 ko.bindingHandlers.applyJQueryMobileStuff = {
      init: function(elem) {
          $(elem).trigger("create");
      }
 }

... and then attach that to whatever element it should be called on, e.g.,:

(inside a component template):
<div data-bind="applyJQueryMobileStuff: true">...</div>

This element can be inside or outside a component - it doesn't matter - the binding will be applied when the element is introduced to the document.

I'll close this now as I think it's the right way to handle this scenario, but please reopen with more details if you disagree! Thanks.

Thanks it works well !!!

Was this page helpful?
0 / 5 - 0 ratings