Change docs to rt-import instead of rt-require
This commit is contained in:
parent
3913453642
commit
8103d35585
117
README.md
117
README.md
|
@ -35,7 +35,7 @@ https://github.com/wix/react-templates-transform-boilerplate
|
|||
http://plugins.jetbrains.com/plugin/7648
|
||||
|
||||
|
||||
###### Basic concepts for React templates
|
||||
## Basic concepts for React templates
|
||||
* Any valid HTML (including comments) is a template
|
||||
* {} to identify JS expression
|
||||
* Built-in directives:
|
||||
|
@ -44,13 +44,14 @@ http://plugins.jetbrains.com/plugin/7648
|
|||
* [rt-scope](#rt-scope)
|
||||
* [rt-props](#rt-props)
|
||||
* [rt-class](#rt-class)
|
||||
* [rt-require](#rt-require-and-using-other-components-in-the-template)
|
||||
* [rt-import](#using-other-components-in-the-template)
|
||||
* ~~rt-require~~ (deprecated, use rt-import)
|
||||
* [rt-template](#rt-template-and-defining-properties-template-functions)
|
||||
* [rt-include](#rt-include)
|
||||
* [styles](#styles)
|
||||
* [event handlers](#event-handlers)
|
||||
|
||||
###### Why not use JSX?
|
||||
## 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.
|
||||
|
||||
|
@ -410,13 +411,73 @@ define([
|
|||
});
|
||||
```
|
||||
|
||||
## rt-require, and using other components in the template
|
||||
In many cases, you'd like to use either external code or other components within your template. An **rt-require** tag lets you include dependencies: `<rt-require dependency="depVarPath" as="depVarName"/>`.
|
||||
Once included, **depVarName** will be in scope. You can only use rt-require tags at the beginning of your template. When including React components, they can be referred to by their tag name inside a template.
|
||||
## 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:
|
||||
```xml
|
||||
<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:
|
||||
```xml
|
||||
<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):
|
||||
```javascript
|
||||
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):
|
||||
```javascript
|
||||
define('div', [
|
||||
'react/addons',
|
||||
'lodash',
|
||||
'module-name',
|
||||
'module-name',
|
||||
'module-name',
|
||||
'module-name'
|
||||
], function (React, _, member, alias2, alias3, alias4) {
|
||||
'use strict';
|
||||
return function () {
|
||||
return React.createElement('div', {});
|
||||
};
|
||||
});
|
||||
```
|
||||
###### Compiled (with CommonJS flag):
|
||||
```javascript
|
||||
'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:
|
||||
```html
|
||||
<rt-require dependency="comps/myComp" as="MyComp"/>
|
||||
<rt-require dependency="utils/utils" as="utils"/>
|
||||
|
@ -424,50 +485,6 @@ Children are accessible from **this.props.children**.
|
|||
<div>{utils.toLower(item.name)}</div>
|
||||
</MyComp>
|
||||
```
|
||||
###### Compiled (AMD):
|
||||
```javascript
|
||||
define([
|
||||
'react/addons',
|
||||
'lodash',
|
||||
'comps/myComp',
|
||||
'utils/utils'
|
||||
], function (React, _, MyComp, utils) {
|
||||
'use strict';
|
||||
function repeatItem1(item, itemIndex) {
|
||||
return React.createElement(MyComp, {}, React.createElement('div', {}, utils.toLower(item.name)));
|
||||
}
|
||||
return function () {
|
||||
return _.map(items, repeatItem1.bind(this));
|
||||
};
|
||||
});
|
||||
```
|
||||
###### Compiled (with CommonJS flag):
|
||||
```javascript
|
||||
var React = require('react/addons');
|
||||
var _ = require('lodash');
|
||||
var MyComp = require('comps/myComp');
|
||||
var utils = require('utils/utils');
|
||||
'use strict';
|
||||
function repeatItem1(item, itemIndex) {
|
||||
return React.createElement(MyComp, {}, React.createElement('div', {}, utils.toLower(item.name)));
|
||||
}
|
||||
module.exports = function () {
|
||||
return _.map(items, repeatItem1.bind(this));
|
||||
};
|
||||
```
|
||||
###### Compiled (with ES6 flag):
|
||||
```javascript
|
||||
import React from 'react/addons';
|
||||
import _ from 'lodash';
|
||||
import MyComp from 'comps/myComp';
|
||||
import utils from 'utils/utils';
|
||||
function repeatItem1(item, itemIndex) {
|
||||
return React.createElement(MyComp, {}, React.createElement('div', {}, utils.toLower(item.name)));
|
||||
}
|
||||
export default function () {
|
||||
return _.map(items, repeatItem1.bind(this));
|
||||
};
|
||||
```
|
||||
|
||||
## 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).
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -27,34 +27,9 @@ function getLine(html, node) {
|
|||
return { line: linesUntil.length, col: linesUntil[linesUntil.length - 1].length + 1 };
|
||||
}
|
||||
|
||||
//function getLine(node) {
|
||||
// if (!node) {
|
||||
// return 0;
|
||||
// }
|
||||
// const line = 0;
|
||||
// const prev = node.prev;
|
||||
// while (prev) {
|
||||
// const nl = prev.data.split('\n').length - 1;
|
||||
// line += nl;
|
||||
// prev = prev.prev;
|
||||
// }
|
||||
//
|
||||
// line += getLine(node.parent);
|
||||
// return line + 1;
|
||||
//}
|
||||
|
||||
//function RTCodeError(message, line) {
|
||||
// this.name = 'RTCodeError';
|
||||
// this.message = message || '';
|
||||
// this.line = line || -1;
|
||||
//}
|
||||
//RTCodeError.prototype = Error.prototype;
|
||||
|
||||
// Redefine properties on Error to be enumerable
|
||||
/*eslint no-extend-native:0*/
|
||||
//Object.defineProperty(Error.prototype, 'message', {configurable: true, enumerable: true});
|
||||
//Object.defineProperty(Error.prototype, 'stack', {configurable: true, enumerable: true});
|
||||
//Object.defineProperty(Error.prototype, 'line', { configurable: true, enumerable: true });
|
||||
function norm(n) {
|
||||
return n === undefined ? -1 : n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} message
|
||||
|
@ -83,21 +58,15 @@ var RTCodeError = function (_Error) {
|
|||
_this.column = norm(column);
|
||||
return _this;
|
||||
}
|
||||
//build buildError
|
||||
|
||||
|
||||
return RTCodeError;
|
||||
}(Error);
|
||||
|
||||
function norm(n) {
|
||||
return n === undefined ? -1 : n;
|
||||
}
|
||||
|
||||
//const norm = n => n === undefined ? -1 : n;
|
||||
|
||||
/**
|
||||
* @type {buildError}
|
||||
*/
|
||||
|
||||
|
||||
RTCodeError.build = buildError;
|
||||
RTCodeError.norm = norm;
|
||||
|
||||
|
@ -348,12 +317,45 @@ var templates = {
|
|||
jsrt: templateJSRTTemplate
|
||||
};
|
||||
|
||||
var isImportAsterisk = _.matches({ member: '*' });
|
||||
var defaultCase = _.constant(true);
|
||||
|
||||
var buildImportTypeScript = _.cond([[isImportAsterisk, function (d) {
|
||||
return 'import ' + d.alias + ' = require(\'' + d.moduleName + '\');';
|
||||
}], [defaultCase, function (d) {
|
||||
return 'import ' + d.alias + ' = require(\'' + d.moduleName + '\').' + d.member + ';';
|
||||
}]]);
|
||||
|
||||
var buildImportES6 = _.cond([[isImportAsterisk, function (d) {
|
||||
return 'import * as ' + d.alias + ' from \'' + d.moduleName + '\';';
|
||||
}], [_.matches({ member: 'default' }), function (d) {
|
||||
return 'import ' + d.alias + ' from \'' + d.moduleName + '\';';
|
||||
}], [defaultCase, function (d) {
|
||||
return 'import { ' + d.member + ' as ' + d.alias + ' } from \'' + d.moduleName + '\';';
|
||||
}]]);
|
||||
|
||||
var buildImportCommonJS = _.cond([[isImportAsterisk, function (d) {
|
||||
return 'var ' + d.alias + ' = require(\'' + d.moduleName + '\');';
|
||||
}], [defaultCase, function (d) {
|
||||
return 'var ' + d.alias + ' = require(\'' + d.moduleName + '\').' + d.member + ';';
|
||||
}]]);
|
||||
|
||||
var buildImport = {
|
||||
typescript: buildImportTypeScript,
|
||||
es6: buildImportES6,
|
||||
commonjs: buildImportCommonJS,
|
||||
amd: buildImportCommonJS,
|
||||
none: buildImportCommonJS,
|
||||
jsrt: buildImportCommonJS
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
htmlSelfClosingTags: htmlSelfClosingTags,
|
||||
attributesMapping: attributesMapping,
|
||||
classNameProp: classNameProp,
|
||||
shouldUseCreateElement: shouldUseCreateElement,
|
||||
templates: templates
|
||||
templates: templates,
|
||||
buildImport: buildImport
|
||||
};
|
||||
},{"lodash":101}],7:[function(require,module,exports){
|
||||
'use strict';
|
||||
|
@ -403,6 +405,8 @@ var templateNode = 'rt-template';
|
|||
var virtualNode = 'rt-virtual';
|
||||
var includeNode = 'rt-include';
|
||||
var includeSrcAttr = 'src';
|
||||
var requireAttr = 'rt-require';
|
||||
var importAttr = 'rt-import';
|
||||
|
||||
var reactTemplatesSelfClosingTags = [includeNode];
|
||||
|
||||
|
@ -564,7 +568,6 @@ function genBind(func, args) {
|
|||
}
|
||||
|
||||
function handleStyleProp(val, node, context) {
|
||||
/*eslint lodash/prefer-lodash-chain:0*/
|
||||
var styleStr = _(val).split(';').map(_.trim).filter(function (i) {
|
||||
return _.includes(i, ':');
|
||||
}).map(function (i) {
|
||||
|
@ -600,9 +603,7 @@ function convertTagNameToConstructor(tagName, context) {
|
|||
* @return {Context}
|
||||
*/
|
||||
function defaultContext(html, options, reportContext) {
|
||||
var defaultDefines = {};
|
||||
defaultDefines[options.reactImportPath] = 'React';
|
||||
defaultDefines[options.lodashImportPath] = '_';
|
||||
var defaultDefines = [{ moduleName: options.reactImportPath, alias: 'React', member: '*' }, { moduleName: options.lodashImportPath, alias: '_', member: '*' }];
|
||||
return {
|
||||
boundParams: [],
|
||||
injectedFunctions: [],
|
||||
|
@ -678,6 +679,9 @@ function convertHtmlToReact(node, context) {
|
|||
if (node.attribs[ifAttr]) {
|
||||
validateIfAttribute(node, context, data);
|
||||
data.condition = node.attribs[ifAttr].trim();
|
||||
if (!node.attribs.key) {
|
||||
_.set(node, ['attribs', 'key'], '' + node.startIndex);
|
||||
}
|
||||
}
|
||||
|
||||
data.props = generateProps(node, context);
|
||||
|
@ -817,6 +821,48 @@ function handleSelfClosingHtmlTags(nodes) {
|
|||
});
|
||||
}
|
||||
|
||||
function handleRequire(tag, context) {
|
||||
var moduleName = void 0;
|
||||
var alias = void 0;
|
||||
var member = void 0;
|
||||
if (tag.children.length) {
|
||||
throw RTCodeError.build(context, tag, '\'' + requireAttr + '\' may have no children');
|
||||
} else if (tag.attribs.dependency && tag.attribs.as) {
|
||||
moduleName = tag.attribs.dependency;
|
||||
member = '*';
|
||||
alias = tag.attribs.as;
|
||||
}
|
||||
if (!moduleName) {
|
||||
throw RTCodeError.build(context, tag, '\'' + requireAttr + '\' needs \'dependency\' and \'as\' attributes');
|
||||
}
|
||||
context.defines.push({ moduleName: moduleName, member: member, alias: alias });
|
||||
}
|
||||
|
||||
function handleImport(tag, context) {
|
||||
var moduleName = void 0;
|
||||
var alias = void 0;
|
||||
var member = void 0;
|
||||
if (tag.children.length) {
|
||||
throw RTCodeError.build(context, tag, '\'' + importAttr + '\' may have no children');
|
||||
} else if (tag.attribs.name && tag.attribs.from) {
|
||||
moduleName = tag.attribs.from;
|
||||
member = tag.attribs.name;
|
||||
alias = tag.attribs.as;
|
||||
if (!alias) {
|
||||
if (member === '*') {
|
||||
throw RTCodeError.build(context, tag, "'*' imports must have an 'as' attribute");
|
||||
} else if (member === 'default') {
|
||||
throw RTCodeError.build(context, tag, "default imports must have an 'as' attribute");
|
||||
}
|
||||
alias = member;
|
||||
}
|
||||
}
|
||||
if (!moduleName) {
|
||||
throw RTCodeError.build(context, tag, '\'' + importAttr + '\' needs \'name\' and \'from\' attributes');
|
||||
}
|
||||
context.defines.push({ moduleName: moduleName, member: member, alias: alias });
|
||||
}
|
||||
|
||||
function convertTemplateToReact(html, options) {
|
||||
var context = require('./context');
|
||||
return convertRT(html, context, options);
|
||||
|
@ -837,13 +883,10 @@ function parseAndConvertHtmlToReact(html, context) {
|
|||
}
|
||||
var firstTag = null;
|
||||
_.forEach(rootTags, function (tag) {
|
||||
if (tag.name === 'rt-require') {
|
||||
if (!tag.attribs.dependency || !tag.attribs.as) {
|
||||
throw RTCodeError.build(context, tag, "rt-require needs 'dependency' and 'as' attributes");
|
||||
} else if (tag.children.length) {
|
||||
throw RTCodeError.build(context, tag, 'rt-require may have no children');
|
||||
}
|
||||
context.defines[tag.attribs.dependency] = tag.attribs.as;
|
||||
if (tag.name === requireAttr) {
|
||||
handleRequire(tag, context);
|
||||
} else if (tag.name === importAttr) {
|
||||
handleImport(tag, context);
|
||||
} else if (firstTag === null) {
|
||||
firstTag = tag;
|
||||
} else {
|
||||
|
@ -870,30 +913,20 @@ function convertRT(html, reportContext, options) {
|
|||
var context = defaultContext(html, options, reportContext);
|
||||
var body = parseAndConvertHtmlToReact(html, context);
|
||||
|
||||
var requirePaths = _(context.defines).keys().map(function (def) {
|
||||
return '"' + def + '"';
|
||||
var requirePaths = _.map(context.defines, function (d) {
|
||||
return '"' + d.moduleName + '"';
|
||||
}).join(',');
|
||||
var buildImport = void 0;
|
||||
if (options.modules === 'typescript') {
|
||||
buildImport = function buildImport(v, p) {
|
||||
return 'import ' + v + ' = require(\'' + p + '\');';
|
||||
};
|
||||
} else if (options.modules === 'es6') {
|
||||
// eslint-disable-line
|
||||
buildImport = function buildImport(v, p) {
|
||||
return 'import ' + v + ' from \'' + p + '\';';
|
||||
};
|
||||
} else {
|
||||
buildImport = function buildImport(v, p) {
|
||||
return 'var ' + v + ' = require(\'' + p + '\');';
|
||||
};
|
||||
}
|
||||
var requireNames = _.map(context.defines, function (d) {
|
||||
return '' + d.alias;
|
||||
}).join(',');
|
||||
var buildImport = reactSupport.buildImport[options.modules] || reactSupport.buildImport.commonjs;
|
||||
var requires = _.map(context.defines, buildImport).join('\n');
|
||||
var header = options.flow ? '/* @flow */\n' : '';
|
||||
var vars = header + _(context.defines).map(buildImport).join('\n');
|
||||
var vars = header + requires;
|
||||
var data = {
|
||||
body: body,
|
||||
injectedFunctions: context.injectedFunctions.join('\n'),
|
||||
requireNames: _.values(context.defines).join(','),
|
||||
requireNames: requireNames,
|
||||
requirePaths: requirePaths,
|
||||
vars: vars,
|
||||
name: options.name
|
||||
|
@ -1039,6 +1072,10 @@ function validate(options, context, reportContext, node) {
|
|||
var loc = rtError.getNodeLoc(context, node);
|
||||
reportContext.warn('rt-if without a key', options.fileName, loc.pos.line, loc.pos.col, loc.start, loc.end);
|
||||
}
|
||||
if (node.type === 'tag' && node.attribs['rt-require'] && (node.attribs.dependency || node.attribs.as)) {
|
||||
var _loc = rtError.getNodeLoc(context, node);
|
||||
reportContext.warn("'rt-require' is obsolete, use 'rt-import' instead", options.fileName, _loc.pos.line, _loc.pos.col, _loc.start, _loc.end);
|
||||
}
|
||||
if (node.children) {
|
||||
node.children.forEach(validate.bind(this, options, context, reportContext));
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,8 +5,8 @@ define(['lodash', 'react', './examples.rt',
|
|||
'text!./samples/rt-props.code', 'text!./samples/rt-props.rt',
|
||||
'text!./samples/rt-repeat.code', 'text!./samples/rt-repeat.rt',
|
||||
'text!./samples/weather.code', 'text!./samples/weather.rt',
|
||||
'text!./samples/rt-require.rt'
|
||||
], function (_, React, examplesTemplate, helloCode, helloRT, todoCode, todoRT, rtIfCode, rtIfRT, rtPropsCode, rtPropsRT, rtRepeatCode, rtRepeatRT, weatherCode, weatherRT, rtRequireRT) {
|
||||
'text!./samples/rt-import.rt'
|
||||
], function (_, React, examplesTemplate, helloCode, helloRT, todoCode, todoRT, rtIfCode, rtIfRT, rtPropsCode, rtPropsRT, rtRepeatCode, rtRepeatRT, weatherCode, weatherRT, rtImportRT) {
|
||||
'use strict';
|
||||
var samples = {
|
||||
hello: [helloCode, helloRT],
|
||||
|
@ -16,22 +16,17 @@ define(['lodash', 'react', './examples.rt',
|
|||
repeat: [rtRepeatCode, rtRepeatRT],
|
||||
weather: [weatherCode, weatherRT]
|
||||
};
|
||||
//samples = _.map(samples, function (v, k) {
|
||||
// return {name: k, templateProps: _.template(v[0])({name: k}), templateHTML: v[1]};
|
||||
//});
|
||||
_.forEach(samples, function (v, k) {
|
||||
samples[k] = {name: k, templateProps: _.template(v[0])({name: k}), templateHTML: v[1]};
|
||||
});
|
||||
samples = _.mapValues(samples, function (v, k) { return {name: k, templateProps: _.template(v[0])({name: k}), templateHTML: v[1]}; });
|
||||
|
||||
return React.createClass({
|
||||
displayName: 'Examples',
|
||||
mixins: [React.addons.LinkedStateMixin],
|
||||
getInitialState: function () {
|
||||
var codeAmd = window.reactTemplates.convertTemplateToReact(rtRequireRT, {modules: 'amd', name: 'template'});
|
||||
var codeCJS = window.reactTemplates.convertTemplateToReact(rtRequireRT, {modules: 'commonjs', name: 'template'});
|
||||
var codeES6 = window.reactTemplates.convertTemplateToReact(rtRequireRT, {modules: 'es6', name: 'template'});
|
||||
var codeAmd = window.reactTemplates.convertTemplateToReact(rtImportRT, {modules: 'amd', name: 'template'});
|
||||
var codeCJS = window.reactTemplates.convertTemplateToReact(rtImportRT, {modules: 'commonjs', name: 'template'});
|
||||
var codeES6 = window.reactTemplates.convertTemplateToReact(rtImportRT, {modules: 'es6', name: 'template'});
|
||||
return {
|
||||
rtRequire: {value: rtRequireRT},
|
||||
rtImport: {value: rtImportRT},
|
||||
amd: {value: codeAmd},
|
||||
cjs: {value: codeCJS},
|
||||
es6: {value: codeES6},
|
||||
|
|
|
@ -44,12 +44,12 @@
|
|||
</p>
|
||||
<playground id="weatherExample" rt-props="this.state.samples.weather" direction="horizontal"></playground>
|
||||
</div>
|
||||
<div id="rt-require" class="example">
|
||||
<h3>rt-require</h3>
|
||||
<div id="rt-import" class="example">
|
||||
<h3>rt-import</h3>
|
||||
<p>
|
||||
This example shows how to load other React components and libraries into a React template and then use them within the template.
|
||||
</p>
|
||||
<viewer rt-props="this.state.rtRequire" mode="javascript" />
|
||||
<viewer rt-props="this.state.rtImport" mode="javascript" />
|
||||
</div>
|
||||
<div id="amd" class="example">
|
||||
<h3>AMD</h3>
|
||||
|
|
|
@ -25,9 +25,9 @@ define([
|
|||
'id': 'weatherExample',
|
||||
'direction': 'horizontal'
|
||||
}, this.state.samples.weather))), React.createElement('div', {
|
||||
'id': 'rt-require',
|
||||
'id': 'rt-import',
|
||||
'className': 'example'
|
||||
}, React.createElement('h3', {}, 'rt-require'), React.createElement('p', {}, '\n This example shows how to load other React components and libraries into a React template and then use them within the template.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.rtRequire))), React.createElement('div', {
|
||||
}, React.createElement('h3', {}, 'rt-import'), React.createElement('p', {}, '\n This example shows how to load other React components and libraries into a React template and then use them within the template.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.rtImport))), React.createElement('div', {
|
||||
'id': 'amd',
|
||||
'className': 'example'
|
||||
}, React.createElement('h3', {}, 'AMD'), React.createElement('p', {}, '\n This example shows the rt-require sample output with AMD support.\n '), React.createElement(viewer, _.assign({}, { 'mode': 'javascript' }, this.state.amd))), React.createElement('div', {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<rt-import name="myComp" from="comps" />
|
||||
<rt-import name="*" as="utils" from="utils/utils" />
|
||||
<div>
|
||||
<myComp customProp="{utils.doSomething()}">myComp is just a regular tag</myComp>
|
||||
</div>
|
Loading…
Reference in New Issue