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

[RFC #338] Implement new template helpers #17177

Closed
wants to merge 21 commits into from

Conversation

cibernox
Copy link
Contributor

@cibernox cibernox commented Nov 2, 2018

  • Implement {{eq}} helper
  • Implement {{not-eq}} helper
  • Implement {{not}} helper
  • Implement {{and}} helper
  • Implement {{or}} helper
  • Implement {{gt}} helper
  • Implement {{gte}} helper
  • Implement {{lt}} helper
  • Implement {{lte}} helper

Open questions:

  • The {{gt}}, {{gte}}, {{lt}} and {{lte}} from ember-truth-helpers take a named argument forceNumber=true to transform input arguments to numbers. Do we want to replicate those too?

- [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
@cibernox cibernox changed the title [RFC #338] Implement new template helpers [WIP][RFC #338] Implement new template helpers Nov 2, 2018
this.render(`{{gt left right}}`, {
left: undefined,
get right() {
debugger;
Copy link
Contributor Author

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.

Copy link
Member

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

@cibernox cibernox force-pushed the rfc-338/new-template-helpers branch 3 times, most recently from 9703584 to c21356b Compare November 4, 2018 10:48
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.
@cibernox cibernox force-pushed the rfc-338/new-template-helpers branch from c21356b to 4fecacb Compare November 4, 2018 10:50
@cibernox cibernox changed the title [WIP][RFC #338] Implement new template helpers [RFC #338] Implement new template helpers Nov 4, 2018
@cibernox
Copy link
Contributor Author

cibernox commented Nov 4, 2018

@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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems wrong ;)

Copy link
Contributor Author

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?

Copy link
Contributor

@locks locks Nov 6, 2018

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?

@rwjblue
Copy link
Member

rwjblue commented Nov 6, 2018

Do we want to replicate those too?

Off the top of my head, I’d say no....

Copy link
Member

@rwjblue rwjblue left a 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,
Copy link
Member

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

@cibernox
Copy link
Contributor Author

cibernox commented Nov 6, 2018

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) {
Copy link
Member

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?

Copy link
Member

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.

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 🤧

Copy link
Contributor Author

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?

Copy link
Member

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}}

Copy link
Contributor Author

@cibernox cibernox Nov 6, 2018

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.

Copy link
Member

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.

Copy link
Member

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?

Copy link
Member

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) {
Copy link
Member

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;

Copy link
Contributor Author

@cibernox cibernox Nov 6, 2018

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;
Copy link
Member

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)?

Copy link
Contributor Author

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?

locks and others added 7 commits November 6, 2018 14:13
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>
@cibernox
Copy link
Contributor Author

Closing this as it would have to be reworked

@locks
Copy link
Contributor

locks commented Jan 15, 2020

For reference, the original RFC has been superseded. See emberjs/rfcs#388 (comment) for full details.

@locks locks closed this Jan 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants