Merge pull request #1 from wix/rtProps

Added rt-props directive
This commit is contained in:
Avi Marcus 2014-11-30 10:31:18 +02:00
commit dddc3770a4
5 changed files with 39 additions and 2 deletions

View File

@ -21,6 +21,7 @@ http://wix.github.io/react-templates/
* rt-if
* rt-repeat
* rt-scope
* rt-props
* rt-class
* style
* event handlers
@ -140,6 +141,34 @@ define([
});
```
## rt-props
This directive is used to inject properties to an element programmatically. It will merge the properties with the properties received in the template. This option allows the code writer to build properties based on some app 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 properties and the values will be the property values.
###### Sample:
```html
<input style="height:10px;width:3px;" rt-props="{style:{width:'5px'},type:'text'}"/>
```
###### Compiled:
```javascript
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
In order to reduce the boiler-plate code when programatically setting class names, you can use the rt-class directive. It expectes to get a JSON object with keys as class names, and a value of true or false as the value. If the value is true, the class name will be included. Please note the following:
1. In react templates, you can use the "class" attribute the same as you'd do in html. If you like, you can even have execution context within

View File

@ -11,6 +11,7 @@ var stringUtils = require('./stringUtils');
var repeatTemplate = _.template('_.map(<%= collection %>,<%= repeatFunction %>.bind(<%= repeatBinds %>))');
var ifTemplate = _.template('((<%= condition %>)?(<%= body %>):null)');
var propsTemplate = _.template('_.merge({}, <%= generatedProps %>, <%= rtProps %>)');
var classSetTemplate = _.template('React.addons.classSet(<%= classSet %>)');
var simpleTagTemplate = _.template('<%= name %>(<%= props %><%= children %>)');
var tagTemplate = _.template('<%= name %>.apply(this,_.flatten([<%= props %><%= children %>]))');
@ -22,6 +23,7 @@ var templateProp = 'rt-repeat';
var ifProp = 'rt-if';
var classSetProp = 'rt-class';
var scopeProp = 'rt-scope';
var propsProp = 'rt-props';
var reactSupportedAttributes = ['accept', 'acceptCharset', 'accessKey', 'action', 'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete', 'autoPlay', 'cellPadding', 'cellSpacing', 'charSet', 'checked', 'classID', 'className', 'cols', 'colSpan', 'content', 'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data', 'dateTime', 'defer', 'dir', 'disabled', 'download', 'draggable', 'encType', 'form', 'formNoValidate', 'frameBorder', 'height', 'hidden', 'href', 'hrefLang', 'htmlFor', 'httpEquiv', 'icon', 'id', 'label', 'lang', 'list', 'loop', 'manifest', 'max', 'maxLength', 'media', 'mediaGroup', 'method', 'min', 'multiple', 'muted', 'name', 'noValidate', 'open', 'pattern', 'placeholder', 'poster', 'preload', 'radioGroup', 'readOnly', 'rel', 'required', 'role', 'rows', 'rowSpan', 'sandbox', 'scope', 'scrolling', 'seamless', 'selected', 'shape', 'size', 'sizes', 'span', 'spellCheck', 'src', 'srcDoc', 'srcSet', 'start', 'step', 'style', 'tabIndex', 'target', 'title', 'type', 'useMap', 'value', 'width', 'wmode'];
var attributesMapping = {'class': 'className', 'rt-class': 'className'};
@ -261,6 +263,9 @@ function convertHtmlToReact(node, context) {
stringUtils.addIfNotThere(context.boundParams, data.item + 'Index');
}
data.props = generateProps(node, context);
if (node.attribs[propsProp]) {
data.props = propsTemplate({generatedProps: data.props, rtProps: node.attribs[propsProp]});
}
if (node.attribs[ifProp]) {
data.condition = node.attribs[ifProp].trim();
}

2
test/data/props.rt Normal file
View File

@ -0,0 +1,2 @@
<!doctype rt>
<input rt-scope="'test' as i" alt="test rt-props" style="height:10px;width:3px;" rt-props="{style:{width:'5px'},type:'text',value:i}"/>

1
test/data/props.rt.html Normal file
View File

@ -0,0 +1 @@
<input alt="test rt-props" style="height:10px;width:5px;" type="text" value="test"/>

View File

@ -36,7 +36,7 @@ function normalizeHtml(html) {
}
test('html tests', function (t) {
var files = ['scope.rt', 'lambda.rt','eval.rt'];
var files = ['scope.rt', 'lambda.rt','eval.rt', 'props.rt'];
t.plan(files.length);
files.forEach(check);
@ -81,7 +81,7 @@ test('util.isStale', function (t) {
var mtime2 = new Date(1995, 11, 17, 3, 24, 1);
fs.utimesSync(b, mtime2, mtime2);
var util = require('../../src/fsUtil');
var fsUtil = require('../../src/fsUtil');
var actual = fsUtil.isStale(a, b);
t.equal(actual, false);
actual = fsUtil.isStale(b, a);