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

WIP Next Region #3664

Closed
wants to merge 3 commits into from
Closed

Conversation

paulfalgout
Copy link
Member

@paulfalgout paulfalgout commented Apr 28, 2019

An iteration and replacement for #3620

This is starting to feel really good.
This is a WIP and I'll add more notes here shortly, but I wanted to get it out for 👀
I do think there's a handful of things we can introduce in a v4.x as well as some small deprecations that can be made for the breaking changes.
There are actually few breaking changes I believe the breaking changes that are there are minor and like inconsequential for most users.
I haven't done perf tests yet, but I feel moderately confident this will be more performant, and again I haven't tested it, but I believe this makes rendering views non-destructive to children.

I will work on documenting changes as well as breaking up this PR into sane commits as well as making v4.x PRs for features and deprecations we can do now.

But this I think is a good start. @marionettejs/marionette-core

Breaking Changes

  • Region no longer accepts a jquery instances as el el: $el[0] should be used instead of el: $el This removes region's dependencies on jquery.
  • As previously discussed, the not documented allowMissingEl is removed, however the reasoning for adding this flag in the first place is not an issue with this revision
  • Both add:region and remove:region events were removed. They're even less useful now than they were previously, and there's a new hook for when regions are bound to the view bind:regions that should cover any use case this previously had. This should make rendering cheaper overall as well.
  • Regions no longer empty on render. This may be the biggest breaking change to watch out for. However for the general case where the user is setting the children in onRender the 2nd show will handle the empty effectively in the same way as before. But there may be some cases where conditional child renders will no longer empty out the previous view. Users will need to handle these cases now, but this also should allow children to be created once in an onReady and child views may not need to be re-rendered at all when the parent is rendered.
  • Not documented, but Region's @ui allowed the user to build complex selectors such as:
    regionName: '@ui.foo @ui.bar' producing regionName: '#foo .bar'. This change prevents that and requires a single ui only. Not only is the complex selector not recommended anyways, this prevents needing to requery the selector and the already queried ui is used instead.
  • Not documented, but defining a Region on a view's region hash allowed the user to pass either and instance of a region or a region class.
     regions : {
       foo: myRegion
       bar: MyRegionClass
     }
    Both of these options are no longer supported as an el selector is required to be managed by the view, and both of these options prevent that. However allowing the view to maintain regions outside of the view is problematic and certainly makes showChildView difficult to understand. While I doubt many people are using this feature anyways, the way to support these options is:
    const MyRegionClass = Region.extend({ el: '#foo' }); // some predefined selector
    const MyView = View.extend({
      initialize({ myRegion }) {
        this.myRegion = myRegion;
      },
      regions: {
        bar: {
          el: '#foo',
          regionClass: MyRegionClass
        }
      }
  • Though largely considered a bug View's region using el from child view, not own view #3320 if a user was setting up regions to be within a child view, this will no longer work. It should be documented however that using addRegion or addRegions after the view is rendered will query all of the children until the render in which it will only query the rendered template. It might be best to suggest simply adding a definition to myView.regions and then re-rendering.
  • Regions are no longer instantiated prior to View#initialize. This shouldn't really be an issue as getting a region will render and instantiation the region needed... but if someone was doing something strange and expecting the region init to be prior to the view's init, it would technically be breaking.
  • The el on a region prior to showing a view was possibly the selector (if instantiated with a selector) Now it will always be a DOM element or undefined if nothing was found by the query. It might be an issue for users who instantiate a region that does a global look up for DOM that didn't exist at the time of instantiation.
  • Region#reset was removed. In this context it is no longer needed.

New Features
View ready event indicating the best spot to attach children
Application region can now be defined as a function returning a region or region definition
Region#setElement was made public and properly handles the various attached states of the elements

@paulfalgout paulfalgout added this to the v5 milestone Apr 28, 2019
@coveralls
Copy link

coveralls commented Apr 28, 2019

Coverage Status

Coverage decreased (-0.5%) to 99.516% when pulling 1e40870 on paulfalgout:region-next into 5090557 on marionettejs:master.

marionettejs#3320

This is one extra loop, but the dom query could be much cheaper since no children will be attached, and it prevents unintended querying of the same selector in a child
Keeps support for edge case in `setElement` where the view was ready on `initialize`, but would be after `setElement`
}

if (!_.isString(definition.el)) {
console.log(definition);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to remove this

onAddRegion: function() {},
onBeforeAddRegion: function() {}
});
this.MyView = Marionette.View.extend();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of the test changes in this file relate to removing add:region / remove:region

@@ -637,53 +638,4 @@ describe('layoutView', function() {
});
});
});

describe('manipulating regions', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// removing add:region / remove:region

@@ -550,6 +550,7 @@ describe('layoutView', function() {
});

it('should set custom region classes', function() {
this.layoutView.render();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regions aren't initialized until the view is rendered

@@ -522,7 +522,7 @@ describe('layoutView', function() {
war: '.craft',
is: {
regionClass: this.CustomRegion,
selector: '#a-fun-game'
el: '#a-fun-game'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests failed silently before 😿

@@ -33,7 +33,7 @@ describe('layoutView', function() {
this.ViewNoDefaultRegion = this.View.extend({
regions: {
regionOne: {
selector: '#regionOne',
el: '#regionOne',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests failed silently before 😿

@@ -470,8 +470,8 @@ describe('layoutView', function() {
this.layoutView.render();
});

it('should call empty twice', function() {
expect(this.region.empty).to.have.been.calledThrice;
it('should call empty once', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a poorly written test, but childviews are no longer emptied on the parent's render

@@ -1317,30 +1226,6 @@ describe('region', function() {
});
});

describe('when calling "_ensureElement"', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed allowMissingEl

@@ -1124,37 +1064,6 @@ describe('region', function() {
});
});

describe('when resetting a region', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove reset

itemView.addRegions({
MyRegion: '#region',
anotherRegion: '#region2'
itemView = new View({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test broke because it was nooping render which is now what builds the regions it was testing

@@ -1031,22 +985,6 @@ describe('region', function() {
});
});

describe('when initializing a region and passing an "el" option', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el is no longer the string after initialization

@@ -212,7 +166,7 @@ describe('region', function() {
beforeEach(function() {
this.setFixtures('<div id="region"></div>');
myRegion = new Region({
el: '#region'
el: $('#region')[0]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can revert this, but it works either way

@@ -156,38 +112,36 @@ describe('region', function() {
});

it('should return the region', function() {
expect(region._setElement(twoEl)).to.equal(region);
expect(region.setElement(twoEl)).to.equal(region);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setElement was made public

@@ -89,52 +72,25 @@ describe('region', function() {
$(this.el).html('some content');
}
});
myView = new MyView();

this.setFixtures('<div id="region"></div>');
});

describe('when showing a view', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed allowMissingEl

describe('when passing an el DOM reference in directly', function() {
let el;
let customRegion;
let optionRegion;
let optionRegionJquery;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the option to pass in el as a jquery object

@@ -8,19 +8,10 @@ import CollectionView from '../../src/collection-view';
describe('region', function() {
'use strict';

describe('when creating a new region and no configuration has been provided', function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el can be undefined now during initialization

@paulfalgout
Copy link
Member Author

Note: nondestructive regions will not work without changing the dom api away from jquery
https://jsfiddle.net/qjmtpg9y/7/
when the view is rendered with $el.html jquery removes any previous listeners which breaks the existing child views.

@paulfalgout
Copy link
Member Author

This will eventually move to https://github.com/marionettejs/marionette

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

Successfully merging this pull request may close these issues.

2 participants