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

Collection view throwing "You can't insert an element into the DOM that has already been inserted" #78

Closed
crofty opened this issue Jul 14, 2011 · 4 comments

Comments

@crofty
Copy link
Contributor

crofty commented Jul 14, 2011

I've got another issue in my app relating to collection views. I've reduced it down to a failing test case which is below. I've run the test against previous versions of the code and verifed that it used to pass.

The breaking change was introduced in 0ae26af.

What I am trying to do is render a CollectionView within a view that has bindings to an object - datasetController. When I swap out the dataset for another one, I'd expect the rendered html to update to reflect the new dataset. Instead, I'm getting the following error:

You can't insert an element into the DOM that has already been inserted

Test case is:

test("should allow view objects to be swapped out without throwing an error", function() {
  var view, dataset, secondDataset;

  SC.run(function() {
    TemplateTests.datasetController = SC.Object.create();

    TemplateTests.ReportingView = SC.View.extend({
      datasetBinding: 'TemplateTests.datasetController*dataset',
      readyBinding: 'dataset.ready',
      itemsBinding: 'dataset.items',
      template: SC.Handlebars.compile("{{#if ready}}{{collection TemplateTests.CollectionView}}{{else}}Loading{{/if}}")
    });

    TemplateTests.CollectionView = SC.CollectionView.extend({
      contentBinding: 'parentView.parentView.items',
      tagName: 'ul',
      template: SC.Handlebars.compile("{{content}}")
    });

    view = TemplateTests.ReportingView.create();
  });

  SC.run(function() {
    view.appendTo('#qunit-fixture');
  });

  equals(view.$().text(), "Loading", "renders the loading text when the dataset is not ready");

  SC.run(function() {
    dataset = SC.Object.create({
      ready: true,
      items: [1,2,3]
    });
    TemplateTests.datasetController.set('dataset',dataset);
  });

  equals(view.$('ul > li').length, 3, "renders the collection with the correct number of items when the dataset is ready");

  SC.run(function() {
    secondDataset = SC.Object.create({ready: false});
    TemplateTests.datasetController.set('dataset',secondDataset);
  });

  equals(view.$().text(), "Loading", "renders the loading text when the second dataset is not ready");

});
@ebryn
Copy link
Member

ebryn commented Jul 14, 2011

I can get the test to pass if you dataset.set('ready', false) rather than setting secondDataset.

test("should allow view objects to be swapped out without throwing an error", function() {
  var view, dataset, secondDataset;

  SC.run(function() {
    TemplateTests.datasetController = SC.Object.create();

    TemplateTests.ReportingView = SC.View.extend({
      datasetBinding: 'TemplateTests.datasetController*dataset',
      readyBinding: 'dataset.ready',
      itemsBinding: 'dataset.items',
      template: SC.Handlebars.compile("{{#if ready}}{{collection TemplateTests.CollectionView}}{{else}}Loading{{/if}}")
    });

    TemplateTests.CollectionView = SC.CollectionView.extend({
      contentBinding: 'parentView.parentView.items',
      tagName: 'ul',
      template: SC.Handlebars.compile("{{content}}")
    });

    view = TemplateTests.ReportingView.create();
  });

  SC.run(function() {
    view.appendTo('#qunit-fixture');
  });

  equals(view.$().text(), "Loading", "renders the loading text when the dataset is not ready");

  SC.run(function() {
    dataset = SC.Object.create({
      ready: true,
      items: [1,2,3]
    });
    TemplateTests.datasetController.set('dataset',dataset);
  });

  equals(view.$('ul > li').length, 3, "renders the collection with the correct number of items when the dataset is ready");

  SC.run(function() {
    dataset.set('ready', false);
  });

  equals(view.$().text(), "Loading", "renders the loading text when the second dataset is not ready");

});

@ebryn
Copy link
Member

ebryn commented Jul 14, 2011

I do think there is a bug here potentially. I'm investigating.

@ebryn
Copy link
Member

ebryn commented Jul 14, 2011

tomdale pushed a commit that referenced this issue Jul 14, 2011
Move the setting of element to null after the childViews.replace()... Fixes issue #78.
@ebryn
Copy link
Member

ebryn commented Jul 14, 2011

Fixed on master now.

@tomdale tomdale closed this as completed Jul 15, 2011
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

No branches or pull requests

3 participants