Angular: JSX like templates in angular

Created on 4 Nov 2015  ·  65Comments  ·  Source: angular/angular

It would be cool to support JSX like templates in angular 2. JSX can hold all required information required to generate the DOM at run time. Following are some benefits come with JSX to angular:

  1. Type safety to catch errors at compile time
  2. Better run time performance. No need to parse template string at run time. DOM info and may be AST can be serialized at compile time
  3. Typescript already supports JSX and understands the syntax
  4. More intelligence and easier refactoring support for IDEs when dealing with templates
  5. Possibility to share component templates with React

Most helpful comment

See below for typed HTML that's _actually HTML_, coming soon to an Angular near you

All 65 comments

Agree that this might be nice for folks who like JSX, but it will have to be an external contributor who works on it rather than the core team as most of this is opinion rather than benefits. My thoughts:

1 & 4: can work fine with Angular 2 templates. Already demonstrated start of this in WebStorm. Coming in other IDEs soon.

2: Angular likely performs better than JSX as compilation happens as a build step (landing soon).

5: Yes, this could be nice and could work well for folks using Flux style data flow. There will likely soon be more components in native Angular 2, however, so not so sure of the actual benefit to the ecosystem.

In general, we like the HTML-spec compliant template as all tools work with them and designers have easier time interacting with them.

@bradlygreen @malekpour
I would argue that you can do this, to some degree today, using TypeScript to seamlessly bridge the two technologies. In the end it's just JavaScript...

I have an example here where I integrate a Flux/React based component into an Angular 2.0 component:
http://www.syntaxsuccess.com/angular-2-samples/#/demo/react

Some more details here too:
http://www.syntaxsuccess.com/viewarticle/integrating-react-with-angular-2.0

@bradlygreen I agree on almost all of your points. I didn't mean to change anything in the current Angular 2 design or removing the run time template parsing which I am a big fan of. To clarify what I mean please compare these two components:

@Component({
  selector: 'key-up',
  template: `
    <div>    
      <h4>Give me some keys!</h4>
      <div><input (keyup)="onKey($event)"><div>
      <div>{{values}}</div>
    </div>
  `
})
class TestComponent {
  values = '';
  onKey(event) {
  }
}
@Component({
  selector: 'key-up',
  templateJsx: (
    <div>
      <h4>Give me some keys!</h4>
      <div><input (keyup)={ onKey($event) }><div>
      <div>{{values}}</div>
    </div>
  )
})
class TestComponent {
  values = '';
  onKey(event) {
  }
}

While onKey in the first template is double quoted string inside another multi line string, in the JSX template it is an identifier and it makes more sense.

Also compiler would generate something similar to this which I strongly doubt if any parser can perform better than this at run time. create will have 3 parameters, tag/directive name, attributes and children.

AngularJsx.create("div", null, 
  AngularJsx.create("h4", null, "Give me some keys!"), 
  AngularJsx.create("div", null, AngularJsx.create("input", {keyup:  onKey($event) })), 
  AngularJsx.create("div", null, {values})
)

I am not aware of the plan you mentioned in your comment (number 2), but even better if angular will support compiled templates. So the JSX compiler will output the same.

And don't forget that this will be a great attraction for react community members to contribute or migrate.

And this is funny, I randomly copied the above component snippet from https://angular.io/docs/ts/latest/guide/user-input.html page. Only when I tried to compile the JSX template, I realized that the div element in the line <div><input (keyup)="onKey($event)"><div> is not closed.
https://github.com/angular/angular.io/blob/master/public/docs/_examples/user-input/ts/src/app/app.ts#L36
This mistake is repeated in that page at least 4 times by the documentation team. These kind of mistakes are very common and type safe template support helps a lot.

@malekpour you may want to have a look at the design documentation for the template compiler - it outputs code not unlike JSX : https://docs.google.com/document/d/11r8IuS4xDyhVSEBp7fDYo7aiLYsLEXKs4lPd36umUGM/edit

That said, you could certainly implement this as a 3rd party render plugin - in fact, we have a react-native renderer that might get you started: https://github.com/angular/react-native-renderer/

@thelgevold super cool demos by the way - your components page is great!

Thanks @robwormald I appreciate that!

I never liked the idea of XML in my JavaScript. The only benefit I can see is static analysis of template HTML strings. It's possible to write static analyzers that lint those HTML strings though. You can either mark the template strings with a tag function like

html`<div>...</div>`

or somehow use TypeScript type system to hint a string is HTML...

I like templateJsx.

+1 templateJsx
@mohsen1 "I never liked the idea of XML in my JavaScript":

  • Don’t put XML to JavaScript, keep it in separate file. However, have it TYPED including all Atom or Visual Studio IDE benefits: find all symbol reference, rename symbol, syntax highlighting, auto indent, etc.
  • When CSS designer accidentally corrupts your JavaScript fragment in HTML template, Typescript compiler will notify you.
  • etc.

This issue is solving in Typescript project, see @MikeRyan52 comment in #7100.

When using TypeScript the templates are strongly typed (TSX) this helps to prevent errors and to provide a better development experience I :+1: for TSX template support!


:smiley:

Unlike politicians I'm not afraid to say I've changed my mind about JSX!

Using TypeScript and JSX (TSX) has been a pleasure in my recent react project. Typed HTML is really great!

See below for typed HTML that's _actually HTML_, coming soon to an Angular near you

this is great. Will this also be possible in linked html templates via templateurl?

I don't understand the closing of the other issue. This is more a typing thing than a jsx one?

@robwormald It's great than jsx.

TSX and in general JSX benefits are not limited to editor intellisense and syntax coloring.

I personally like the way JSX naturally eliminates run-time parse and AST generation, comparing to current Angular 2 template parsing or even future build time template compilation.

Please do not forget that jsx !== React, it is just invented by React team. I think Angular team can support this as an incentive for React community to migrate. Here is proposed JSX specification https://facebook.github.io/jsx/

I like where TypeScript extensibility is going to and I can see some day typescript drops all of JSX stuff and move it to an extension. What I saw on the issue referenced above is better than JSX actually. JSX has its own pitfalls like class keyword conflict and so on. I'm sure what typescript team is working on is going to be better and we shouldn't really ask Angular team to support JSX.

@mohsen1 I agree that TypeScript Extensibility is so cool, but why

we shouldn't really ask Angular team to support JSX

@malekpour because it can be solved in programming language level?

@mohsen1 You are right that it can be solved in programming language level. In fact it is already solved by TSX and supported by TypeScript for a while now.

Regardless of how TypeScript Extensibility can help in development time, value type of template will remain string which needs to be parsed and analysed at run-time, but value of templateJsx will be ready to use object or function.

value type of template will remain string which needs to be parsed and analysed at run-time

This is not true. There is already a PR open that will compile templates as part of the build step instead of at runtime https://github.com/angular/angular/pull/7155

This is not true. There is already a PR...

@MikeRyan52 So, simply that is true unless you post-compile templates in an additional build step.

I don't exactly know how TypeScript extensibility will work out with Angular but I hope it's going to be better than TSX. Two issues I have in TSX that I think the new proposal will fix:

  • No more className instead of class
  • Allowing <Type> syntax within the template. Currently in TSX it's impossible to do something like return (<div>{(<Foo>bar).baz}</div>)

In TSX you can use (bar as Foo).baz instead of (<Foo>bar).baz.

This 10 line jsbin shows how easily a TSX template works
http://jsbin.com/yodiwid/edit?js,output

Yes, I'm aware of that. Thank you for the gist though!

Maybe I missed something - in this case sorry for the following…

From my point of view, angular runtime have to analyze both template-string and templateUrl-file in order to composite Component tree. "Analyze" means to convert string to any JavaScript representation (object tree or something similar).

TSX (parsed into JavaScript object tree by TypeScript, in compile time) could be another representation of Angular template. Maybe I am wrong but solving Microsoft/TypeScript#6508 issue must be much more difficult than using JavaScript object tree as another Angular template representation. Besides,
Microsoft/TypeScript#6508 is not an ideal solution, it solves only some of the issues (refactoring, intellisense etc.). I does not solve another huge benefit of JSX/TSX approach: its functional nature:

  • “Template as function” opens other templating possibilities
  • it is not bound to Typescript

I think that “Template as function” is a bit different from "JSX like templates in angular" so I created new #7339 issue.

Angular 2 orientation on Typescript (together with "Angular - one framework" concept) was one of the main reasons I left React to Angular. The only thing I am missing now are strictly typed functional templates.

Thanks @malekpour for many excellent arguments supporting TSX/JSX/functional templates idea. I believe Angular team will listen to them.

@bradlygreen, where can I find out more about:
"2: Angular likely performs better than JSX as compilation happens as a build step (landing soon)."

What will the compiled templates look like?

My interest is related to code-coverage on E2E tests when conditional logic exists in templates.
With Angular 1.x string based templates there was no way to determine if all code paths had been exercised, unlike compiled JSX.

The end goal is to be able to run a suite of E2E tests with 100% coverage and remove unused styles.
See https://github.com/addyosmani/grunt-uncss

As I finished my first mid size ng2 app, just realized that Jsx can also eliminate the requirement of providing directives and selector.

@malekpour see #7339: "JSX... it's not something the (Angular) team is interested in supporting".

Angular likely performs better than JSX as compilation happens as a build step

As if JSX weren't a build step too...

@cmelion Well, we'll just have to see about that. :) First half of this will land in a few weeks. We'll make a big deal about it when it does.

See also http://angularjs.blogspot.com/2016/03/why-angular-renders-components-with.html for why we like templates over JSX-style stuff.

+1:+1: templateJsx

Coming from React, and looking into ng2 I must say that the JSX being able to use native JS for loops etc is a killer feature. Also getting a compile error is critical. For some reason running the tutorial and making a typo in a template doesn't throw any exception. Not at runtime nor compile time. You are just left with HTML rendering out some code??

Sitting with a template language writing *ngFor="let hero of heroes" over heroes.map(hero => ...); is just not as intuitive. Having JS/TS at your disposal is superior.

The template is better in the sense you are actually writing HTML. I really like that, as I do not have to learn className vs class. Here the template shines.

@robwormald: Any updates on the fancy editor support ? I am using VScode and just tried out Atom and none of them seems to have any good template experience with rich html + ts auto completion. Atom does make a nice highlighting of HTML tamplate string. Also will this work for separate HTML files?

I really like typescript and rx. Having a webcomponent architecture is also a plus. But I do not want to use the ng-for etc like things that are currently in the template. JSX is much better as it uses just javascript.

So for me, for now not having jsx is a show stopper. I am sure many people feel the same way.

[UPDATE]
I think I was wrong. With ng compiler you basically get the same kind of functionality.
I still do not like the ng-for directives, but I understand the reasoning now after reading the statement from robwormald.

Another React and JSX lover chiming in: everything about NG2 is fine until there's the "good old" HTML templates coming in with the custom attributes for onClick, onBlur and other ev. handlers, basic map functions, etc.

I'd like to ask - WHY? Why NG2 templates must contain some obscure HTML-like attributes that accepts a string to run a loop? Why the the ev. handlers must have some kind of prefix? Why it must NOT be consistent to the usual HTML that front-end devs work with?

Look at JSX. It's very simple. It has very clean, approachable and well-defined syntax. Scopes are very clearly defined by the correct usage of curly braces. It's plain JS. It doesn't try to reinvent the wheel like NG2 templates.

And speaking of the ease for designers to modify the rendered content (HTML vs JSX), from my experience, if a designer is capable, it's very easy for him to explain how JSX works instead of all the weird *ngIf, etc. HTML attrs.

For me, personally, JSX is the clear winner here. Of course, that's debatable and it's a matter of habit in general, but at least both sides are allowed to speak out and compare things :)

@Inlesco just have to note, that I find it unlikely that a designer will have a better time modifying an JSX template with JS involved in it, rather than an HTML that has *ngFor in it.

@gioragutt a designer finds it difficult to modify xml templates for android apps. That's not a valid reason to use html for building android apps

@m3l7 consider this:

Hey matt, can you please help me align the textbox in trade-form.component.html?

versus

Hey matt, can you please help me align the textbox in TradeFormComponent.tsx? Yeah, just look for the render function, and don't forget that you have to use className instead of class

And so on. Of course this is opinionated, I'm not saying one approach is absolutely better than the other. Unlike what I always hear from React developers: Ha we do data.map(...) so it's so much better than *ngFor. This means nothing. You're gonna get shit done either way. Only reason today to choose React over Angular or the other way around - is people's opinions. If you/your ceo/your cto/whatever love React more than you do Angular, you're gonna do React. Same for vice versa.

This also implies for all other frameworks/libraries out there. All this Vue/Aurelia or the other dozens of frameworks. Who needs that shit. The community should pick a couple of good ones (aka React / Angular) and improve the living hell out of them. Publishing all those dozens of libraries ain't gonna get any progress.

@gioragutt it's not an opinion. Type checking in templates is a huge step forward.

For the second point: correct, that's why many people take angular and try to improve it (i.e. by adding jsx/tsx)

@m3l7 Yes, type checking is important, and is possible in Angular templates with typescript language service. On the other hand, having unlimited expressiveness in templates hinders tooling support and has other implications, such as how much energy one potentially needs to spend understanding a template file. On that one can have opinion whether it is worth the power and consistency of having same language.

@m3l7 As @egaga said, You can have Type checking and linting and validation in general in html templates. In fact, this comes built in with angular today. I think that it's might worth mentioning that comparing *ngFor to items.map(item => ...) might not be that worth doing, likewise for *ngIf, since there are stuff behind it that aren't just foring over a collection, like map.

Also, take for example: pipes. How easy it is to use pipes, how expressive it is and how well it integrates into templates. As someone who works with linux and bash daily, the concept of pipes is so clear and intuitive, let alone composable. It takes a bit more in pure JS to do that.

See - https://github.com/angular/vscode-ng-language-service

Our position on this has not changed, nor is it likely to. You are, of course, welcome to integrate React or any of the JSX-based libraries into Angular, as it's trivial to do yourself. We will not be supporting this in Angular core.

Then u just open the market for Vue

@robwormald We need a way to have strong type html integrated with typescript, finding references and refactoring features based on this references. The same for selectors of components, We should not use a selector name string based, instead use the class name of the component, so we can find references based on the class instead the selector and do quick refactoring instead finding and replacing. C'mon guys angular can do it better on this, please take a decision soon before it is too late.

@bradlygreen Please make it happen a lot of benefits will be for angular if this happens

Are there any third party libs that can accomplish this as of right now?

@John0x It would be counter productive to use angular without its native features / choices :rose:

please make this happen :)

The fact that people are actually using the className argument to dismiss the benefits of JSX is laughable. In my opinion, this issue is Angular's largest failing as a front-end framework in terms of the developer experience, and this complacence is only going to lose Angular more and more ground to the other major frameworks.

@KamiShikkaku ... if you like JSX so much, you may be interested in the NG-VDOM, introduced by @trotyl ... see:
https://blog.angularindepth.com/introducing-to-ng-vdom-a-new-way-to-write-angular-application-60a3be805e59

I don't really get why Angular devs are against the variety of templating languages available on the market. The more we have, the better, especially if it's something thought-out, powerful and TS-compatible like JSX.

If JSX happens and, presumably, hits the deck big time, some will continue to use NgJs' HTML templating, some will jump ship and migrate their apps to JSX. Where's the problem here? Definitely nowhere, the way I see it.

@Inlesco ... not sure that it's true.

The more we have, the better ...

@Inlesco probably JSX is the signature of React whereas Html is one of the signatures of Angular.

I have a component with dynamic dropdown menu which I want to configure from within the child components (context menu). This is 5 mins work with React, what about Angular?

@mitevdev ... a component with dynamic dropdown usually has an input with its configuration. Not sure what a child component (context menu) is and why it's a child of the dropdown component at all.

There is a component A (parent) which is a wrapper for component B (child). A has a toolbar wich can be customized by component B. There are many different implementations of B but A stays always the same. The contents of that toolbar may vary with the implementation of B.

Of course, I can "predict" all possible combinations and use *ngIf or *ngSwitch but this is not so elegant as if component B could just sent the contents (elements) configured as views and callback handlers as well (which is exactly what React supports).

@mitevdev I think <ng-content> / slots should work for your case, it acts like props.children in React

@khaledosman good point, looking for <ng-content> I've found <ng-container> in relation to *ngTemplateOutlet which seems to be solution for my case.

The idea behind is to define the toolbar's elements within child component B:

...
<ng-template #element1>...</ng-template>
...

Component A fetches the IDs of that elements and use to render the elements defined in B.

<ng-container *ngTemplateOutlet="element1"></ng-container>

The only I need to test is if the elements IDs are available on global scope without the need to disable the default component encapsulation.

UPDATE: It works ....!

Not that I'm against people asking for help, but @mitevdev's problem is barely even tangentially related to the issue of support for JSX in Angular. Would be nice to stay on topic.

@John0x "Are there any third party libs that can accomplish this as of right now?"

My google-fu has turned up this currently experimental library: ng-vdom.

I've not yet tested it, but it claims to provide support for React style render() methods with JSX inside Angular

https://blog.angularindepth.com/introducing-to-ng-vdom-a-new-way-to-write-angular-application-60a3be805e59

https://github.com/trotyl/ng-vdom

The best solution to this problem is to use React.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings