wix-incubator / react-templates

Light weight templates for react
https://wix.github.io/react-templates
MIT License
2.82k stars 207 forks source link

html/es6 in attributes #209

Closed TimKraemer closed 7 years ago

TimKraemer commented 7 years ago

Hi, thanks for the great project!

I'm using ant-design for my project, they're using HTML/ES6 inside attributes in some of their components. For example this one:

<Modal footer={[ <Button onClick={this.handleCancel}>custom cancel</Button> ]}>
    <p>modal content...</p>
</Modal>

I wonder if there's a way to make this work with react-templates? Thanks!

nippur72 commented 7 years ago

I'm not sure because it's something I rarely use:

<Modal>
    <rt-template prop="footer">
        <Button onClick={this.handleCancel}>custom cancel</Button>
    </rt-template>
    <p>modal content...</p>
</Modal>

If you try it, can you please tell if it's actually working for your use case (with antd)?

TimKraemer commented 7 years ago

unfortunately your idea is not working for my case: Warning: Failed prop type: Invalid prop 'footer' supplied to 'Modal', expected a ReactNode.

nippur72 commented 7 years ago

I think the problem is in footer being a function that creates a ReactNode, rather than a ReactNode itself.

Would you please try this ugly hack (just to see if it works):

<Modal rt-props="{footer: f1.bind(this)()}">
    <rt-template prop="f">
        <Button onClick={this.handleCancel}>custom cancel</Button>
    </rt-template>
    <p>modal content...</p>
</Modal>

BTW, I remember I suggested a possible improvement long ago, but no discussion followed. See #103, #150 and #155.

TimKraemer commented 7 years ago

Thanks! That did the trick ;) Well it is rather ugly and I'm not sure if I would use this in bigger projects, but it will do for this one. Just for clarification: the "1" in f1.bind(this) is some kind of iterator?

nippur72 commented 7 years ago

@TimKraemer yes of course I wouldn't advise to use it in any project, it was just to check if it could work at least in theory. Which it is, so perhaps we can add this functionality easily in the future.

Regarding the "1": when you have <rt-template prop="f">, react-templates creates an inner function using "f" as a base name, but then it adds a number in order to prevent clashing with already existing names. The result is f1.

What I've done simply is creating a f1() function, and passing its return value as props.footer. You can check it in the generated JavaScript:

var templateRT = function () {
    function f1() {
        return React.createElement(Button, { 'onClick': this.handleCancel }, 'custom cancel');
    }
    return React.createElement(Modal, _.assign({}, { 'f': f1.bind(this) }, { footer: f1.bind(this)() }), React.createElement('p', {}, 'modal content...'));
};