From 6c2f000f11040709dd8dcdcf07b1224569afde80 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 20 May 2015 07:39:32 -0400 Subject: [PATCH] [BUGFIX beta] Fix {{each}} with `itemViewClass` and {{else}}. --- .../lib/templates/legacy-each.hbs | 2 +- .../ember-htmlbars/tests/helpers/each_test.js | 19 ++++++ .../lib/mixins/empty_view_support.js | 62 +++++++++++++++++++ .../ember-views/lib/views/collection_view.js | 51 +-------------- .../ember-views/lib/views/legacy_each_view.js | 3 +- 5 files changed, 87 insertions(+), 50 deletions(-) create mode 100644 packages/ember-views/lib/mixins/empty_view_support.js diff --git a/packages/ember-htmlbars/lib/templates/legacy-each.hbs b/packages/ember-htmlbars/lib/templates/legacy-each.hbs index c6b7983fe04..2b34027d615 100644 --- a/packages/ember-htmlbars/lib/templates/legacy-each.hbs +++ b/packages/ember-htmlbars/lib/templates/legacy-each.hbs @@ -1 +1 @@ -{{~#each view._arrangedContent as |item|}}{{#if attrs.itemViewClass}}{{#view attrs.itemViewClass controller=item _defaultTagName=view._itemTagName}}{{legacy-yield item}}{{/view}}{{else}}{{legacy-yield item controller=item}}{{/if}}{{else if attrs.emptyViewClass}}{{view attrs.emptyViewClass _defaultTagName=view._itemTagName}}{{/each~}} +{{~#each view._arrangedContent as |item|}}{{#if attrs.itemViewClass}}{{#view attrs.itemViewClass controller=item _defaultTagName=view._itemTagName}}{{legacy-yield item}}{{/view}}{{else}}{{legacy-yield item controller=item}}{{/if}}{{else if view._emptyView}}{{view view._emptyView _defaultTagName=view._itemTagName}}{{/each~}} diff --git a/packages/ember-htmlbars/tests/helpers/each_test.js b/packages/ember-htmlbars/tests/helpers/each_test.js index d64c36c0730..0fc0c8defd0 100644 --- a/packages/ember-htmlbars/tests/helpers/each_test.js +++ b/packages/ember-htmlbars/tests/helpers/each_test.js @@ -622,6 +622,25 @@ QUnit.test("it supports {{itemViewClass=}} with tagName in itemViewClass (DEPREC equal(view.$('ul li').text(), 'Steve HoltAnnabelle'); }); +QUnit.test("it supports {{itemViewClass=}} with {{else}} block (DEPRECATED)", function() { + runDestroy(view); + + view = EmberView.create({ + template: templateFor(` + {{~#each view.people itemViewClass="my-view" as |item|~}} + {{item.name}} + {{~else~}} + No records! + {{~/each}}`), + people: A(), + container: container + }); + + runAppend(view); + + equal(view.$().text(), 'No records!'); +}); + QUnit.test("it supports {{itemViewClass=}} with in format", function() { MyView = EmberView.extend({ template: templateFor("{{person.name}}") diff --git a/packages/ember-views/lib/mixins/empty_view_support.js b/packages/ember-views/lib/mixins/empty_view_support.js new file mode 100644 index 00000000000..d33f50c4da5 --- /dev/null +++ b/packages/ember-views/lib/mixins/empty_view_support.js @@ -0,0 +1,62 @@ +/** + @module ember + @submodule ember-views + */ + +import { Mixin } from "ember-metal/mixin"; +import View from "ember-views/views/view"; +import { get } from "ember-metal/property_get"; +import { set } from "ember-metal/property_set"; +import { computed } from "ember-metal/computed"; + +/** + @class EmptyViewSupport + @namespace Ember + */ +export default Mixin.create({ + /** + This provides metadata about what kind of empty view class this + collection would like if it is being instantiated from another + system (like Handlebars) + + @private + @property emptyViewClass + */ + emptyViewClass: View, + + /** + An optional view to display if content is set to an empty array. + + @property emptyView + @type Ember.View + @default null + */ + emptyView: null, + + _emptyView: computed('emptyView', 'attrs.emptyViewClass', 'emptyViewClass', function() { + var emptyView = get(this, 'emptyView'); + var attrsEmptyViewClass = this.getAttr('emptyViewClass'); + var emptyViewClass = get(this, 'emptyViewClass'); + var inverse = get(this, '_itemViewInverse'); + var actualEmpty = emptyView || attrsEmptyViewClass; + + // Somehow, our previous semantics differed depending on whether the + // `emptyViewClass` was provided on the JavaScript class or via the + // Handlebars template. + // In Glimmer, we disambiguate between the two by checking first (and + // preferring) the attrs-supplied class. + // If not present, we fall back to the class's `emptyViewClass`, but only + // if an inverse has been provided via an `{{else}}`. + if (inverse && actualEmpty) { + if (actualEmpty.extend) { + return actualEmpty.extend({ template: inverse }); + } else { + set(actualEmpty, 'template', inverse); + } + } else if (inverse && emptyViewClass) { + return emptyViewClass.extend({ template: inverse }); + } + + return actualEmpty; + }) +}); diff --git a/packages/ember-views/lib/views/collection_view.js b/packages/ember-views/lib/views/collection_view.js index 200dcbd0209..ac197287290 100644 --- a/packages/ember-views/lib/views/collection_view.js +++ b/packages/ember-views/lib/views/collection_view.js @@ -1,4 +1,3 @@ - /** @module ember @submodule ember-views @@ -17,6 +16,7 @@ import { beforeObserver } from "ember-metal/mixin"; import { readViewFactory } from "ember-views/streams/utils"; +import EmptyViewSupport from "ember-views/mixins/empty_view_support"; /** `Ember.CollectionView` is an `Ember.View` descendent responsible for managing @@ -179,9 +179,10 @@ import { readViewFactory } from "ember-views/streams/utils"; @class CollectionView @namespace Ember @extends Ember.ContainerView + @uses Ember.EmptyViewSupport @since Ember 0.9 */ -var CollectionView = ContainerView.extend({ +var CollectionView = ContainerView.extend(EmptyViewSupport, { /** A list of items to be displayed by the `Ember.CollectionView`. @@ -192,25 +193,6 @@ var CollectionView = ContainerView.extend({ */ content: null, - /** - This provides metadata about what kind of empty view class this - collection would like if it is being instantiated from another - system (like Handlebars) - - @private - @property emptyViewClass - */ - emptyViewClass: View, - - /** - An optional view to display if content is set to an empty array. - - @property emptyView - @type Ember.View - @default null - */ - emptyView: null, - /** @property itemViewClass @type Ember.View @@ -398,33 +380,6 @@ var CollectionView = ContainerView.extend({ } }, - _emptyView: computed('emptyView', 'attrs.emptyViewClass', 'emptyViewClass', function() { - var emptyView = get(this, 'emptyView'); - var attrsEmptyViewClass = this.getAttr('emptyViewClass'); - var emptyViewClass = get(this, 'emptyViewClass'); - var inverse = get(this, '_itemViewInverse'); - var actualEmpty = emptyView || attrsEmptyViewClass; - - // Somehow, our previous semantics differed depending on whether the - // `emptyViewClass` was provided on the JavaScript class or via the - // Handlebars template. - // In Glimmer, we disambiguate between the two by checking first (and - // preferring) the attrs-supplied class. - // If not present, we fall back to the class's `emptyViewClass`, but only - // if an inverse has been provided via an `{{else}}`. - if (inverse && actualEmpty) { - if (actualEmpty.extend) { - return actualEmpty.extend({ template: inverse }); - } else { - set(actualEmpty, 'template', inverse); - } - } else if (inverse && emptyViewClass) { - return emptyViewClass.extend({ template: inverse }); - } - - return actualEmpty; - }), - _emptyViewTagName: computed('tagName', function() { var tagName = get(this, 'tagName'); return CollectionView.CONTAINER_MAP[tagName] || 'div'; diff --git a/packages/ember-views/lib/views/legacy_each_view.js b/packages/ember-views/lib/views/legacy_each_view.js index 344bc90d773..bbd2b374103 100644 --- a/packages/ember-views/lib/views/legacy_each_view.js +++ b/packages/ember-views/lib/views/legacy_each_view.js @@ -8,8 +8,9 @@ import { set } from "ember-metal/property_set"; import { computed } from "ember-metal/computed"; import View from "ember-views/views/view"; import { CONTAINER_MAP } from "ember-views/views/collection_view"; +import EmptyViewSupport from "ember-views/mixins/empty_view_support"; -export default View.extend({ +export default View.extend(EmptyViewSupport, { template: legacyEachTemplate, tagName: '',