canjs component tempate dom live binding

284 views Asked by At

My code is to realize a paginate page like this example, https://github.com/bitovi/canjs/blob/master/component/examples/paginate.html .

I found the {#messages}...{/messages} in message.mustache template was not been inserted into page , while messagelist component inserted event has been triggered, so i can not do any binding to {#messages} dom in the event, because it ‘not exists in the page.

Are there other ways to fix this problem?

The Templates:

message_list.mustache:

<app>
<messagelist deferredData='messagesDeferred'></messagelist>
<next-prev paginate='paginate'></next-prev>
<page-count page='paginate.page' count='paginate.pageCount'></page-count>
</app>

message.mustache:

{#messages}}
<dl>
<dt>.....</dt>
<dd>....</dd>
</dl>
{/messages}

The Component:

can.Component.extend({
  tag: "messagelist",
  template: can.view('/static/web/tpl/mobile/message.mustache'),    // to load message template
  scope: {
    messages: [],
    waiting: true,
    },
  events: {
    init: function () {
      this.update();
    },
    "{scope} deferreddata": "update",
    update: function () {
      var deferred = this.scope.attr('deferreddata'),
        scope = this.scope,
        el = this.element;
      if (can.isDeferred(deferred)) {
        this.scope.attr("waiting", true);
        deferred.then(function (messages) {
          scope.attr('messages').replace(messages);
        });
      } else {
        scope.attr('messages').attr(deferred, true);
      }
    },
    "{messages} change": function () {
      this.scope.attr("waiting", false);
    },
    inserted: function(){
        // can't  operate the dom  in message.mustache template
    }
  }
});

//to load component template
can.view("/static/web/tpl/mobile/message_list.mustache",{}, function(content){
  $("#message-list").html(content)
});
1

There are 1 answers

0
fychinesepjj On

I have solved the problem, but not the best, Maybe someone have a better way.

  • I changed my template, add a new component called <messageitem>
  • <messageitem> will load another template: message.mustache
  • Every <messageitem> will trigger inserted event when inserted into <messagelist>

The new component:

can.Component.extend({
  tag: "messageitem",
  template:can.view('/static/web/tpl/mobile/message.mustache'),
  events: {
    inserted: function(el, ev){
     // Can-click can not satisfy my needs,
     // because i call the third-party module to bind click event
    // this module will be called repeatedly, not the best way
      reloadModules(['accordion']); 
    }
  }
});

// To load message_list.mustache
can.view("/static/web/tpl/mobile/message_list.mustache",{}, function(content){
  $("#message-list").html(content)});

Static html:

<body>
<div id="message-list">
....
</div>
</body>

message_list.mustache:

<app>
   <messagelist deferredData='messagesDeferred'>
   {{#messages}}
  <messageitem></messageitem>
  {{/messages}}
   </messagelist>
   <next-prev paginate='paginate'></next-prev>
   <page-count page='paginate.page' count='paginate.pageCount'></page-count>
</app>

message.mustache:

<dl class="am-accordion-item" >
...
</dl>