loading...

The EmberJS of the future... today!

nullvoxpopuli profile image NullVoxPopuli ・5 min read

Ember has some exciting features that take it from a "dated" framework that some may be more familiar with to an exciting, ergonomic, and fully featured frontend toolset for ultimate productivity.
If you've previously brushed off Ember as something not worth trying, check this post where I will demonstrate some of my personal favorite features that I'm using right now on emberclear.io.

NOTE: Some of these are somewhat bleeding edge, and not yet released officially. Each feature has a vigorous Q.A. process, and getting through all the backwards-compatibility scenarios and upgrade paths takes some time. So, the official guides will not have some of these features mentioned. The breakdown of what is production-ready / still in experimental phases is at the bottom of this post.

To stay as up to date as possible, please join the Ember Community Discord

Async Lifecycle Hooks

Ember route demonstrating server-side rendering gates as well as [decorators](http://ember-decorators.github.io/ember-decorators/latest/), and async-aware lifecycle hooks

Here is a route-handler - demonstrating async lifecycle hooks that are disabled in a server-side rendering context via a decorator. One may want to do this because an app may interact with localStorage or indexeddb, which don't exist in a server-side context.

  • beforeModel is a guard for access to the route. In emberclear.io, in order to chat, you must have your "account" set up.
  • model is what fetches the data for the route. The data api supports graph-data – In the findAll invocation, I specify that for each message, I also want the sender. This helps reduce the number of requests to the backend.

Syntax for Components

Template for the login route demonstrating component invocation using Angle Brackets

Following in the footsteps of angular, react, and vue, Ember also has <AngleBracketInvocation /> of components, which allows your code to feel more natural and more readable – especially in comparison with the older (and sometimes hated) Handlebars syntax, where a template would be loaded up with {{ ... }} everywhere.

Now, the {{ ... }} are only used for non-HTML values, or in other words, dynamic / interpolated values.

  • {{input ... }} is a helper which abstracts away some <input configuration as well as sets up 2-way data-binding.
  • {{t ... }} is a helper which looks up an internationalization / i18n key for dynamic translations.
  • @title is a notation that tells the component that the variable is intended for use as an argument to the component, rather than an HTML attribute to tag. For example, you can, in the FocusCard template, specify ...attributes and all HTML attributes specified on the <FocusCard ... /> invocation would pass through to the ...attributes usage. This is a big advantage over this.props in react, in my opinion. Being explicit with intend by default is so undervalued in javascript.
  • lastly, {{action ...}} dictates what the button will do when clicked (the bound dom event can be customized, but is not shown here)

Testing

Testing comes for free out of the box with ember

Ember applications come out of the box with an async-aware testing framework that uses real browsers. No jsdom or fake browsers to cause worry about weird compatibility issues between your tests and reality. The tests ARE reality.

By default, Ember ships with QUnit, but mocha and chai are also widely supported as an alternative if you have your heart set on a particular set of testing tools.

Dependency Injection is a Must

Example dependency injection service consumption within a component

In my opinion, a dependency injection container makes all the difference in the completeness of a framework. By default, Ember comes with dependency injection. No need to wire up all your dependencies. No need to import everything. No need to worry about how many instances of a class you have, since services singletons.

The Ember dependency injection container boosts productivity by helping manage application-level state without any glue code whatsoever.

Keyboard Accessibility

Declarative Keyboard shortcuts

Want to add keyboard accessibility to your app? The Ember addon ember-keyboard makes it easy by providing a set of utilities that allows you to do common keyboard-accessible tasks like toggle modals.

The component in the example screenshot is powered by this template-less component: KeyboardPress.

Summary

At the time of writing this, some of the features are available for testing and experimental use by early adopters.


But, you can experiment with the following today:

These are production ready in any app today:

Even though each of these features may not yet officially be supported, there are still a good number of people trying things out and using these addons and features in production. So, if you're willing to spend some of the extra time to have the bleeding edge, it's worth it ;)

Note: If you want to look even more into the future: Ember Octane


A little about me – on twitter, I'm @NullVoxPopuli, and I love programming and the abstractions that people are coming up with to make development more productive and more fun. I have 2.5 years of professional experience with react, and 4 years of casual / hobby experience with Ember. I like them both. And I prefer to use each for specific purposes. I think Ember fits more of the "fully-featured app" purpose than react does – though, technically, react and its supporting ecosystem can solve all the same problems Ember does. With Ember, it's really nice to not have to figure out all the glue code between all the libraries like in the react ecosystem. "Productivity through Constraint" is my motto when it comes to frameworks.

Discussion

pic
Editor guide
Collapse
gaurav0 profile image
Gaurav Munjal

I like "Productivity through Constraint" much better than "Convention over configuration".

Collapse
xori profile image
Evan Verworn

Yuck.

(EDIT)
Decorators are never the saving grace of any language, and any framework that relies heavily on them is misusing the base language, or making up for the language. In this case, the former.

{{input is a bad fix for prop binding and event handling. {{t is a bad fix for i18n, they could have used template string functions so that it worked in javascript too, not just components (imagine i18n`Hello World` working everywhere, not just component templates). And @ prefixed attributes I really don't think should be a thing. Do the spec approved thing and ensure you're including a - in your props if you're having conflicts and you'll never smoosh anything again.

DI is just a more opaque import system, where I now have to debug the black box, rather than my own code.

And Keyboard Accessibility hookup via XML just reminds me of dated desktop app layout systems and ColdFusion

I dunno, agree to disagree.

Collapse
nullvoxpopuli profile image
NullVoxPopuli Author

Decorators are never the saving grace of any language, and any framework that relies heavily on them is misusing the base language, or making up for the language.

Can you expand on this? or, why do you think this? I think it's a good way to add behavior. Java, however, is historically known for abusing annotations/decorators.


Have you seen this thread? reddit.com/r/javascript/comments/9... I see from your github that you use Vue, so, I don't know how much of the comparison of jsx vs ember-templates translates..

{{input is a bad fix for prop binding and event handling.

can you expand on this?

they could have used template string functions so that it worked in javascript too,

there is actually a reason for not using javascript for the templates: youtube.com/watch?v=nXCSloXZ-wc (it's a 30 minute video, so.. I guess only watch if you're really curious.

Do the spec approved thing and ensure you're including a - in your props if you're having conflicts and you'll never smoosh anything again.

but class, style, tabindex, checked, value, id, href, etc are all non-hyphenated native html attributes. So, the differentiation is nice, I think :)

DI is just a more opaque import system

you can't really manage class instances with just import.

I now have to debug the black box, rather than my own code.

Why use anything other than assembly then? every tool is an abstraction, and it is OK to abstract upon other abstractions. Documentation and understanding is key. :)

And Keyboard Accessibility hookup via XML just reminds me of dated desktop app layout systems and ColdFusion

I'm personally fairly new to this, so -- what would you do?

Collapse
xori profile image
Evan Verworn

Decorators are never the saving grace of any language, and any framework that relies heavily on them is misusing the base language, or making up for the language.

Can you expand on this? or, why do you think this?

Javascript/Typescript are extremely dynamic and expressive languages. Why do you think you need them? What do they actually accomplish that's hasn't been implemented more cleanly by another framework without them? Admittedly Ember isn't as bad as Angular is with this.

Re: {{input

Why do you like this? How is this better than a directive that injects and listens to changes of the prop? Vue has v-model="variable" that can be put onto any component. How is a handlebar helper that is tied to a form input better? How is this not just considered bloat to you?

Re: {{t

Not having the templates be javascript is fine. The issue I was talking about is I can't use that {{t helper in a javascript method of mine. I'm sure Ember has an alternative for accessing the i18n strings in JS but that was a great opportunity that they missed out on.

Re: Smooshing

Sure

you can't really manage class instances with just import.

You really can. My prefered way if you want a singleton service export default new MyService(). Bam, shared instance, and there can only ever be one. Or attach it to your root App and $emit() or trigger() from any child component.

DI is a pattern, it's fine to use it, I have too, but there are better ways.

Re: Keyboard XML

On a second viewing it's not bad, I'm just not used to it. Polymer did a lot of this too, but I'd just listen to the keys. I don't know how the full ember event system works but in Vue <MyComponent @keydown.alt.115="modelVisible = !modelVisible" ... I like how expressive and customizable it is and there isn't anything new to learn, you just use the event system, like you always have.

Thread Thread
nullvoxpopuli profile image
NullVoxPopuli Author

Javascript/Typescript are extremely dynamic and expressive languages. Why do you think you need them?

How else would you denote something via shorthand as 'tracked' / cached so that it only updates when it needs to?

Why do you like this? How is this better than a directive that injects and listens to changes of the prop? Vue has v-model="variable" that can be put onto any component. How is a handlebar helper that is tied to a form input better? How is this not just considered bloat to you?

It's actually a shorthand, so, in Ember, you can totally just do:

<input value={{this.something}} oninput={{action this.updateSomething}} />

where then in your JS, you'd need:

updateSomething(e)  {
  const value = e.target.value;

  this.set('something', value);
  // note that set is going away in the future as ember moves away from it's pre-es6 object model (soon)
  // set is used as a bit of a trigger to update all the cached / dependent computed properties once before a re-render. 
  // once set is removed, this'll be wrapped behavior from the `@tracked` decorator
  // NOTE: for any React readers, this is like this.setState, but with super powers :)
}

So, that is equiv to:

{{input value=something onChange=(action (mut something))}}

so, no js involved. It's just a personal preference, imo. There are plenty of ember people who opt for as much of the native DOM behavior as possible.

side question: what all does v-model="variable do in Vue? it doesn't seem specific to anything and seems somewhat generic? Above, I use value= because an input expects a value.

Not having the templates be javascript is fine. The issue I was talking about is I can't use that {{t helper in a javascript method of mine. I'm sure Ember has an alternative for accessing the i18n strings in JS but that was a great opportunity that they missed out on.

Most helpers, like t, have two exports. 1. A default export (used by templates), and 2. A named export of a pure function that actually does the behavior. The named export is what can get imported into the js.
For t, specifically, it's exposed in additional ways as a service, so you can bind changes in your app to a change in locale but also as a direct import

You really can. My prefered way if you want a singleton service export default new MyService()

Personally, I think this is an accident of how bundlers evaluate scripts at build time.

DI is a pattern, it's fine to use it, I have too, but there are better ways.

to each their own. most things have purposes.

On a second viewing it's not bad, I'm just not used to it. Polymer did a lot of this too, but I'd just listen to the keys. I don't know how the full ember event system works but in Vue

So, my keyboard usage here is an API that I came up with (linked, is the template-less component that is in the screenshot) using lower-level keyboard event handling. I also didn't want my key events tied to a specific component (though, that is certainly an option, the lib I'm using is very flexible ).

I personally am not a fan of dynamically interpreted keys (even though there isn't a real good way around it when it comes to defining the shortcuts)), but I'd write your example (with my existing KeyboardPress component)

<KeyboardPress @key="alt+s" @onKeyDown={{action this.toggleModelVisibility}} />

I'd imagine though, if you wanted similar behavior from Vue, you could get close. You'd likely have to eval that string "modelVisible = !modelVisible", so.. that could be risky.

Collapse
nullvoxpopuli profile image
NullVoxPopuli Author

yuck? can you explain? I'm very curious.