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

Add templateAsEl option to View #3259

Closed

Conversation

paulfalgout
Copy link
Member

Resolves #2357

Adds templateAsEl option to View

This allows the user to bypass the View’s el, tagName, className, attributes and use the template as the el.

Note that re-rendering will re-delegate events which is much more expensive than using the view’s el.

https://jsfiddle.net/9z76s1p1/2/

I'm not sure how much I really like this feature. It seems like it will have unwelcomed pref issues for little value.

What could be further addressed is delegating events on the document at which point #2967 will only get worse if not handled correctly. I've seen mixed opinions on globally delegated events and performance.

In any case, here it is to play with. If there is interested in seeing this to completion it'll need specs and docs. I'd also love to see perf tests to fully understand the hit calling delegateEvents for each render will have.

this allows the user to bypass the View’s `el`, `tagName`, `className`, `attributes` and use the template as the `el`.

Note that re-rendering will re-delgate events which is much more expensive than using the view’s `el`.
@rafde
Copy link
Member

rafde commented Nov 14, 2016

How will this work when the template produces nodes that aren't contained? Example:

<span>hi</span>
<span>there</span>

@paulfalgout
Copy link
Member Author

Only the first node of the template is used.

@rafde
Copy link
Member

rafde commented Nov 14, 2016

Most people are not going to expect. I am leaning on the no side to this because of the complications people will expect this to solve.
Too bad DOM API doesn't provide something like DOM array that you could bind events to without being part of the DOM.

@paulfalgout
Copy link
Member Author

Yep.. Besides overhauling backbone entirely I don't see this working with multiple nodes.. the getEl in Backbone uses $(el)[0]. I think trying support multiple nodes is a bad idea anyhow.

I've never been a big fan of this feature... that said I think this might be it's best shot? I dunno if there's anyone around who's still interested in seeing this. In the very least this and the issue could be closed and reopened later if someone needs it.

@paulfalgout paulfalgout mentioned this pull request Nov 14, 2016
'templateContext',
'triggers',
'ui'
];

const TEMPLATE_AS_EL = 'TEMPLATE_AS_EL';
Copy link
Member Author

Choose a reason for hiding this comment

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

if for some reason this PR does go through, we should look into changing this into a Symbol()

@blikblum
Copy link
Collaborator

The way i thought to overcome this limitation was with the aid of tooling. With a tool like vue-loader is possible to design the markup with a root el and the view class would be configured with the according properties.

It has some benefits:

  • One file with markup and code
  • No changes in core Mn and Backbone
  • Allow to use CSS modules / scoped CSS

and drawbacks:

  • One file with markup and code
  • Only can export a view per file
  • Tied to webpack
  • Another dev tool

@howardroark
Copy link

I like this @paulfalgout !

Choosing the first element in the template makes sense... React also chooses the first element if more than one is present. I think people get that a View is expecting a single element to work with. Maybe at first 50% assume a wrapper element is created, and the other 50% assume it grabs the first.

In terms of performance issue... do you think it would compare at all to DOM repaints?

@paulfalgout
Copy link
Member Author

I don't think it compares to DOM repaints, but I don't know that this helps with DOM repaints at all either.. so at the moment it only increase perf issues... I think. How much, I dunno.. would love someone to measure this somehow.

@howardroark
Copy link

I'm thinking that dom repaints will most likely be the thing that effects the "perceived performance" when rendering a lot. Not really directly related... but just kind of pointing out dealing with repaints will indirectly deal with this. :P

@scott-w
Copy link
Member

scott-w commented Dec 30, 2016

Regarding the multiple root nodes: is it relatively straightforward to detect this and raise an error?

@paulfalgout
Copy link
Member Author

paulfalgout commented Feb 14, 2017

@scott-w FWIW Backbone and Marionette already has this restriction without errors. The function causing the issue is in Backbone:

_setElement: function(el) {
  this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
  this.el = this.$el[0];  // <- Selects only the first element
},

It would not be impossible to handle multiple els I suppose, but it's definitely something you could run into now.

<ul>
  <li>This'll be the view</li>
  <li>This won't</li>
  <li>Or this</li>
</ul>
<script>
const MyView = Marionette.View.extend({
  el: 'li' 
});

const view = new MyView();

view.$el.text(); // This'll be the view
</script>

@paulfalgout
Copy link
Member Author

regarding multiple nodes.. this could always fallback to using the view el if the template's length !== 1

@scott-w
Copy link
Member

scott-w commented Mar 22, 2017

👍 on that

@JSteunou
Copy link
Contributor

I did not see this one. I like it a lot, working on bel + morphdom I had to put some work to bypass view.el and use only DOM from template string.

@paulfalgout
Copy link
Member Author

Ok so I believe this can be done pretty easily using the setRenderer interface. It'll be even easier in v4 when attachElContent doesn't get called if the renderer doesn't produce html.. Not sure we need to worry about this as an API option.

@paulfalgout paulfalgout closed this Sep 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants