-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
[RFC #338] Implement new template helpers #17177
Conversation
- [x] Implement `{{eq}}` helper - [ ] Implement `{{not}}` helper - [ ] Implement `{{and}}` helper - [ ] Implement `{{or}}` helper - [ ] Implement `{{gt}}` helper - [ ] Implement `{{gt3}}` helper - [ ] Implement `{{lt}}` helper - [ ] Implement `{{lte}}` helper
this.render(`{{gt left right}}`, { | ||
left: undefined, | ||
get right() { | ||
debugger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rwjblue Any guidance on how to define a getter or a CP to verify that its value is not eagerly pulled by the helper? Seems that right now the keys of this object are eagerly accessed by Object.assign
by the setup of the test itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of rendering gt directly render a component whose own template uses gt, then have that component have left and right CP’s that you can track when they are evaluated
9703584
to
c21356b
Compare
It has lazy evaluation of the second argument, so it doesn't even get read if the first argument is already undefined. For now without an option to coerce strings to numbers.
c21356b
to
4fecacb
Compare
@rwjblue Tests are failing because of missing documentation, however I've documented every helper, so I'm not sure what I'm missing. |
@public | ||
@method and | ||
@for Ember.Templates.helpers | ||
@since 2.7.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems wrong ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Master is 2.7, am I wrong? 2.6 maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you mean 3.7?
Off the top of my head, I’d say no.... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking really good here, only major thing that I see is that it needs feature flagging...
@@ -64,12 +73,21 @@ function makeOptions(moduleName: string, namespace?: string): LookupOptions { | |||
const BUILTINS_HELPERS = { | |||
if: inlineIf, | |||
action, | |||
and, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding to the BUILTINS_HELPERS
array needs to be guarded by feature flags
I added a feature flag. It's enabled by default. |
let last: any = true; | ||
for (let i = 0; i < references.length; i++) { | ||
last = references[i].value(); | ||
if (!last) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chancancode - Should we consider []
as falsey here? In general, in template land I think we do right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I think we do.
ember.js/packages/@ember/-internals/glimmer/lib/utils/to-bool.ts
Lines 4 to 10 in 1b7e613
export default function toBool(predicate: Opaque): boolean { | |
if (isArray(predicate)) { | |
return (predicate as { length: number }).length !== 0; | |
} else { | |
return !!predicate; | |
} | |
} |
I bigger question is should we support proxies, I completely forgot about that. I think that needed to be discussed and clarified in the RFC 🤧
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is surprising. I was expecting and/or helpers to behave just like && / II. Why this deviation from standard JS behaviour?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{{#each @posts as |post|}}
...
{{else}}
No posts!
{{/each}}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{{#each}}
is designed to display lists, and seems normal that it has special behavior for empty lists, but and
and or
are not for lists, so I don't see why the behavior of {{each}}
should influence them and make them behave different than &&
and ||
On top of that, this is not how ember-truth-helpers behave. I'm not saying that we can't deviate from what e-t-h if there is a good reason, but it would be nice not to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well it really isn't about each
, {{#if someEmptyArray}}{{else}}{{/if}}
will render the falsey branch. I think it is very confusing to have if
behave differently than eq
/not
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works the same way for...
{{#if @posts as |post|}}
...
{{else}}
No posts!
{{/if}}
...and with
, let
etc. I think the bottom line is it would be pretty surprising if {{else}}
doesn't work consistently in the control flow things in the "language".
So now what if you refactor from the first example into...
{{#each (or @posts @reblogs) as |post|}}
...
{{else}}
No posts!
{{/each}}
...what should this do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is probably important for the "language" to have one boolean semantics, and for better or for worse empty arrays are falsey everywhere else.
return false; | ||
} | ||
let right = references[1].value(); | ||
if (right === undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this satisfy a specific edge case? I would have imagined that the following would have been enough:
return left > right;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried, but typescript doesn't like comparing things with null or undefined.
return false; | ||
} | ||
if (right === null) { | ||
return left >= 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems odd to me, why do we need to extra logic (vs just using the final return left >= right
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reason. Typescript doesn't ket me compare things with undefined or null. How can we silence that?
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Co-Authored-By: cibernox <miguel.camba@gmail.com>
Closing this as it would have to be reworked |
For reference, the original RFC has been superseded. See emberjs/rfcs#388 (comment) for full details. |
{{eq}}
helper{{not-eq}}
helper{{not}}
helper{{and}}
helper{{or}}
helper{{gt}}
helper{{gte}}
helper{{lt}}
helper{{lte}}
helperOpen questions:
{{gt}}
,{{gte}}
,{{lt}}
and{{lte}}
fromember-truth-helpers
take a named argumentforceNumber=true
to transform input arguments to numbers. Do we want to replicate those too?