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

idea: JSX to Turbine #75

Open
trusktr opened this issue Jul 18, 2018 · 3 comments · May be fixed by #76
Open

idea: JSX to Turbine #75

trusktr opened this issue Jul 18, 2018 · 3 comments · May be fixed by #76
Assignees

Comments

@trusktr
Copy link

trusktr commented Jul 18, 2018

It'd be neat if we could write JSX in the Turbine views. It'd require a custom Turbine transform, as the output from today's JSX transformers output to a format designed for VDom.

Check out Surplus. It has it's own JSX transpiler, but the output is completely Surplus-specific.

Maybe Turbine could get something like this eventually.

@paldepind
Copy link
Member

paldepind commented Jul 19, 2018

Hello @trusktr. Yes, this is something that we definitely want to do and we've considered a few ways to make it possible. After the recently merged #72 it should be fairly easy to implement.

It'd require a custom Turbine transform, as the output from today's JSX transformers output to a format designed for VDom.

I think we could use the JSX transformation from Babel/TypeScript. Turbine views looks a lot like normal virtual DOM hyperscript so I think it would work.

The biggest problem is that in Turbine we sometimes want to invoke methods on components in the view. Here is an example adapted from here in the zip-codes example.

const view = ({ status }) => [
  span("Please type a valid US zip code: "),
  input({ placeholder: "Zip code" }).output({ zipCode: "inputValue" })
];

The method call is on line 3. The problem is that doing that in JSX is fairly cumbersome. It would end up looking like this:

const view = ({ status }) => <div>
  <span>Please type a valid US zip code:</span>
  {<input placeholder="Zip code"/>.output({ zipCode: "inputValue" })}
</div>

To me, that looks a bit weird and cumbersome. What do you think @trusktr? Is the above not to bad or should we find some workaround?

@paldepind
Copy link
Member

Code like this:

<MyComponent foo="bar" output={{ zipCode: "inputValue" }} />

is transformed something like the following:

h(MyComponent, { foo: "bar", output: { zipCode: "inputValue" }}, null);

The function/method that is most often invoked on components is the output method. @limemloh had the idea that we could add special support for an output attribute in the function that the JSX is compiled into. So the h in the code above would be implemented roughly as this:

function h(component, attributes, children) {
  const result = component(attributes, children);
  if ("output" in attributes) {
    return result.output(attributes.output);
  } else {
    return result;
  }
}

This has the benefits that one doesn't have to call the output method with the very clunky syntax. The downside is that it still only works for the output method. Calling map, chain, etc. on a component is still cumbersome.

@Jomik Jomik self-assigned this Jul 20, 2018
@Jomik Jomik linked a pull request Jul 20, 2018 that will close this issue
@paldepind
Copy link
Member

Work on this is being done in #76.

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

Successfully merging a pull request may close this issue.

3 participants