Generate a raw HTML string from a component file and a view model

断了今生、忘了曾经 提交于 2019-12-10 04:24:45

问题


We have a template like this.

the-template.html

<template><div>${Foo}</div></template>

We want to do this with it.

some-file.ts

let htmlString = makeItHappen('the-template.html', { Foo = 'bar' });
console.info(htmlString); // <div>bar</div>

What is the equivalent of our makeItHappen function?


回答1:


Ok so here's the gist: https://gist.run/?id=d57489d279b69090fb20938bce614d3a

Here's the code in case that goes missing (with comments):

import {bindable} from 'aurelia-framework';
import {ViewLocator,ViewSlot,ViewEngine,ViewCompileInstruction} from 'aurelia-templating';
import {inject, Container} from 'aurelia-dependency-injection';

@inject(Element,ViewLocator,ViewEngine,Container)
export class LoadViewCustomAttribute {
  @bindable view;
  @bindable viewModel;

  constructor(element,vl,ve,container) {
    this.element = element;
    this.vl = vl;
    this.ve = ve;
    this.container = container;
  }

  attached() {
    // Get a view strategy for this view - this will let Aurelia know how you want to locate and load the view
    var view = this.vl.getViewStrategy(this.view);

    // Create a view factory from the view strategy (this loads the view and compiles it)
    view.loadViewFactory(this.ve, new ViewCompileInstruction()).then(vf => {
      // Create a view from the factory, passing the container (you can create a child container at this point if you want - this is what Aurelia usually does for child views) 
      var result = vf.create(this.container);
      // Bind the view to the VM - I've passed the current VM as the override context which allows Aurelia to do away with the $parent trick 
      result.bind(this.viewModel, this);

      console.log(result); // for inspection

      // Optional - create a viewslot and add the result to the DOM - 
      // at this point you have a view, you can just look at the DOM
      // fragment in the view if you want to pull out the HTML. Bear in 
      // mind, that if you do add to the ViewSlot - since nodes can only 
      // belong to 1 parent, they will be removed from the fragment in 
      // the resulting view (don't let this confuse you when debugging 
      // since Chrome shows a LIVE view of an object if you console.log(it)!) 

      // var vs = new ViewSlot(this.element, true);
      // vs.add(result);

      // Since you can't just get a fragments HTML as a string, you have to
      // create an element, add the fragment and then look at the elements innerHTML...         
      var div = document.createElement('div');
      div.appendChild(result.fragment);
      console.log(div.innerHTML);
    });
  }
}

That should do it - and the usage:

<template>
  <require from="load-view"></require>
  <section>
    <div load-view="view.bind: 'view-to-load.html'; view-model.bind: { someData: 'test' }"></div>
  </section>
</template>

And finally view-to-load.html

<template>
  <div>
    this is the template...  ${someData}
  </div>
</template>

Obviously, this doesn't have to be a custom attribute - you can just inject the bits and compile in a helper class or something like that (which can just return the raw HTML string).

This would make the equivalent of your makeItHappen function the attached method in the custom attribute. Of course you need all the deps so you need to at least have Aurelias dependency injection support to get hold of those.

Note: I'd suggest always using a ViewSlot if you plan on adding the content to the DOM (assuming you have an element that can act as the anchor) since that's the way Aurelia works and it will have more consistent results since ViewSlots know how to add/remove grandchildren gracefully

This may not be possible in the case that you have a 3rd party plugin that accepts strings as template input - but if possible look for extension points that work with DOM nodes instead.



来源:https://stackoverflow.com/questions/37845208/generate-a-raw-html-string-from-a-component-file-and-a-view-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!