Giter Site home page Giter Site logo

react-templates's Introduction

NPM version build status Coverage Status

React Templates

Lightweight templates for React.

  • No runtime libraries. No magic. Simply precompile your way to clear React code.
  • Easy syntax that's similar to HTML, supported by most IDEs.
  • Clear separation of presentation and logic - almost zero HTML in component files.
  • Declarative coding ensures that the HTML that you write and the HTML you inspect look nearly identical.
  • Supports AMD, CommonJS, ES6, Typescript and globals.

How does it work

React Templates compiles an *.rt file (react template file - an extended HTML format) into a JavaScript file. This file, which uses AMD syntax, returns a function. When invoked, this function returns a virtual React DOM based on React.DOM elements and custom user components.

A common use case would be that a regular React component would require a JavaScript file generated from a template, and then perform `func.apply(this)`, causing the template to have that component as its context.

Playground

http://wix.github.io/react-templates/

Yeoman generator

https://github.com/wix/generator-react-templates

Hello react-templates

Here's a sample Hello project:
https://github.com/wix/hello-react-templates

Here's a sample Hello project with webpack, es6 and hot reload:
https://github.com/wix/react-templates-transform-boilerplate

IntelliJ / WebStorm plugin

http://plugins.jetbrains.com/plugin/7648

Basic concepts for React templates

Why not use JSX?

Some love JSX, some don't. We don't. More specifically, it seems to us that JSX is only a good fit for components with very little HTML inside. And this can be accomplished by creating DOM elements in code. Also, we like to separate code and HTML because it just feels right.

Installation

You can install react-templates using npm:

npm install react-templates -g

Usage

rt [file.rt|dir]* [options]

See more on CLI usage here.

In most cases, this package will be wrapped in a build task, so CLI will not be used explicitly:

Use React Templates for Native Apps?

You can get all the react templates functionality and more. Click here for more info

Template directives and syntax

Any valid HTML is a template

Any HTML that you write is a valid template, except for inline event handlers ("on" attributes). See the "event handlers" section below for more information.

{} to identify JavaScript expressions

To embed JavaScript expressions in both attribute values and tag content, encapsulate them in {}. If this is done inside an attribute value, the value still needs to be wrapped in quotes. For directives (see below), {} are not used.

Sample:
<a href="{this.state.linkRef}">{this.state.linkText}</a>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    return function () {
        return React.DOM.a({ 'href': this.state.linkRef }, this.state.linkText);
    };
});

rt-if

This lets you add conditions to a subtree of HTML. If the condition evaluates to true, the subtree will be returned; otherwise, it will not be calculated. It is implemented as a ternary expression.

Sample:
<div rt-if="this.state.resultCode === 200">Success!</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    return function () {
        return this.state.resultCode === 200 ? React.DOM.div({}, 'Success!') : null;
    };
});

rt-repeat

Repeats a DOM node with its subtree for each item in an array. The syntax is rt-repeat="itemVar, indexVar in arrayExpr", where the element, itemVar, will be available in JavaScript context, and an itemVarIndex will be created to represent the index of the item. By using this naming scheme, repeated expressions have access to all levels of nesting. It is also possible to declare a custom index variable using the syntax rt-repeat="itemVar, indexVar in arrayExpr", in which case the index variable will be indexVar.

Sample:
<div rt-repeat="myNum in this.getMyNumbers()">{myNumIndex}. {myNum}</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    function repeatMyNum1(myNum, myNumIndex) {
        return React.DOM.div({}, myNumIndex + '. ' + myNum);
    }
    return function () {
        return _.map(this.getMyNumbers(), repeatMyNum1.bind(this));
    };
});

rt-virtual

This directive creates as a virtual node, which will not be rendered to the DOM, but can still be used as a root for directives, e.g. rt-if and rt-repeat.

Sample:

For instance, to repeat several nodes at once without a shared root for each instance:

<ul>
  <rt-virtual rt-repeat="n in [1,2,3]">
    <li>{n}</li>
    <li>{n*2}</li>
  </rt-virtual>
</ul>
Compiled:
define([
    'react/addons',
    'lodash'
], function (React, _) {
    'use strict';
    function repeatN1(n, nIndex) {
        return [
            React.createElement('li', {}, n),
            React.createElement('li', {}, n * 2)
        ];
    }
    return function () {
        return React.createElement.apply(this, [
            'ul',
            {},
            _.map([
                1,
                2,
                3
            ], repeatN1.bind(this))
        ]);
    };
});

rt-scope

This directive creates a new JavaScript scope by creating a new method and invoking it with its current context. The syntax is rt-scope="expr1 as var1; expr2 as var2. This allows for a convenient shorthand to make the code more readable. It also helps to execute an expression only once per scope.

Sample:
<div rt-repeat="rpt in array">
    <div rt-scope="')' as separator; rpt.val as val">{rptIndex}{separator} {val}</div>
    <div>'rpt' exists here, but not 'separator' and 'val'</div>
</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    function scopeSeparatorVal1(rpt, rptIndex, separator, val) {
        return React.DOM.div({}, rptIndex + separator + ' ' + val);
    }
    function repeatRpt2(rpt, rptIndex) {
        return React.DOM.div({}, scopeSeparatorVal1.apply(this, [
            rpt,
            rptIndex,
            ')',
            rpt.val
        ]), React.DOM.div({}, '\'rpt\' exists here, but not \'separator\' and \'val\''));
    }
    return function () {
        return _.map(array, repeatRpt2.bind(this));
    };
});

Subsequent expressions may reference preceding variables, since generated code declares each alias as a var (as opposed to a function parameter, which get bound to formal parameter names only after evaluation), so you can do stuff like

<div rt-scope="users[userId] as user; user.profile as profile; profile.avatar as avatar;">

When used with rt-if, the rt-if condition is evaluated first, and only if it is truthy, the rt-scope mappings are processed. This means you can write things like

<div rt-if="user.profile" rt-scope="user.profile.image as image">

without risking accessing a field on an undefined, or doing something ugly like user.profile && user.profile.image as image.

When used with rt-repeat, the rt-scope is evaluated for every iteration, so that iteration's item and itemIndex are in scope.

rt-props

rt-props is used to inject properties into an element programmatically. It will merge the properties with the properties received in the template. This option allows you to build properties based on external logic and pass them to the template. It is also useful when passing properties set on the component to an element within the template. The expected value of this attribute is an expression returning an object. The keys will be the property name, and the values will be the property values.

Sample:
<input style="height:10px;width:3px;" rt-props="{style:{width:'5px'},type:'text'}"/>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    return function () {
        return React.DOM.input(_.merge({}, {
            'style': {
                height: '10px',
                width: '3px'
            }
        }, {
            style: { width: '5px' },
            type: 'text'
        }));
    };
});

rt-class

To reduce the boilerplate code when setting class names programatically, you can use the rt-class directive. It expects a JSON object with keys as class names, and a Boolean as the value. If the value is true, the class name will be included.

Note the following:
1. In React templates, you can use the "class" attribute as you would in HTML.
2. If you use both class and rt-class on the same HTML element, they get merged.

Sample:
<div rt-scope="{blue: true, selected: this.isSelected()} as classes">
    These are logically equivalent
    <div rt-class="classes">Reference</div>
    <div rt-class="{blue: true, selected: this.isSelected()}">Inline</div>
    <div class="blue{this.isSelected() ? ' selected' : ''}">Using the class attribute</div>
</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    function scopeClasses1(classes) {
        return React.DOM.div({}, 'These are logically equivalent', React.DOM.div({ 'className': React.addons.classSet(classes) }, 'Reference'), React.DOM.div({
            'className': React.addons.classSet({
                blue: true,
                selected: this.isSelected()
            })
        }, 'Inline'), React.DOM.div({ 'className': 'blue' + this.isSelected() ? ' selected' : '' }, 'Using the class attribute'));
    }
    return function () {
        return scopeClasses1.apply(this, [{
                blue: true,
                selected: this.isSelected()
            }]);
    };
});

rt-include

Optionally choose to extract static contents out of rt files.
rt-include is a "macro" that takes a text file (e.g svg/html/xml) and injects it into the file as if it was part of the original markup.

Sample:

given main.rt:

<div>
  <rt-include src="./my-icon.svg" />
</div>

and my-icon.svg:

<svg xmlns="http://www.w3.org/2000/svg">
  <rect height="50" width="50" style="fill: #00f"/>
</svg>

is equivalent to:

<div>
  <svg xmlns="http://www.w3.org/2000/svg">
      <rect height="50" width="50" style="fill: #00f"/>
  </svg>
</div>

rt-pre

When using the option --normalize-html-whitespace it allows to override the whitespace removal behaviour on a specific tag.

Sample:

given main.rt:

<span rt-pre>
    here   repeating   whitespaces   are   preserved
    even   if  --normalize-html-whitespace   is   on  
</span>
<span>    
    here   repeating   whitespaces   are   removed
    if  --normalize-html-whitespace   is   on   
</span>

rt-pre is applied automatically on <pre> and <textarea> tags:

Sample:

given main.rt:

<pre>
    here   repeating   whitespaces   are   preserved
    even   if  --normalize-html-whitespace   is   on  
</pre>

style

React templates allow the settings of styles inline in HTML, optionally returning an object from the evaluation context. By default, style names will be converted from hyphen-style to camelCase-style naming.

To embed JavaScript inside a style attribute, single curly braces are used. To embed an entire object, double curly braces are used. Note: When embedding objects, styles must conform to camelCase-style naming.

Sample:
<div>
    These are really equivalent
    <div style="color:white; line-height:{this.state.lineHeight}px">Inline</div>
    <div style="{{'color': 'white', 'lineHeight': this.state.lineHeight + 'px'}}">Inline</div>
</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    return function () {
        return React.DOM.div({}, 'These are really equivalent', React.DOM.div({
            'style': {
                color: 'white',
                lineHeight: this.state.lineHeight + 'px'
            }
        }, 'Inline'), React.DOM.div({
            'style': {
                'color': 'white',
                'lineHeight': this.state.lineHeight + 'px'
            }
        }, 'Inline'));
    };
});

stateless components

Since React v0.14, React allows defining a component as a pure function of its props. To enable creating a stateless component using react templates, add the rt-stateless attribute to the template's root element. Using rt-stateless generates a stateless functional component instead of a render function. The resulting function receives props and context parameters to be used in the template instead of this.props.

Sample:
<div rt-stateless>Hello {props.person}</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    return function (props, context) {
        return React.createElement('div', {}, 'Hello ', props.person);
    };
});

event handlers

React event handlers accept function references inside of {}, such as onClick="{this.myClickHandler}". When functions are not needed, lambda notation can be used, which will create a React template that creates a function for the included code. There is no performance impact, as the function created is bound to the context instead of being recreated.

The lambda notation has the form: `onClick="(evt) => console.log(evt)"`. In this example, **evt** is the name of the first argument passed into the inline function. With browser events, this will most likely be the React synthetic event. However, if you expect a property that starts with **on**Something, then React templates will treat it as an event handler. If you have an event handler called **onBoxSelected** that triggers an event with row and column params, you can write `onBoxSelected="(row, col)=>this.doSomething(row,col)"`. A no-param version is supported as well: `onClick="()=>console.log('just wanted to know it clicked')"`.

Sample:
<div rt-repeat="item in items">
    <div onClick="()=>this.itemSelected(item)" onMouseDown="{this.mouseDownHandler}">
</div>
Compiled:
define([
    'react',
    'lodash'
], function (React, _) {
    'use strict';
    function onClick1(item, itemIndex) {
        this.itemSelected(item);
    }
    function repeatItem2(item, itemIndex) {
        return React.DOM.div({}, React.DOM.div({
            'onClick': onClick1.bind(this, item, itemIndex),
            'onMouseDown': this.mouseDownHandler
        }));
    }
    return function () {
        return _.map(items, repeatItem2.bind(this));
    };
});

rt-import and using other components in the template

In many cases, you'd like to use either external code or other components within your template. To do so, you can use an rt-import tag that lets you include dependencies in a syntax similar to ES6 imports:

<rt-import name="*" as="depVarName" from="depName"/>

Once included, depVarName will be in scope. You can only use rt-import tags at the beginning of your template. When including React components, they can be referred to by their tag name inside a template. For example, <MySlider prop1="val1" onMyChange="{this.onSliderMoved}">. Nesting is also supported: <MyContainer><div>child</div><div>another</div></MyContainer>.

Children are accessible from this.props.children.

Sample:
<rt-import name="member" from="module-name"/>
<rt-import name="member" as="alias2" from="module-name"/>
<rt-import name="*" as="alias3" from="module-name"/>
<rt-import name="default" as="alias4" from="module-name"/>
<div>
</div>
Compiled (ES6 flag):
import * as React from 'react/addons';
import * as _ from 'lodash';
import { member } from 'module-name';
import { member as alias2 } from 'module-name';
import * as alias3 from 'module-name';
import alias4 from 'module-name';
export default function () {
    return React.createElement('div', {});
}
Compiled (AMD):
define('div', [
    'react',
    'lodash',
    'module-name',
    'module-name',
    'module-name',
    'module-name'
], function (React, _, $2, $3, alias3, $5) {
    'use strict';
    var member = $2.member;
    var alias2 = $3.member;
    var alias4 = $5.default;
    return function () {
        return React.createElement('div', {});
    };
});
Compiled (with CommonJS flag):
'use strict';
var React = require('react/addons');
var _ = require('lodash');
var member = require('module-name').member;
var alias2 = require('module-name').member;
var alias3 = require('module-name');
var alias4 = require('module-name').default;
module.exports = function () {
    return React.createElement('div', {});
};

deprecated: rt-require

The tag rt-require is deprecated and replaced with rt-import. Its syntax is similar to rt-import but does not allow default imports:

<rt-require dependency="comps/myComp" as="MyComp"/>
<rt-require dependency="utils/utils" as="utils"/>
<MyComp rt-repeat="item in items">
    <div>{utils.toLower(item.name)}</div>
</MyComp>

Inline Templates

Although we recommend separating the templates to a separate .rt file, there's an option to use a template inline as the render method (ร  la JSX). To do that, write your code in a .jsrt file, and send it to react-templates with the modules flag set to jsrt.

Sample:
define(['react','lodash'], function (React, _) {
    var comp = React.createClass({
        render:
            <template>
                <div>hello world</div>
            </template>
    });

    return comp;
});
Compiled (with jsrt flag):
define([
    'react',
    'lodash'
], function (React, _) {
    var comp = React.createClass({
        render: function () {
            return function () {
                return React.createElement('div', {}, 'hello world');
            };
        }()
    });
    return comp;
});

rt-template, and defining properties template functions

In cases you'd like to use a property that accepts a function and return renderable React component. You should use a rt-template tag that will let you do exactly that: <rt-template prop="propName" arguments="arg1, arg2"/>.

Templates can be used only as an immediate child of the component that it will be used in. All scope variable will be available in the template function.

Sample:
<MyComp data="{[1,2,3]}">
    <rt-template prop="renderItem" arguments="item">
        <div>{item}</div>
    </rt-template>
</MyComp>
Compiled (AMD):
define([
    'react/addons',
    'lodash'
], function (React, _) {
    'use strict';
    function renderItem1(item) {
        return React.createElement('div', {}, item);
    }
    return function () {
        return React.createElement(MyComp, {
            'data': [
                1,
                2,
                3
            ],
            'renderItem': renderItem1.bind(this)
        });
    };
});
Compiled (with CommonJS flag):
'use strict';
var React = require('react/addons');
var _ = require('lodash');
function renderItem1(item) {
    return React.createElement('div', {}, item);
}
module.exports = function () {
    return React.createElement(MyComp, {
        'data': [
            1,
            2,
            3
        ],
        'renderItem': renderItem1.bind(this)
    });
};
Compiled (with ES6 flag):
import React from 'react/addons';
import _ from 'lodash';
function renderItem1(item) {
    return React.createElement('div', {}, item);
}
export default function () {
    return React.createElement(MyComp, {
        'data': [
            1,
            2,
            3
        ],
        'renderItem': renderItem1.bind(this)
    });
};

Contributing

See the Contributing page.

License

Copyright (c) 2015 Wix. Licensed under the MIT license.

react-templates's People

Contributors

amitkaufman avatar avi avatar danyshaanan avatar shaikfir avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-templates's Issues

'use' element inside svg isn't being created as a string

I'm currently using svg's to display some logos:

<svg class="badge"><use xlinkHref="#logo"></use></svg>

However this is getting created like so:

React.createElement('svg', { 'className': 'badge' }, React.createElement(use, { 'xlinkHref': '#logo' })))

Notice that use is not being created with quotes. Thus, when this compiles it fails to work since use was never defined. Thoughts?

Compile template syntax in jsx files

It would be nice if this template markup syntax, with sugar for looping/conditionals/etc, could be used in a component .jsx file as well as in a .rt file.

Many people do prefer their markup in their component, but would still benefit from all the syntactic sugar added by react-templates. How hard would it be to extend the compiler to be able to process a full .jsx file?

rt-class uses React.addons.classSet which will be deprecated

from react/docs/class-name-manipulation

"This module now exists independently at JedWatson/classnames and is React-agnostic. The add-on here will thus be removed in the future."

just to inform you that i get a warning when i use the rt-class, and that in future version the React.addons.classSet will be deprecated.

thanx,
ran

Don't accept nodejs PATH

error_rt
Don't accept the default path for Nodejs, and it's in my main PATH.
I see this message: Path to node interpreter is invalid Fix it
My specs is Windows 7 x64 Ultimate
WebStorm 10.0.1

Pass data to the template?

Is there no way to pass data to the template from the render method? Checked the docs and issues but couldn't find anything. Something like:

import template from './MyComponent.rt';

export default class MyClass extends Component {
  render() {
    var someVariable = 'foobar';

    // How do I pass someVariable for it to be accessible?
    return template.apply(this);
  }
}
<h1>{someVariable}</h1>

There's an improved version of this library available

I implemented some improvements to this library. Based on a chat in one of the issues, it seems that the authors here may be inactive or slow at dealing with PRs, so I branched the library here:

https://github.com/anchann/react-templates

Locally I'm using it with npm link. I figured we could publish parallel npm packages, perhaps react-templates-improved, but since I'm lazy, I won't proactively do so unless somebody asks me to.

Docs - not entirely clear how to compile or use with CommonJS?

I see that there's a CommonJS example as the output of the template, but when using tools like WebPack & gulp-react, I'm not sure how these templates would fit into my workflow.

Do I author a myThing.jsx and myThing.react.html? How do I combine the two?

Using react-templates with EcmaScript 2015 (ES6) classes

My footer.rt looks as follows:

<nav>
  <span className='current-year'>&copy; { this.currentYear() }</span>
</nav>

and footer.js is:

import template from './footer.rt'

export default class extends React.Component {
  currentYear() {
    return new Date().getFullYear()
  }

  render() {
    return template()
  }
}

I get an error that this is undefined inside template. How to handle ES6 classes?

is there any way to use component without requiring?

Sometimes we define multiple component classes in one file since they won't be reused anywhere else, but when we use it in react-template, we are forced to separate those classes in different files. Is there anyway to do:

component.coffee

ComponentA = React.createClass 
  render: ->
    rtA.apply(this)

ComponentB = React.createClass
  render: ->
    rtB.apply(this)

componentA.rt

<ComponentB />

componentB.rt

<div> hello </div>

[Question] Usage with Facebook Flow

Does anyone have a workflow with react-templates that can preserve the type-checking properties one would get from JSX?

With JSX, template javascript can be type-checked by Flow because it resides next to the javascript using it. Generating code without type declarations into separate files or even just separate modules that rely on this is going to lose a lot of potential type-safety at the module boundary.

I can think of 2 approaches:

  1. keep the template in the same file as the JS or otherwise directly include the resulting JS in that same file.
  2. have react-template generate Flow type declarations that can be imported into the JS.

Key is not defined

Hi everyone!

I'm getting started with your useful templating engine.

I'm having this issue though, when I write this template:

<div id="LoginPage">
    <div rt-if="true == true">Hii</div>
</div>

I have this error:

ERROR in ./src/javascripts/pages/login/LoginPage.rt
Module build failed: TypeError: Cannot call method 'warn' of undefined
    at validate (/home/anomen/Desktop/circlad/front-end/node_modules/react-templates/src/reactTemplates.js:420:23)
    at Array.forEach (native)
    at validate (/home/anomen/Desktop/circlad/front-end/node_modules/react-templates/src/reactTemplates.js:423:23)
    at Array.forEach (native)
    at validate (/home/anomen/Desktop/circlad/front-end/node_modules/react-templates/src/reactTemplates.js:423:23)
    at Object.convertTemplateToReact (/home/anomen/Desktop/circlad/front-end/node_modules/react-templates/src/reactTemplates.js:438:5)
    at Object.module.exports (/home/anomen/Desktop/circlad/front-end/node_modules/react-templates-loader/index.js:5:24)

Opening this file at this line, I get:

        reportContext.warn('rt-if without a key', options.fileName, loc.pos.line, loc.pos.col, loc.start, loc.end);                                             

If I write:

<div id="LoginPage">
    <div key="heyy" rt-if="true == true">Hii</div>
</div>

It works well.

I keep reading the documentation, I don't see any mention of a property "key" (I may be wrong). Do I have to write a key in every single tag that uses rt-if?

Thanks!
Kevin

error rt-require may have no children

I have no idea what this error message means. The sad thing is that I cannot even figure it out from looking at the source code: I have no idea how/where rt-require obtains its children.

Working with react 0.14.0?

When working with react 0.14.0, using "es6" flag, require("react/addons") raise an "not found" error.

Maybe this is deprecated in react 0.14.0, and I think we should be prepared for the up coming update.

Thanks.

Embedding React Code should not lead to string concatenation

I have the following in my template

<div class="foobar">
  {React.createElement("h1", {}, "Hello, World!")}
</div>

Obviously, I have something a bit more complex than just creating a simple element (it calls this.createMyElement(someDataIGetInALoop).

However, this compiles as follows:

React.createElement("div", {}, "\n   " + React.createElement("h1", {}, "Hello, World!") + "\n")

which always gives you the output [Object Object].

I thought of one of two ways to potentially solve this.

  1. Either get rid of spacing around {}
  2. Create a new field called rt-content, which will let you set the children programatically.

Server usage

Is it possible to use react-templates on server-side code without compiling the .rt file to .js, just importing the .rt like if I used WebPack with react-templates-loader? Something like this:

component.jsx

import React from 'react';
import render from './template.rt';

export default React.createClass({
  displayName: 'Component',
  render,
});

template.rt

<div>
  Hello world
</div>

rt-if throwing error 'undefined is not a function'

<div rt-if="true==true">
  Testing
</div>

Is telling me this:

[17:53:34] Plumber found unhandled error:
 TypeError in plugin 'gulp-react-templates'
Message:
    undefined is not a function

Using react-templates 0.1.8 via gulp-react-templates 0.0.6

May make standalone project to attempt reproduction...unless anyone has ideas.

Playground not working on https

If the user has HTTPS Everywhere or accesses the site via https, the scripts fail to load. You can fix this by using relative urls (//) instead of http://.

parse component 's props error

I use a component in a .rt file , like:

<Table dataSource={this.state.fakeData} columns={this.state.columns}/>

then columns be parsed to string type, but it's an array

but.

<Table dataSource={this.state.fakeData} columns={this.state.columns} />

it worked~
the only difference is one space

Route.Link

How can i get this
var Router = require('react-router'); var Link = Router.Link;
Whit this
<rt-require dependency="react-router" as="ReactRouter"/> <rt-require dependency={ReactRouter.Link} as="Link"/>

Passing props to nested components?

I'm trying to set up a simple Hello World app and am confused as to how props get passed to nested components with react-templates. I tried following the example given with InfiniteScroll.js but it doesn't seem to be working for me.

The initialization code:

import ListTemplate from './ListTemplate.rt.js';
import React from '../vendor/react';

var ListPosts = React.createClass({
  render: function() {
    return ListTemplate.apply(this);
  }

})

function init() {
    React.render(
      React.createElement(ListPosts), 
      document.querySelector("#content"));
}

module.exports = {
    init: init
}

ListTemplate.rt:

<rt-require dependency="./Hello" as="Hello"/>
<div>
    <p>My First React Templates App:</p>

    <Hello msg="Hello World">
        <p>Message from props: {this.props.msg}</p>
    </Hello>
</div>

Hello.js

import React from '../vendor/react';

export default class Hello extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return React.DOM.div(this.props, this.props.children)
  }
}

ListTemplate.rt.js:

import React from '../vendor/react';
import _ from '../vendor/lodash';
import Hello from './Hello';
export default function () {
    return React.createElement('div', {}, React.createElement('p', {}, 'My First React Templates App:'), React.createElement(Hello, { 'msg': 'Hello World' }, React.createElement('p', {}, 'Message from props: ', this.props.msg)));
};

The output is just: "My first React Templates App:" . The problem I see is that this.props.msg is not defined in ListTemplate.rt.js. The documentation doesn't seem to provide examples of this type of process. Any ideas?

Unable to modify render function definition?

For example i am returning,

define([
    'react', 
    'lodash', 
    'jquery', 
    './ArticleTopHeader.rt'
    ], function (React, _, $, Articletemplate) {
    'use strict';

    return React.createClass({
        render: Articletemplate
    });

I have 2 templates,
e.g. ArticleTopHeader.rt and ArticleSimple.rt for same component.

I am going to choose dynamically(depends on props value) which one should load, so my question is that where should i check condition.

How can i modify render method?

Possible to use with native map function (instead of Lodash?)

I really like the syntax of react-templates, however one potential gotcha is that we're using custom container types in a few places.

We've implemented a custom map function that handles these correctly, however since react-templates uses lodash for iteration it'll just treat our containers as a raw object instead of mapping correctly.

Is there a way to toggle react-templates to call xs.map(fn) instead of _.map(xs, fn)?

The last space before a self closing tag is significant

This has actually tripped me up more than a few times. If there is no space before the '/>', we get invalid dom, which causes elements to vanish. This especially happens if you do not quote the property properly.

example:

<div>
 <img class={"foobar"}/>
</div>

results in

function () {
    return React.createElement('div', {}, React.createElement('img', { 'className': 'foobar' + '/' }));
};
<div>
 <img class={"foobar"} />
</div>

results in

function () {
    return React.createElement('div', {}, React.createElement('img', { 'className': 'foobar' }));
};

rt-if-not

Hello,

I implemented the improved readability counterpart of rt-if, the rt-if-not. Also cleaned up the code a bit. It's sitting in https://github.com/anchann/react-templates, but I'll be happy to rebase off the tip of your main branch and submit a proper PR once you're done reviewing and merging all the in-progress changes.

-a

Jest integration

Hi, I've just introduced react-templates and I'm having trouble to preprocess the .rt files

[email protected] test /home/****

jest

Using Jest CLI v0.5.2
FAIL tests/tracker-test.js (0.862s)
โ— Tracker โ€บ it Verify that the state contains the given steps

  • SyntaxError: /home/**/tracker.js: /home/*/tracker.rt: Unexpected token <

It's blowing up because the .rt file is not compiled.

Jest is configured as follow:
https://facebook.github.io/jest/docs/tutorial-react.html#setup

But I'm pretty sure that I need to write a custom preprocessor that invokes react-template AND deamdify (or let react-template to compile directly to commonjs).

Any suggestion?

no space allowed?

<div onClick={ this.hello }>Hello</div>

got this error:

when using 'on' events, use lambda '(p1,p2)=>body' notation or use {} to return a callback function. error: [onClick='{']

while

<div onClick={this.hello}>Hello</div>

is fine

lodash dependency

Hi, I'm using react-templates in a project. All good so far :)

Question: what do you need lodash for? I see that you use _.map. What else? I'm asking because maybe you can add only the functions that you need instead of requiring the entire library. lodash increases js bundle size at least by 50k. Is not that much but is just a thought.

Thanks for this library!

compiled rt not using React.DOM

react: 0.14.3
react-dom: 0.14.3
react-templates: 0.3.2
react-templates-loader: 0.2.0

snippet from my webpack.config.js:

module: {
  loaders: [
    { test: /\.rt/, loader: 'react-templates-loader' }
  ]
}

The examples in your README.md show the expected compiled template using var React = require('react') and React.DOM for creating elements.

In my compiled templates (and on http://wix.github.io/react-templates/), react is being pulled in via require('react/addons') which is now deprecated.

Warning: require('react/addons') is deprecated. Access using require('react-addons-{addon}') instead.

I think, ideally, React would be required in via require('react') or require('react-dom') as illustrated in your README.md - is this an issue with the webpack loader I'm using? What is the preferred approach for compiling react templates? Or, is there something I'm missing?

Thanks!

Feature Request: Support hyphenated tag names

The custom-elements spec requires that custom elements contain a hyphen in the name. React natively supports this with React.createElement("my-custom-element", null). Currently, react-templates compiles <my-custom-element> as React.createElement(my - custom - element, {}), which is undesirable.

Additionally, it would be nice to support hyphenated identifiers for components imported via rt-require: <rt-require dependency='users/form' as='users-form'/>.

This could be handled in the templating phase (pre esprima.parse), and two separate cases would need to be handled:

  1. For hyphens in rt-require components: convert dash-case names to camelCase.
  2. For custom elements, enclose the identifier in quotes.

I'd be willing to work on this, but I figure I'd check to see if there were interest in the idea before starting development.

rt-require - ES6 module resolving is not working

When using the ES6 modules option,
lines like:

<rt-require dependency="./Item" as="Item"/>

convert to:

import {Item} from "./Item"

With brackets it actually tries to import the Item member from the module.
However, often modules export themselves as a whole (export default), so it should be:

import Item from "./Item"

Even the basic conversion fail, as these lines are added to each conversion:

import {React} from "react/addons";
import {_} from "lodash";

and these should be without brackets.

Props that are React Elements are not supported

I'm using material-ui in a project and was hoping to use react-templates as a tidy way to remove the html content from the jsx.

Problem encountered though in using the ListItem component, it has some optional props that expect to be passed React Elements.

So in jsx you might have

var mui = require('material-ui'); var FileFolder = require('material-ui/lib/svg-icons/file/folder');

.... in render

<mui.ListItem primaryText="Example item" leftIcon={<FileFolder />} />

In my rt file I I can rt-require the material component straight forward enough.
On compilation though you'll get a parse error

Failed to parse text '{<FileFolder' while parsing file: <file path>

I presume because rt is treating the {} markup as signifying javascript snippet?

I guess such nesting is outside of react-templates scope currently?

rt-repeat: No warning when there's no key defined

Is there a reason why the following warning does not appear when using rt-repeat?

I find this warning very important, especially for new users...

Each child in an array should have a unique "key" prop.
Check the render method of undefined. See http://fb.me/react-warning-keys for more information.

Repeat-inside

Is there a simple way to do repeat-inside through children like some angular plugins does?

Ex.:

<dl repeat-inside="(word, definition) in words">
    <dt>{{word}}</dt>
    <dd>{{definition}}</dd>
</dl>

Location where project will be maintained

This project does not seem to be maintained anymore. But there are users who are willing to maintain this project, see this comment for example: #43 (comment)

Please specify where this project will be maintained. I am opening this issue to keep the discussion in one place.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.