Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store templates as string #239

Open
LeonardoGentile opened this issue Apr 24, 2018 · 9 comments
Open

Store templates as string #239

LeonardoGentile opened this issue Apr 24, 2018 · 9 comments

Comments

@LeonardoGentile
Copy link

Hello,
I'm having this requirements: in a single js file I need to store multiple rt templates as strings.
For example:

templates = {
  'tpl1': `<div rt-if="this.state.resultCode === 200">Success!</div>`
  'tpl2': `<div rt-if="this.anotherVar === 'blue">Blue!</div>`
}

Then import the templates object and select one of its attribute. Finally passing it to the component that should render it.
So what I need is a sort of a compilation process of the template, similar of what was available in (ahem) angular1 $compile(element)(scope)

Is this possible?

@nippur72
Copy link
Contributor

react-templates are already compiled, they don't live anywhere as strings during runtime. They are functions.

You should address your problem differently, e.g. treat your 'tpl1' and 'tpl2' as components and render then via props.children (just a suggestion).

@sergey-v9
Copy link

if you want to "compile" your strings at runtime you could try to call reactTemplates.convertTemplateToReact(...) as it used in react-templates-loader

@LeonardoGentile
Copy link
Author

@dthpth what would reactTemplates.convertTemplateToReact(...) return? The same 'render' function normally used in the docs?

Would something like this work?

const templates = {
  'tpl1': `<div rt-if="this.state.resultCode === 200">Success!</div>`
  'tpl2': `<div rt-if="this.anotherVar === 'blue">Blue!</div>`
}

class MyComp extends Component {
  componentDidMount() {
     this.renderTpl = reactTemplates.convertTemplateToReact(templates['tpl1'])
  }

  render() {
    return this.renderTpl()
  }
}

@nippur72
Copy link
Contributor

@dthpth at runtime you can't use it because react-templates adds no runtime library, e.g. convertTemplateToReact is not available (unless of course you require it, but I would do that only server-side).

@LeonardoGentile why not just that:

import tpl1 from "./yourtemplate1";
import tpl2 from "./yourtemplate2";

class MyComp extends Component {
  render() {
    if(this.state.resultCode === 200) return tpl1();
    if(this.anotherVar === 'blue') return tpl2();
  }
}

still, I think there are better ways to handle the problem.

@LeonardoGentile
Copy link
Author

@nippur72 so it is technically possible (but not advisable) to implement the solution I posted above?

You are right, there are far better ways to solve this but unfortunately this is part of a requirement.

The object

const templates = {
  'tpl1': `<div rt-if="this.state.resultCode === 200">Success!</div>`
  'tpl2': `<div rt-if="this.anotherVar === 'blue">Blue!</div>`
}

contains potentially hundreds of templates and is stored in a single file.

In particular that file is standard es5 that should not go through any compilation, just a plain js file exporting a global var.

Then the react app will get that global object containing all the templates and use/compile the correct ones depending on certain conditions.

I know it is a poor/ugly design but it is required to be implemented this way 🙄

@nippur72
Copy link
Contributor

yes it's technically possible, I have done something similar in the past, and certainly the Playground does it already.

The two main drawbacks that I see are:

  • increased footprint because you have to require("react-templates") which in turn has a long list of dependencies. Remember that react templates was meant to be run as server-side compiler so the dependencies were not a design issue.

  • need to to use eval() to convert the string returned by react-templates into a true JavaScript function (which is a React "render" function).

Something like this:

var source = /* your template */ ;
var reactTemplates = require('react-templates/src/reactTemplates');
var options = { /* rt command line options */};
var sfunction = reactTemplates.convertTemplateToReact(source, options);
var code = eval(sfunction);

@LeonardoGentile
Copy link
Author

Thanks for your help!
Yes, indeed that dependencies list at the moment is quite heavy for client-side templating:

"dependencies": {
    "chalk": "2.3.0",
    "cheerio": "0.22.0",
    "css": "2.2.1",
    "escodegen": "1.9.0",
    "esprima": "4.0.0",
    "glob": "7.1.2",
    "lodash": "4.17.5",
    "normalize-html-whitespace": "0.2.0",
    "nyc": "^11.4.1",
    "optionator": "0.8.2",
    "text-table": "0.2.0"
  },

Are you planning to improve client-side support or probably it is better to look for alternative solutions? Probably something like this https://github.com/TroyAlford/react-jsx-parser ?

@nippur72
Copy link
Contributor

I'm not a maintainer but I don't think it will be improved in the foreseeable future.

If you are not tied to React, you might want to look into Riot.js which has template compilation at runtime. Vue is also another alternative.

@LeonardoGentile
Copy link
Author

Thanks, unfortunately I'm tied to react

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants