run(function() { TemplateTests.contentController = ArrayProxy.create({ content: A(['foo','bar']) }); TemplateTests.InnerList = CollectionView.extend({ tagName: 'ul', contentBinding: 'parentView.innerListContent' }); TemplateTests.OuterListItem = EmberView.extend({ template: EmberHandlebars.compile('{{#collection TemplateTests.InnerList class="inner"}}{{content}}{{/collection}}{{content}}'), innerListContent: computed(function() { return A([1,2,3]); }) }); TemplateTests.OuterList = CollectionView.extend({ tagName: 'ul', contentBinding: 'TemplateTests.contentController', itemViewClass: TemplateTests.OuterListItem }); view = EmberView.create({ template: EmberHandlebars.compile('{{collection TemplateTests.OuterList class="outer"}}') }); });
test("should render nested collections", function() { TemplateTests.InnerList = CollectionView.extend({ tagName: 'ul', content: A(['one','two','three']) }); TemplateTests.OuterList = CollectionView.extend({ tagName: 'ul', content: A(['foo']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection TemplateTests.OuterList class="outer"}}{{content}}{{#collection TemplateTests.InnerList class="inner"}}{{content}}{{/collection}}{{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('ul.outer > li').length, 1, "renders the outer list with correct number of items"); equal(view.$('ul.inner').length, 1, "the inner list exsits"); equal(view.$('ul.inner > li').length, 3, "renders the inner list with correct number of items"); });
QUnit.test("should render nested collections", function() { var registry = new Registry(); var container = registry.container(); registry.register('view:inner-list', CollectionView.extend({ tagName: 'ul', content: A(['one','two','three']) })); registry.register('view:outer-list', CollectionView.extend({ tagName: 'ul', content: A(['foo']) })); view = EmberView.create({ container: container, template: compile('{{#collection "outer-list" class="outer"}}{{content}}{{#collection "inner-list" class="inner"}}{{content}}{{/collection}}{{/collection}}') }); runAppend(view); equal(view.$('ul.outer > li').length, 1, "renders the outer list with correct number of items"); equal(view.$('ul.inner').length, 1, "the inner list exsits"); equal(view.$('ul.inner > li').length, 3, "renders the inner list with correct number of items"); });
test("a block passed to a collection helper defaults to the view", function() { TemplateTests.CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection "TemplateTests.CollectionTestView"}} <label>{{view.content}}</label> {{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); // Preconds equal(view.$('li:nth-child(1) label').length, 1); equal(view.$('li:nth-child(1) label').text(), 'foo'); equal(view.$('li:nth-child(2) label').length, 1); equal(view.$('li:nth-child(2) label').text(), 'bar'); equal(view.$('li:nth-child(3) label').length, 1); equal(view.$('li:nth-child(3) label').text(), 'baz'); run(function() { set(firstChild(view), 'content', A()); }); equal(view.$('label').length, 0, "all list item views should be removed from DOM"); });
QUnit.test("empty views should be removed when content is added to the collection (regression, ht: msofaer)", function() { var EmptyView = EmberView.extend({ template : compile("<td>No Rows Yet</td>") }); var ListView = CollectionView.extend({ emptyView: EmptyView }); var listController = ArrayProxy.create({ content : A() }); view = EmberView.create({ listView: ListView, listController: listController, template: compile('{{#collection view.listView content=view.listController tagName="table"}} <td>{{view.content.title}}</td> {{/collection}}') }); runAppend(view); equal(view.$('tr').length, 1, 'Make sure the empty view is there (regression)'); run(function() { listController.pushObject({ title : "Go Away, Placeholder Row!" }); }); equal(view.$('tr').length, 1, 'has one row'); equal(view.$('tr:nth-child(1) td').text(), 'Go Away, Placeholder Row!', 'The content is the updated data.'); });
test("should re-render when the content object changes", function() { TemplateTests.RerenderTest = CollectionView.extend({ tagName: 'ul', content: A() }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection TemplateTests.RerenderTest}}{{view.content}}{{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); run(function() { set(firstChild(view), 'content', A(['bing', 'bat', 'bang'])); }); run(function() { set(firstChild(view), 'content', A(['ramalamadingdong'])); }); equal(view.$('li').length, 1, "rerenders with correct number of items"); equal(trim(view.$('li:eq(0)').text()), "ramalamadingdong"); });
test("should work inside a bound {{#if}}", function() { var testData = A([EmberObject.create({ isBaz: false }), EmberObject.create({ isBaz: true }), EmberObject.create({ isBaz: true })]); var IfTestCollectionView = CollectionView.extend({ tagName: 'ul', content: testData }); view = EmberView.create({ ifTestCollectionView: IfTestCollectionView, template: compile('{{#if view.shouldDisplay}}{{#collection view.ifTestCollectionView}}{{content.isBaz}}{{/collection}}{{/if}}'), shouldDisplay: true }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('ul li').length, 3, "renders collection when conditional is true"); run(function() { set(view, 'shouldDisplay', false); }); equal(view.$('ul li').length, 0, "removes collection when conditional changes to false"); run(function() { set(view, 'shouldDisplay', true); }); equal(view.$('ul li').length, 3, "collection renders when conditional changes to true"); });
QUnit.test('a block passed to a collection helper defaults to the view', function() { var CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ collectionTestView: CollectionTestView, template: compile('{{#collection view.collectionTestView}} <label>{{view.content}}</label> {{/collection}}') }); runAppend(view); // Preconds equal(view.$('li:nth-child(1) label').length, 1); equal(view.$('li:nth-child(1) label').text(), 'foo'); equal(view.$('li:nth-child(2) label').length, 1); equal(view.$('li:nth-child(2) label').text(), 'bar'); equal(view.$('li:nth-child(3) label').length, 1); equal(view.$('li:nth-child(3) label').text(), 'baz'); run(function() { set(firstChild(view), 'content', A()); }); equal(view.$('label').length, 0, 'all list item views should be removed from DOM'); });
QUnit.test("collection helper should accept relative paths", function() { view = EmberView.create({ template: compile('{{#collection view.collection}} <label></label> {{/collection}}'), collection: CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }) }); runAppend(view); equal(view.$('label').length, 3, 'one label element is created for each content item'); });
QUnit.test("select tagName on collection helper automatically sets child tagName to option", function() { var RerenderTest = CollectionView.extend({ content: A(['foo']) }); view = EmberView.create({ rerenderTestView: RerenderTest, template: compile('{{#collection view.rerenderTestView tagName="select"}}{{view.content}}{{/collection}}') }); runAppend(view); equal(view.$('option').length, 1, "renders the correct child tag name"); });
QUnit.test("should give its item views the class specified by itemClass", function() { var ItemClassTestCollectionView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ itemClassTestCollectionView: ItemClassTestCollectionView, template: compile('{{#collection view.itemClassTestCollectionView itemClass="baz"}}foo{{/collection}}') }); runAppend(view); equal(view.$('ul li.baz').length, 3, "adds class attribute"); });
QUnit.test("should include an id attribute if id is set in the options hash", function() { var CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ collectionTestView: CollectionTestView, template: compile('{{#collection view.collectionTestView id="baz"}}foo{{/collection}}') }); runAppend(view); equal(view.$('ul#baz').length, 1, "adds an id attribute"); });
test("should give its item views the class specified by itemClass", function() { TemplateTests.itemClassTestCollectionView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection "TemplateTests.itemClassTestCollectionView" itemClass="baz"}}foo{{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('ul li.baz').length, 3, "adds class attribute"); });
QUnit.test("if no content is passed, and no 'else' is specified, nothing is rendered", function() { var CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A() }); view = EmberView.create({ collectionTestView: CollectionTestView, template: compile('{{#collection view.collectionTestView}} <aside></aside> {{/collection}}') }); runAppend(view); equal(view.$('li').length, 0, 'if no "else" is specified, nothing is rendered'); });
QUnit.test("passing a block to the collection helper sets it as the template for example views", function() { var CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ collectionTestView: CollectionTestView, template: compile('{{#collection view.collectionTestView}} <label></label> {{/collection}}') }); runAppend(view); equal(view.$('label').length, 3, 'one label element is created for each content item'); });
QUnit.test("if no content is passed, and 'else' is specified, the else block is rendered", function() { var CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A() }); view = EmberView.create({ collectionTestView: CollectionTestView, template: compile('{{#collection view.collectionTestView}} <aside></aside> {{ else }} <del></del> {{/collection}}') }); runAppend(view); equal(view.$('li:has(del)').length, 1, 'the else block is rendered'); });
test("if no content is passed, and no 'else' is specified, nothing is rendered", function() { TemplateTests.CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A() }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection "TemplateTests.CollectionTestView"}} <aside></aside> {{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('li').length, 0, 'if no "else" is specified, nothing is rendered'); });
test("if no content is passed, and 'else' is specified, the else block is rendered", function() { TemplateTests.CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A() }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection "TemplateTests.CollectionTestView"}} <aside></aside> {{ else }} <del></del> {{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('li:has(del)').length, 1, 'the else block is rendered'); });
test("passing a block to the collection helper sets it as the template for example views", function() { TemplateTests.CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection TemplateTests.CollectionTestView}} <label></label> {{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('label').length, 3, 'one label element is created for each content item'); });
test("select tagName on collection helper automatically sets child tagName to option", function() { TemplateTests.RerenderTest = CollectionView.extend({ content: A(['foo']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection TemplateTests.RerenderTest tagName="select"}}{{view.content}}{{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('option').length, 1, "renders the correct child tag name"); });
test("should include an id attribute if id is set in the options hash", function() { TemplateTests.CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection "TemplateTests.CollectionTestView" id="baz"}}foo{{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('ul#baz').length, 1, "adds an id attribute"); });
QUnit.test("itemViewClass works in the #collection via container", function() { registry.register('view:example-item', EmberView.extend({ isAlsoCustom: true })); view = EmberView.create({ container: container, exampleCollectionView: CollectionView.extend(), exampleController: ArrayProxy.create({ content: A(['alpha']) }), template: compile('{{#collection view.exampleCollectionView content=view.exampleController itemViewClass="example-item"}}beta{{/collection}}') }); runAppend(view); ok(firstGrandchild(view).isAlsoCustom, "uses the example view class specified in the #collection helper"); });
QUnit.test("Collection views that specify an example view class have their children be of that class", function() { var ExampleViewCollection = CollectionView.extend({ itemViewClass: EmberView.extend({ isCustom: true }), content: A(['foo']) }); view = EmberView.create({ exampleViewCollection: ExampleViewCollection, template: compile('{{#collection view.exampleViewCollection}}OHAI{{/collection}}') }); runAppend(view); ok(firstGrandchild(view).isCustom, "uses the example view class"); });
run(function() { TemplateTests.datasetController = EmberObject.create(); TemplateTests.ReportingView = EmberView.extend({ datasetBinding: 'TemplateTests.datasetController.dataset', readyBinding: 'dataset.ready', itemsBinding: 'dataset.items', template: EmberHandlebars.compile("{{#if view.ready}}{{collection TemplateTests.CollectionView}}{{else}}Loading{{/if}}") }); TemplateTests.CollectionView = CollectionView.extend({ contentBinding: 'parentView.items', tagName: 'ul', template: EmberHandlebars.compile("{{view.content}}") }); view = TemplateTests.ReportingView.create(); });
QUnit.test("should give its item views the class specified by itemClass", function() { var ItemClassBindingTestCollectionView = CollectionView.extend({ tagName: 'ul', content: A([EmberObject.create({ isBaz: false }), EmberObject.create({ isBaz: true }), EmberObject.create({ isBaz: true })]) }); view = EmberView.create({ itemClassBindingTestCollectionView: ItemClassBindingTestCollectionView, isBar: true, template: compile('{{#collection view.itemClassBindingTestCollectionView itemClass=view.isBar}}foo{{/collection}}') }); runAppend(view); equal(view.$('ul li.is-bar').length, 3, "adds class on initial rendering"); // NOTE: in order to bind an item's class to a property of the item itself (e.g. `isBaz` above), it will be necessary // to introduce a new keyword that could be used from within `itemClassBinding`. For instance, `itemClassBinding="item.isBaz"`. });
run(function() { TemplateTests.datasetController = EmberObject.create(); var ExampleCollectionView = CollectionView.extend({ contentBinding: 'parentView.items', tagName: 'ul', _itemViewTemplate: compile('{{view.content}}') }); var ReportingView = EmberView.extend({ exampleCollectionView: ExampleCollectionView, datasetBinding: 'TemplateTests.datasetController.dataset', readyBinding: 'dataset.ready', itemsBinding: 'dataset.items', template: compile('{{#if view.ready}}{{collection view.exampleCollectionView}}{{else}}Loading{{/if}}') }); view = ReportingView.create(); });
QUnit.test("a block passed to a collection helper defaults to the content property of the context", function() { var CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ collectionTestView: CollectionTestView, template: compile('{{#collection view.collectionTestView}} <label>{{view.content}}</label> {{/collection}}') }); runAppend(view); equal(view.$('li:nth-child(1) label').length, 1); equal(view.$('li:nth-child(1) label').text(), 'foo'); equal(view.$('li:nth-child(2) label').length, 1); equal(view.$('li:nth-child(2) label').text(), 'bar'); equal(view.$('li:nth-child(3) label').length, 1); equal(view.$('li:nth-child(3) label').text(), 'baz'); });
QUnit.test('collection helper should try to use container to resolve view', function() { var registry = new Registry(); var container = registry.container(); var ACollectionView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); registry.register('view:collectionTest', ACollectionView); view = EmberView.create({ container: container, template: compile('{{#collection "collectionTest"}} <label></label> {{/collection}}') }); runAppend(view); equal(view.$('label').length, 3, 'one label element is created for each content item'); });
test("a block passed to a collection helper defaults to the content property of the context", function() { TemplateTests.CollectionTestView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); view = EmberView.create({ template: EmberHandlebars.compile('{{#collection "TemplateTests.CollectionTestView"}} <label>{{view.content}}</label> {{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('li:nth-child(1) label').length, 1); equal(view.$('li:nth-child(1) label').text(), 'foo'); equal(view.$('li:nth-child(2) label').length, 1); equal(view.$('li:nth-child(2) label').text(), 'bar'); equal(view.$('li:nth-child(3) label').length, 1); equal(view.$('li:nth-child(3) label').text(), 'baz'); });
test("collection helper should try to use container to resolve view", function() { var container = new Container(); var ACollectionView = CollectionView.extend({ tagName: 'ul', content: A(['foo', 'bar', 'baz']) }); container.register('view:collectionTest', ACollectionView); var controller = {container: container}; view = EmberView.create({ controller: controller, template: EmberHandlebars.compile('{{#collection "collectionTest"}} <label></label> {{/collection}}') }); run(function() { view.appendTo('#qunit-fixture'); }); equal(view.$('label').length, 3, 'one label element is created for each content item'); });