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

Don't detach pre-existing HTML when view's el is already in the region #3227

Closed
paulfalgout opened this issue Oct 11, 2016 · 3 comments
Closed
Milestone

Comments

@paulfalgout
Copy link
Member

Related to #3128

When a view is attached to pre-existing DOM and then shown in a region, the view's el may already be inside of the region, but currently the region is unaware of this. So to allow for pre-generated HTML we detach the region HTML https://github.com/marionettejs/backbone.marionette/blob/master/src/region.js#L212
Which is then immediately re-attached in the region's show.

Functionally this works, but this is likely causing extra paints and it is detaching/attaching a view without throwing events, so anything setup externally to this HTML will break with no use-able hooks to handle the situation.

We could solve this in a couple of ways. The cheapest way is for a region to not empty itself if it doesn't have a view but the view being passed in to show is already attached.. This way assumes that the view's el is already in the region. Can anyone think of any other reason an already attached view should be shown in a region? Attaching a view to 2 regions seems like a horribly bad idea. But we could take it a step further to ensure the region contains the view el with something like Backbone.$.contains(this.el, view.el); But then what are we protecting against?

Conversely _attachView would need to bail out if the view was already attached. This pattern would I think also be applied to CollectionView This makes attach and render much more similar so I think I like it.

@paulfalgout paulfalgout added this to the v3.x milestone Oct 11, 2016
@paulfalgout paulfalgout changed the title Don't detach pre-existing HTML Don't detach pre-existing HTML when view's el is already in the region Oct 11, 2016
@scott-w
Copy link
Member

scott-w commented Oct 25, 2016

About the only time I can see the former being useful is where:

var MyView = Mn.View.extend({
  region: {
    main: '.main-hook'
  },

  showSomeView: function() {
    this.showChildView('main', this._someView, {preventDestroy: true});
  },

  showDifferentView: function() {
    this.showChildView('main', this._differentView, {preventDestroy: true});
  },

  initialize: function() {
    this._someView = new SomeView();
    this._differentView = new DifferentView();
  }
});

It's not something I've personally done but maybe there's a lot of work involved setting up the view you might want to save on by just keeping them alive and swappable? This wouldn't involve showing a view in multiple places, however, just in the same place.

That leads me more to the latter solution, however, if this view is shown, do nothing - perhaps just using console.warn to assist debugging?

@paulfalgout
Copy link
Member Author

The only way your example is a problem is if both views currently exist in the DOM prior to being shown in the region. Otherwise we'd be ok because the 2nd show would detach the other view, and it would resolve itself. The main issue here is when we're trying to show a view that is currently attached to the DOM inside the region it is being shown in. If another view is in there and they're begin swapped, we're ok now.

@scott-w
Copy link
Member

scott-w commented Oct 26, 2016

So:

var someView = new SomeView();
view.showChildView('main', someView);
view.showChildView('main', someView);

is currently an issue?

Or are we thinking specifically for:

var someView = new SomeView();

view.showChildView('main', someView);
view.showChildView('other', someView);

paulfalgout added a commit to paulfalgout/backbone.marionette that referenced this issue Nov 15, 2016
Resolves marionettejs#3227

This PR also moves some of `Region.show` into a `_setupChildView` function which mirrors what is happening in a CollectionView currently and helps reduce the length of the `show` function which grew to handle the should empty check.

In the specs, there was a failing test regarding “when setting the "replaceElement" class option”.  I believe this test was failing because it was reusing `this.view` which wasn’t cleaned up in a prior test.  So effectively `this.view` was currently already shown in another region.  I switched this to `this.view1` which is instantiated as part of this `describe` block (or closer at least) and should be better for these tests.
@paulfalgout paulfalgout modified the milestones: v3.2, v3.x Dec 16, 2016
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

2 participants