0

Using jquerymobile and knockout, I am trying to create a custom binding that looks as follows

<ul data-bind="listview: observablearray">
    <li data-bind="text: text"></li>
</ul>

where the listview binding would first act like a foreach binding and then apply $(element).listview() to it (or $(element).listview('refresh') on an update).

I tried doing the following to naively imitate the foreach binding:

ko.bindingHandlers.listview = {
  init: function (element, valueAccessor) {
    var listview = $(element);
    listview.listview();
  },
  update: function (element, valueAccessor) {
    var listview = $(element);
    setTimeout(function () {
      listview.html('');
      var items = valueAccessor().list;
      var link = valueAccessor().link;
      var text = valueAccessor().text;
      var icon = valueAccessor().icon;
      $.each(ko.utils.unwrapObservable(items) || [], function (i, item) {
        var li = $('<li></li>').css({
          height: '44px'
        })
        var a;
        if (link) {
          a = $('<a href="#"></a>').click(function () {
            link(item)
          });
          li.append(a);
        }
        if (icon) {
          (a || li).append($('<img />').attr('src', icon(item)).addClass('ui-li-icon'));
        }
        if (text) {
          (a || li).append($('<span></span>').text(item[text]));
        }
        listview.append(li);
      });
      listview.listview('refresh')
    }, 0);
  }
};

Unfortunately, not only was this a poor implementation that didn't use templating, it also through an error on init:

Uncaught TypeError: Cannot read property 'jQuery19101983379740267992' of undefined

Thanks in advance!

2
  • 1
    Perhaps this (stackoverflow.com/questions/15702996/…) can help you... Commented Apr 8, 2013 at 18:32
  • it does, although i'm interested in the inner workings of knockout, specifically how to manually render an anonymous template Commented Apr 8, 2013 at 18:46

2 Answers 2

0

You can call internal knockout bindings from withing your bindings.

In your case this should work.

ko.bindingHandlers.listview = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var res = ko.bindingHandlers.foreach.init(element, valueAccessor()['listview']);
        $(element).listview();
        return res;
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var res = ko.bindingHandlers.foreach.update(element, valueAccessor()['listview'], allBindingsAccessor, viewModel, bindingContext);
        $(element).listview('refresh');
        return res;
    }
};

Rendering templates on your own is quite a challenge, your are better off using the internal 'template' binding. The 'foreach' binding does so too. Look in the knockoutjs code to see how its done.

Sign up to request clarification or add additional context in comments.

Comments

0

For me the quickest and elegant way to work with dinamic jQueryMobile listview is to subscribe to models changes, something like this:

viewModel.products.subscribe(function() {
    jQuery("#productsList").listview("refresh");  
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.