BorisMoore / jsviews

Interactive data-driven views, MVVM and MVP, built on top of JsRender templates
http://www.jsviews.com/#jsviews
MIT License
856 stars 130 forks source link

Async template inclusion and composition #364

Closed BorisMoore closed 7 years ago

BorisMoore commented 7 years ago

See https://github.com/BorisMoore/jsrender/issues/289#issuecomment-280941389

Proof of concept below, but a future support might be more generic and let you make any tag asynchronous, along the lines of: {^{someTag fetch="..."/}} - just as any tag can now have a tmpl property: '{^{someTag tmpl="..."/}}'.

tmpl as promise: It could take the form of supporting setting the tmpl property to a promise, which would automatically lead to the async behavior - with a view refresh with the returned template when the promise resolves...

<script id="pageTmpl" type="text/x-jsrender">

Show: <input data-link="show" type="checkbox"/><br/>

{^{if show}}
a {^{remote "Jo" fetch="First" wait="..."}}inner1{{/remote}}
b {^{remote "Rebecca" fetch="Second" }}inner2{{/remote}}
c {^{remote "Jeff" fetch="First" /}}
d {^{remote "Xavier" fetch="First" wait=""}}inner4{{/remote}}
e
{{/if}}

</script>

<div id="page"></div>

<script>
var emptyTemplate = $.templates();

$.views.tags("remote", {
  basetag: "include",
  init: function(tagCtx) {
    tagCtx.tmpl = $.templates[tagCtx.props.fetch];
    if (!tagCtx.tmpl) {
      this.template = tagCtx.props.wait === undefined ? tagCtx.content : tagCtx.props.wait;
      tagCtx.tmpl = tagCtx.tmpl || emptyTemplate;
    }
  },
  onAfterLink: function(tagCtx) {
    var tag = this,
      vw = tag.view;

    if (!$.templates[tagCtx.props.fetch]) {
      setTimeout(function() { // AJAX call
        tag.tagCtx.template = undefined;
        vw.tmpl = $.templates(tagCtx.props.fetch, "<b>remote" + tagCtx.props.fetch + ":</b> {{:}} {{include tmpl=~tag.tagCtx.content/}}");
        vw.refresh();
      }, 1000);
    }
  }
});

var tmpl = $.templates("#pageTmpl");
tmpl.link("#page", {show: true});

</script>
BorisMoore commented 7 years ago

Closing for now since deferred to "After V1"

kashirin-alex commented 6 years ago

I was unable to determine the difference with the new version v0.9.89 trying to move from v0.9.82 (the actual code is at line 24: https://thither.direct/static/jsviews/app3.js) in order to use the onAfterLink: function(tagCtx) { var tag = this, vw = tag.view;

this.view is undefined. and to use this as the view, the .refresh(); is not doing well.

Thanks, Kashirin Alex

BorisMoore commented 6 years ago

Ah yes, there was a change in v0.9.86 in which the property tag.view (or this.view in the context of the onAfterLink) was moved to this.tagCtx.contentView.

One of the reasons for the change was that if you have a custom tag with {{else}} blocks, then there is a content view for each block - this.tagCtxs[i].contentView. Previously those views were difficult to access, since the this.view in fact became the content view for the last {{else}} block.

I called out the change here, but should have also indicated the breaking change aspect that tagCtx.contentView replaced tag.view.

kashirin-alex commented 6 years ago

OK, great , it is working.
I have not seen the changes of the commit might could have notice.

Thanks, Kashirin Alex