Closed jmca closed 9 years ago
nice find
Need to clean up the fiddle for this, but I'm getting :sleeping:.
The behavior above is indeed happening. Thankfully, Region#show
is at least preventing this from populating multiple regions with a view whether outside or inside the LayoutView
. Our culprit seems to be good ole' getEl
that we redefine in Region.buildRegion
. It's used in the Region
constructor, but we don't redefine it until after we've instantiated the Region
, meaning the old implementation that doesn't take into account parentEl
gets run the first time. The implementation with parentEl
gets run with Region#show
.
Was there any headway on this issue? It's still an issue with v2.2.1. If everybody's busy I can dig in.
Was there any headway on this issue?
Not that I know of, @jmca.
If everybody's busy I can dig in.
That'd be awesome!
k
yeah @jmca it was in @jfairbank 's work however that was backed out due to some breaking changes
k
I created a pull request candidate. Let me know if I'm missing anything.
Hey, @jmca. Thanks for taking a look at this! I've been swamped the past few weeks, so another set of eyes on this is appreciated.
My latest PR is still an in progress, but I wanted to get some feedback. After weeding through things this issue might be a use-case non-issue, but technically is an issue.
The issue:
el
option), it's initial $el
is scoped to the document level (whole DOM).The non-issue:
someRegion.show(...)
, the Region's $el
is recalculated and gets reassigned the correct element scoped to its LayoutView. About the changes:
this._initializeRegions(options);
after Marionette.ItemView.call(this, options);
I'm not sure why exactly it is placed before, would love some feedback on this. When _initializeRegions
is executed before the ItemView constructor call the layout's $el
is not formed yet, this is done in the ItemView call. This change is the one thing that is breaking a test case.getEl
(non breaking according to tests) since the Region constructor first calls getEl
in its original form (which queries the DOM from document level), then re-assigns getEl
to use the scope of the parentEl
. So, before refactor = the Region's initial $el value is every selector in the whole document, after refactor = the Region's initial $el is the correct element in the LayoutView's scope.Unfortunately, I don't think that that will work. Refactoring getEl
and moving _initializeRegions
was exactly what I did in my previous PR #1705, which broke Marionette. Others have brought up use cases where they need access to the regions in their LayoutView
initialize
method. If we move _initializeRegions
after the ItemView
constructor call, then the regions aren't available in initialize
.
Please keep sounding your ideas. I would love to see a BC fix for this. Any feedback @marionettejs/marionette-core?
I've put thought into this before, and I only ever came to the conclusion it was only possible to do all of the refactors I wanted in a v3 non-BC way.
It's been awhile since I've studied it, but it seems like that might still be the way to go. v3 isn't that far off, relatively. In 3 weeks, once 2.3 comes out, we'll be able to start merging v3 ideas into a branch. Maybe we just wait til then?
it is not a questions
do all of the refactors I wanted
rather how can we fix this one bad bug
Ha, I know. I meant to convey that this bug fix necessarily requires breaking refactors from what I could tell.
@jfairbank How does/would refactoring getEl break the current build?
@jfairbank
Others have brought up use cases where they need access to the regions in their LayoutView initialize method
I'm curious what the use case would be, mainly because the correct Region's $el
would not be available before View init. And since Region's are view based, they should probably be messed with in the View's onRender
method.
Also we could keep the Region init before the View init, then re-init all Regions $el
after View init. Not the most streamlined but it should also not break anything.
Another thought on the above comment, should a LayoutView's regions really be available in its constructor? Initialization methods assume the DOM is not constructed. While the onRender
events (or at the end of the render
method) assume that the DOM is constructed and available.
I created a work-around for now that "shouldn't" break anything.
Awesome @jmca! Excited to see. In the future, you should comment on the PR if you have a comment about the PR. It saves us time having to go figure out the PR that you're talking about :P
K. For some reason PR thread comments disappear when a re-pull happens. I'll keep comments there in the future though.
@jmca @samccone @jmeas The idea of my PR as stated is to force the scope after when the layout has been rendered so we have a valid $el. @jmca fix did not work for me.
I had the same issue has described by @jmca.
My use case is :
Fixed by #2149
@jmeas it appears that in the end it's still not possible to have scoping unless el
is already defined (e.g. the view has been rendered). Am I missing something?
@fabien what do you mean? Can you provide more info?
Well, unless the LayoutView has already been rendered, the parentEl
that is passed in here will be undefined
- which is always the case for template based layouts:
https://github.com/marionettejs/backbone.marionette/blob/master/src/layout-view.js#L107
However, if I take out this this._isFirstRender
clause, and let this._reinitializeRegions
run, it will work fine, and the region selector will be correctly scoped to the LayoutView:
https://github.com/marionettejs/backbone.marionette/blob/master/src/layout-view.js#L39
Make a new issue? //cc @megawac
@jmeas I don't have the time right now, sorry.
My current workaround to have the regions correctly scoped and available when I need them:
initialize: function(options) {
this.once('render', this.setupRegions);
},
setupRegions: function() {
this.addRegion('container', {
selector: '[data-region="container"]',
regionClass: ContainerRegion
});
this.addRegion('details', '[data-region="details"]');
}
I ran into the same issue as @fabien. It seems the parentEl
is not set if using a LayoutView
with a template because this.el
is not yet initialized. I was able to workaround the issue by overriding the LayoutView
constructor and moving the call to _initializeRegions
after the call to the Marionette.ItemView
constructor. This allows this.el
to be initialized now that Backbone.View._ensureElement
is called first. Changing the order does not appear to break anything in our project but I did notice the comment in the source that states // Ensure the regions are available when the 'initialize' method is called
so my change would break that expectation. I have not had a need to use regions in my initialize method and just mostly in the "before:show" or "render" view events so as of now I am okay with the change. I would be interested in any thoughts or other suggestions.
The regions hash in LayoutView attaches regions that are outside of the LayoutView's DOM tree.
The expected behavior is that it should only grab the inner/scoped regions under the LayoutView DOM tree.
The example below is using
el: ...
, I have not tried this using an actual template. I'm using_.template('')
only to thwart the "no template" exception.