Earlier , I mentioned that Ember's Helper
was introduced in version 1.13 . In my opinion, helpers are some of the most useful, but not often discussed, Ember functions.
In my lecture Idiomatic Ember at EmberConf 2016, I talked in detail about helpers, showing how they can be used to connect and significantly extend the functionality of Handlebars .
They can be used for declarative templating - a style of templating using composable actions, and giving templates more responsibility for presentation logic.
Together with a colleague Marten Schilstra , from DockYard, we created the addon ember-composable-helpers . This is a package of declarative helpers, and with its help you can reduce the number of sample code in your application. You can install it like this:
ember install ember-composable-helpers
One of my favorite helpers in the addon is pipe
(and its closure version, pipe-action
). It allows you to declare actions in a template declaratively, instead of creating multiple variations in a component:
{{perform-calculation add=(action "add") subtract=(action "subtract") multiply=(action "multiply") square=(action "square") }}
{{! perform-calculation/template.hbs }} <button {{action (pipe add square) 2 4}}>Should be 36</button> <button {{action (pipe subtract square) 4 2}}>Should be 4</button> <button {{action (pipe multiply square) 5 5}}>Should be 625</button>
The pipe helper was inspired by the Elixir pipe operator ( |>
), which allows you to write the following:
A(B(C(D(E), "F"), "G"), "H")
As a chain of converters:
E |> D() |> C("F") |> B("G") |> A("H")
Using the pipe operator, you can naturally express how E
passed to function D
, then the resulting value is passed to C
as the first argument, and so on. I think we can agree that the pipe version is much easier to read!
You might think that the helper is a primitive KeyWord
construct that uses Ember and HTMLBars to extend the expressions provided by Handlebars.
At the most basic level, Handlebars is responsible for compiling hbs
templates in HTML:
<p>{{myText}}</p> <!-- : --> <p>Hello world!</p>
Ember and HTMLBars builds on top of this by adding useful expressions like action
, mut
, get
, and hash
. In fact, all the familiar helpers that you use (from each
to the component
) are part of the HTMLBars !
Ember Helpers work at a higher level than HTMLBars helpers, and can be used to create new expressions in Ember, allowing you to effectively extend templating with your own behavior.
More experienced or conservative developers might find this dangerous: for all its usefulness to end users, it can also open up opportunities for abuse.
For example, in Elixir, macros can be used to extend a language, but not recommended for real use. This was codified in the excellent book by Chris McCord. Metaprogramming on Elixir - "Rule 1: Do not use macros."
Fortunately, helpers are not as powerful as Elixir macros, and play an important role in the Ember programming model. Unlike macros that allow you to reach AST, the use of Ember assistant to expand the presentation logic is acceptable as long as we do not abuse this , and this is a feature where experience comes into play. So use helpers wisely.
Some people may experience discomfort when using add-ons containing helpers, due to the misconception that they introduce too much logic into the templates, and prefer to keep them free from it.
As a best practice, we must refrain from complex logic in patterns, as well as using nested constructs like this:
{{#unless (or (and (gte value 0) (lt value 0.0001)) (and (lt value 0) (not allowNegativeResults)))}} ... {{/unless}}
Instead, use computed properties.
At the same time, keeping your templates 100% free from logic is very difficult - you most likely already use logical helpers like if/else
or unless
. You can easily overlook the fact that the amount of logic in the pattern is not strictly defined.
ember-composable-helpers
, in fact, does not significantly increase the amount of logic in templates, if used correctly, it encapsulates the presentation logic inside these helpers, and in many cases can help you eliminate redundant code in components or controllers.
For example, you could write something similar in your application:
import Ember from 'ember'; const { Component, computed: { filterBy, setDiff }, set } = Ember; export default Component.extend({ activeEmployees: filterBy('employees', 'isActive'), inactiveEmployees: setDiff('employees', 'activeEmployees') });
A fairly common practice is to have an “intermediary component” for use in other components. With the help of ember-composable-helpers
you can write such constructions directly in the template, where everything is absolutely clear:
<h2>Active Employees</h2> {{#each (filter-by "isActive" engineers) as |employee|}} {{employee.name}} is active! {{/each}} <h2>Inactive Employees</h2> {{#each (reject-by "isActive" engineers) as |employee|}} {{employee.name}} is inactive! {{/each}}
You can think of composable helpers as a kind of computed macro properties that you can use and create directly in the template. And since you can create sub-expressions in Ember, they can be a powerful construct for reducing template code in an application.
Given the above, remember, do not get too carried away with deep nesting!
Like any other programming tools, it is important to exercise common sense and use them wisely.
If you can do something, it does not mean that you should .
A well-written view layer means that templates should be declarative (everything is absolutely obvious), as far as possible, and not that we should avoid logic in general.
However, we are not in favor of moving all of our logic into a pattern — again, the amount of logic in a pattern is not strictly regulated.
If you want to see how the addon is used, Katherin Siracusa wrote an excellent article about how she uses ember-composable-helpers
in AlphaSights :
This pattern allows you to perform operations on data and in the future more auxiliary, short-term actions that constantly occur in our application. Using compiled helpers, we can do it quite simply, without much duplication and without worrying about unwanted side effects.
You can also participate in the discussion on our Slack channel #e-composable-helpers
.
As always, thank you for your attention!
Source: https://habr.com/ru/post/308326/
All Articles