Skip to content

Commit

Permalink
Merge pull request #9718 from marcioj/mj-inline-if
Browse files Browse the repository at this point in the history
[FEATURE] if helper inline form
  • Loading branch information
mmun committed Nov 26, 2014
2 parents ed343f9 + 31bd85c commit 436dae0
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 5 deletions.
8 changes: 8 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,11 @@ for a detailed explanation.

Enables HTMLBars compiler to interpret `<x-foo></x-foo>` as a component
invocation (instead of a standard HTML5 style element).

* `ember-htmlbars-inline-if-helper`

Enables the use of the if helper in inline form. The truthy
and falsy values are passed as params, instead of using the block form.

Added in [#9718](https://github.com/emberjs/ember.js/pull/9718).

3 changes: 2 additions & 1 deletion features.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"ember-testing-pause-test": true,
"ember-htmlbars": null,
"ember-htmlbars-block-params": null,
"ember-htmlbars-component-generation": null
"ember-htmlbars-component-generation": null,
"ember-htmlbars-inline-if-helper": null
},
"debugStatements": [
"Ember.warn",
Expand Down
17 changes: 13 additions & 4 deletions packages/ember-htmlbars/lib/helpers/if_unless.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { bind } from "ember-htmlbars/helpers/binding";

import { get } from "ember-metal/property_get";
import { isArray } from "ember-metal/utils";
import ConditionalStream from "ember-views/streams/conditional_stream";

function shouldDisplayIfHelperContent(result) {
var truthy = result && get(result, 'isTruthy');
Expand Down Expand Up @@ -89,13 +90,21 @@ function unboundIfHelper(params, hash, options, env) {
@return {String} HTML string
*/
function ifHelper(params, hash, options, env) {
Ember.assert("You must pass exactly one argument to the if helper", params.length === 1);
Ember.assert("You must pass a block to the if helper", !!options.render);

options.helperName = options.helperName || ('if ');
Ember.assert("If helper in block form expect exactly one argument", !options.render || params.length === 1);
if (Ember.FEATURES.isEnabled('ember-htmlbars-inline-if-helper')) {
if (!options.render) {
Ember.assert("If helper in inline form expects between two and three arguments", params.length === 2 || params.length === 3);
var condition = params[0];
var truthy = params[1];
var falsy = params[2];
return new ConditionalStream(condition, truthy, falsy);
}
}

options.inverse = options.inverse || function(){ return ''; };

options.helperName = options.helperName || ('if ');

if (env.data.isUnbound) {
return env.helpers.unboundIf.helperFunction.call(this, params, hash, options, env);
} else {
Expand Down
171 changes: 171 additions & 0 deletions packages/ember-htmlbars/tests/helpers/if_unless_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -665,3 +665,174 @@ test('edge case: rerender appearance of inner virtual view', function() {

equal(Ember.$('#qunit-fixture').text(), 'test');
});

if (Ember.FEATURES.isEnabled('ember-htmlbars-inline-if-helper')) {
test("`if` helper with inline form: renders the second argument when conditional is truthy", function() {
view = EmberView.create({
conditional: true,
template: compile('{{if view.conditional "truthy" "falsy"}}')
});

appendView(view);

equal(view.$().text(), 'truthy');
});

test("`if` helper with inline form: renders the third argument when conditional is falsy", function() {
view = EmberView.create({
conditional: false,
template: compile('{{if view.conditional "truthy" "falsy"}}')
});

appendView(view);

equal(view.$().text(), 'falsy');
});

test("`if` helper with inline form: can omit the falsy argument", function() {
view = EmberView.create({
conditional: true,
template: compile('{{if view.conditional "truthy"}}')
});

appendView(view);

equal(view.$().text(), 'truthy');
});

test("`if` helper with inline form: can omit the falsy argument and renders nothing when conditional is falsy", function() {
view = EmberView.create({
conditional: false,
template: compile('{{if view.conditional "truthy"}}')
});

appendView(view);

equal(view.$().text(), '');
});

test("`if` helper with inline form: truthy and falsy arguments are changed if conditional changes", function() {
view = EmberView.create({
conditional: true,
template: compile('{{if view.conditional "truthy" "falsy"}}')
});

appendView(view);

equal(view.$().text(), 'truthy');

run(function() {
view.set('conditional', false);
});

equal(view.$().text(), 'falsy');
});

test("`if` helper with inline form: can use truthy param as binding", function() {
view = EmberView.create({
truthy: 'ok',
conditional: true,
template: compile('{{if view.conditional view.truthy}}')
});

appendView(view);

equal(view.$().text(), 'ok');

run(function() {
view.set('truthy', 'yes');
});

equal(view.$().text(), 'yes');
});

test("`if` helper with inline form: can use falsy param as binding", function() {
view = EmberView.create({
truthy: 'ok',
falsy: 'boom',
conditional: false,
template: compile('{{if view.conditional view.truthy view.falsy}}')
});

appendView(view);

equal(view.$().text(), 'boom');

run(function() {
view.set('falsy', 'no');
});

equal(view.$().text(), 'no');
});

test("`if` helper with inline form: raises when using more than three arguments", function() {
view = EmberView.create({
conditional: true,
template: compile('{{if one two three four}}')
});

expectAssertion(function() {
appendView(view);
}, 'If helper in inline form expects between two and three arguments');
});

test("`if` helper with inline form: raises when using less than two arguments", function() {
view = EmberView.create({
conditional: true,
template: compile('{{if one}}')
});

expectAssertion(function() {
appendView(view);
}, 'If helper in inline form expects between two and three arguments');
});

test("`if` helper with inline form: works when used in a sub expression", function() {
view = EmberView.create({
conditional: true,
innerConditional: true,
template: compile('{{if view.conditional (if view.innerConditional "truthy" )}}')
});

appendView(view);

equal(view.$().text(), 'truthy');
});

test("`if` helper with inline form: updates if condition changes in a sub expression", function() {
view = EmberView.create({
conditional: true,
innerConditional: true,
template: compile('{{if view.conditional (if view.innerConditional "innerTruthy" "innerFalsy")}}')
});

appendView(view);

equal(view.$().text(), 'innerTruthy');

run(function() {
view.set('innerConditional', false);
});

equal(view.$().text(), 'innerFalsy');
});

test("`if` helper with inline form: can use truthy param as binding in a sub expression", function() {
view = EmberView.create({
conditional: true,
innerConditional: true,
innerTruthy: "innerTruthy",
template: compile('{{if view.conditional (if view.innerConditional view.innerTruthy)}}')
});

appendView(view);

equal(view.$().text(), 'innerTruthy');

run(function() {
view.set('innerTruthy', 'innerOk');
});

equal(view.$().text(), 'innerOk');
});
}
52 changes: 52 additions & 0 deletions packages/ember-views/lib/streams/conditional_stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Stream from "ember-metal/streams/stream";
import { read } from "ember-metal/streams/read";
import { create as o_create } from "ember-metal/platform";

function ConditionalStream(test, consequent, alternate) {
this._super(conditionalValueFn);
this.oldTest = undefined;
this.test = test;
this.consequent = consequent;
this.alternate = alternate;

if (test && test.isStream) {
test.subscribe(this.notify, this);
}
}

ConditionalStream.prototype = o_create(Stream.prototype);
ConditionalStream.prototype._super = Stream;

ConditionalStream.prototype._unsubscribe = function(value) {
if (value && value.isStream) {
value.unsubscribe(this.notify, this);
}
};

ConditionalStream.prototype._subscribe = function(value) {
if (value && value.isStream) {
value.subscribe(this.notify, this);
}
};

function conditionalValueFn() {
var test = !!read(this.test);

if (test !== this.oldTest) {
if (this.oldTest) {
this._unsubscribe(this.consequent);
} else {
this._unsubscribe(this.alternate);
}
if (test) {
this._subscribe(this.consequent);
} else {
this._subscribe(this.alternate);
}
this.oldTest = test;
}

return test ? read(this.consequent) : read(this.alternate);
}

export default ConditionalStream;

0 comments on commit 436dae0

Please sign in to comment.