diff --git a/packages/ember-glimmer/lib/environment.js b/packages/ember-glimmer/lib/environment.js index 1bfa3ed6bcb..3fa3e680911 100644 --- a/packages/ember-glimmer/lib/environment.js +++ b/packages/ember-glimmer/lib/environment.js @@ -6,11 +6,15 @@ import createIterable from './utils/iterable'; import { RootReference, ConditionalReference } from './utils/references'; import { default as concat } from './helpers/concat'; -import { default as inlineIf } from './helpers/inline-if'; +import { + inlineIf, + inlineUnless +} from './helpers/inline-if-unless'; const helpers = { concat, - if: inlineIf + if: inlineIf, + unless: inlineUnless }; const VIEW_KEYWORD = 'view'; // legacy ? 'view' : symbol('view'); diff --git a/packages/ember-glimmer/lib/helpers/inline-if-unless.js b/packages/ember-glimmer/lib/helpers/inline-if-unless.js new file mode 100644 index 00000000000..df1873ab967 --- /dev/null +++ b/packages/ember-glimmer/lib/helpers/inline-if-unless.js @@ -0,0 +1,68 @@ +/** +@module ember +@submodule ember-templates +*/ + +import { toBool as emberToBool } from './if-unless'; +import { assert } from 'ember-metal/debug'; + +/** + The inline `if` helper conditionally renders a single property or string. + This helper acts like a ternary operator. If the first property is truthy, + the second argument will be displayed, otherwise, the third argument will be + displayed + ```handlebars + {{if useLongGreeting "Hello" "Hi"}} Alex + ``` + You can use the `if` helper inside another helper as a subexpression. + ```handlebars + {{some-component height=(if isBig "100" "10")}} + ``` + @method if + @for Ember.Templates.helpers + @public +*/ +export function inlineIf(args) { + return resolveValue(args, true); +} + +/** + The inline `unless` helper conditionally renders a single property or string. + This helper acts like a ternary operator. If the first property is falsy, + the second argument will be displayed, otherwise, the third argument will be + displayed + ```handlebars + {{unless useLongGreeting "Hi" "Hello"}} Ben + ``` + You can use the `unless` helper inside another helper as a subexpression. + ```handlebars + {{some-component height=(unless isBig "10" "100")}} + ``` + @method unless + @for Ember.Templates.helpers + @public +*/ +export function inlineUnless(args) { + return resolveValue(args, false); +} + +function resolveValue(args, truthy) { + assert( + 'The inline form of the `if` and `unless` helpers expect two or ' + + 'three arguments, e.g. `{{if trialExpired \'Expired\' expiryDate}}` ', + args.length === 2 || args.length === 3 + ); + + let predicate = emberToBool(args[0]); + if (!truthy) { + predicate = !predicate; + } + + if (predicate) { + return args[1]; + } else { + //TODO: always return `args[2]` post glimmer2: https://github.com/emberjs/ember.js/pull/12920#discussion_r53213383 + let falsyArgument = args[2]; + return falsyArgument === undefined ? '' : falsyArgument; + } +} diff --git a/packages/ember-glimmer/lib/helpers/inline-if.js b/packages/ember-glimmer/lib/helpers/inline-if.js deleted file mode 100644 index 7040af19c46..00000000000 --- a/packages/ember-glimmer/lib/helpers/inline-if.js +++ /dev/null @@ -1,39 +0,0 @@ -/** -@module ember -@submodule ember-templates -*/ - -import { toBool as emberToBool } from './if-unless'; -import { assert } from 'ember-metal/debug'; - -/** - The inline `if` helper conditionally renders a single property or string. - This helper acts like a ternary operator. If the first property is truthy, - the second argument will be displayed, if not, the third argument will be - displayed - ```handlebars - {{if useLongGreeting "Hello" "Hi"}} Alex - ``` - You can use the `if` helper inside another helper as a subexpression. - ```handlebars - {{some-component height=(if isBig "100" "10")}} - ``` - @method if - @for Ember.Templates.helpers - @public -*/ -export default function inlineIf(args) { - assert( - 'The inline form of the `if` and `unless` helpers expect two or ' + - 'three arguments, e.g. `{{if trialExpired \'Expired\' expiryDate}}` ', - args.length === 2 || args.length === 3 - ); - - if (emberToBool(args[0])) { - return args[1]; - } else { - //TODO: always return `args[2]` post glimmer2: https://github.com/emberjs/ember.js/pull/12920#discussion_r53213383 - let falsyArgument = args[2]; - return falsyArgument === undefined ? '' : falsyArgument; - } -} diff --git a/packages/ember-glimmer/tests/integration/helpers/if-unless-test.js b/packages/ember-glimmer/tests/integration/helpers/if-unless-test.js index e6851f7844f..7901b77b906 100644 --- a/packages/ember-glimmer/tests/integration/helpers/if-unless-test.js +++ b/packages/ember-glimmer/tests/integration/helpers/if-unless-test.js @@ -1,6 +1,4 @@ import { moduleFor } from '../../utils/test-case'; -import { set } from 'ember-metal/property_set'; - import { TogglingHelperConditionalsTest } from '../../utils/shared-conditional-tests'; moduleFor('Helpers test: inline {{if}}', class extends TogglingHelperConditionalsTest { @@ -9,84 +7,128 @@ moduleFor('Helpers test: inline {{if}}', class extends TogglingHelperConditional return `{{if ${cond} ${truthy} ${falsy}}}`; } - ['@test it can omit the falsy argument']() { - this.render(`{{if cond1 'T1'}}{{if cond2 'T2'}}`, { cond1: true, cond2: false }); + ['@test it raises when there are more than three arguments']() { + expectAssertion(() => { + this.render(`{{if condition 'a' 'b' 'c'}}`, { condition: true }); + }, /The inline form of the `if` and `unless` helpers expect two or three arguments/); + } + + ['@test it raises when there are less than two arguments']() { + expectAssertion(() => { + this.render(`{{if condition}}`, { condition: true }); + }, /The inline form of the `if` and `unless` helpers expect two or three arguments/); + } + +}); + +moduleFor('@glimmer Helpers test: nested {{if}} helpers (returning truthy values)', class extends TogglingHelperConditionalsTest { + + templateFor({ cond, truthy, falsy }) { + return `{{if (if ${cond} ${cond} false) ${truthy} ${falsy}}}`; + } + +}); + +moduleFor('@glimmer Helpers test: nested {{if}} helpers (returning falsy values)', class extends TogglingHelperConditionalsTest { + + templateFor({ cond, truthy, falsy }) { + return `{{if (if ${cond} true ${cond}) ${truthy} ${falsy}}}`; + } + +}); + +moduleFor('@glimmer Helpers test: {{if}} used with another helper', class extends TogglingHelperConditionalsTest { + + wrapperFor(templates) { + return `{{concat ${templates.join(' ')}}}`; + } + + templateFor({ cond, truthy, falsy }) { + return `(if ${cond} ${truthy} ${falsy})`; + } - this.assertText('T1'); +}); - this.runTask(() => this.rerender()); +moduleFor('@glimmer Helpers test: {{if}} used in attribute position', class extends TogglingHelperConditionalsTest { - this.assertText('T1'); + wrapperFor(templates) { + return `
`; + } + + templateFor({ cond, truthy, falsy }) { + return `{{if ${cond} ${truthy} ${falsy}}}`; + } + + textValue() { + return this.$('div').attr('data-foo'); + } - this.runTask(() => set(this.context, 'cond1', false)); +}); - this.assertText(''); +moduleFor('Helpers test: inline {{if}} and {{unless}} without the inverse argument', class extends TogglingHelperConditionalsTest { - this.runTask(() => { - set(this.context, 'cond1', true); - set(this.context, 'cond2', true); - }); + templateFor({ cond, truthy, falsy }) { + return `{{if ${cond} ${truthy}}}{{unless ${cond} ${falsy}}}`; + } - this.assertText('T1T2'); +}); - this.runTask(() => { - set(this.context, 'cond1', true); - set(this.context, 'cond2', false); - }); +moduleFor('Helpers test: inline {{unless}}', class extends TogglingHelperConditionalsTest { - this.assertText('T1'); + templateFor({ cond, truthy, falsy }) { + return `{{unless ${cond} ${falsy} ${truthy}}}`; } ['@test it raises when there are more than three arguments']() { expectAssertion(() => { - this.render(`{{if condition 'a' 'b' 'c'}}`, { condition: true }); + this.render(`{{unless condition 'a' 'b' 'c'}}`, { condition: true }); }, /The inline form of the `if` and `unless` helpers expect two or three arguments/); } ['@test it raises when there are less than two arguments']() { expectAssertion(() => { - this.render(`{{if condition}}`, { condition: true }); + this.render(`{{unless condition}}`, { condition: true }); }, /The inline form of the `if` and `unless` helpers expect two or three arguments/); } }); -moduleFor('@glimmer Helpers test: nested {{if}} helpers (returning truthy values)', class extends TogglingHelperConditionalsTest { +moduleFor('@glimmer Helpers test: nested {{unless}} helpers (returning truthy values)', class extends TogglingHelperConditionalsTest { templateFor({ cond, truthy, falsy }) { - return `{{if (if ${cond} ${cond} false) ${truthy} ${falsy}}}`; + return `{{unless (unless ${cond} false ${cond}) ${falsy} ${truthy}}}`; } }); -moduleFor('@glimmer Helpers test: nested {{if}} helpers (returning falsy values)', class extends TogglingHelperConditionalsTest { +moduleFor('@glimmer Helpers test: nested {{unless}} helpers (returning falsy values)', class extends TogglingHelperConditionalsTest { templateFor({ cond, truthy, falsy }) { - return `{{if (if ${cond} true ${cond}) ${truthy} ${falsy}}}`; + return `{{unless (unless ${cond} ${cond} true) ${falsy} ${truthy}}}`; } }); -moduleFor('@glimmer Helpers test: {{if}} used with another helper', class extends TogglingHelperConditionalsTest { +moduleFor('@glimmer Helpers test: {{unless}} used with another helper', class extends TogglingHelperConditionalsTest { wrapperFor(templates) { return `{{concat ${templates.join(' ')}}}`; } templateFor({ cond, truthy, falsy }) { - return `(if ${cond} ${truthy} ${falsy})`; + return `(unless ${cond} ${falsy} ${truthy})`; } }); -moduleFor('@glimmer Helpers test: {{if}} used in attribute position', class extends TogglingHelperConditionalsTest { +moduleFor('@glimmer Helpers test: {{unless}} used in attribute position', class extends TogglingHelperConditionalsTest { wrapperFor(templates) { return `
`; } templateFor({ cond, truthy, falsy }) { - return `{{if ${cond} ${truthy} ${falsy}}}`; + return `{{unless ${cond} ${falsy} ${truthy}}}`; } textValue() {