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

A more flexible way to append Ember.View to DOM? #587

Closed
radicaled opened this issue Mar 13, 2012 · 20 comments
Closed

A more flexible way to append Ember.View to DOM? #587

radicaled opened this issue Mar 13, 2012 · 20 comments

Comments

@radicaled
Copy link

So I got some code that looks like this:

App.Controllers.albumList.setup().done(function() {
  var view = App.Views.ControlPanel.AlbumList.create();
  // Copied from internal method on Ember.View
  view._insertElementLater(function() {
    if (this.get(this, 'isVisible') === null) {
      this.set(this, 'isVisible', true);
    }
    this.$().prependTo("#albums");
  });
});

For some boring background, App.Controllers.albumList.setup() loads some JSON via XHR asynchronously, and returns a jQuery Deferred object so that when the data is populated we know when to create the view that consumes that data.

Anyway, in this situation the DOM element that gets created has to be prepended, not appended, to another DOM element. There's no method on Ember.View for this.

So after a little scrounging through the Ember.View source I realized I have to copy and paste some internal body logic, because appendTo does the whole get and set thing for isVisible -- and since I'm not sure what that does, I've copied the content body of Ember.View.appendTo and am erring on the side of caution here.

I'm using _insertElementLater because App.Views.ControlPanel.AlbumList uses willInsertElement and didInsertElement to do some fancy processing and setup before and after the element is inserted.

Ideally I'd like not to have to copy the method body of Ember.View.appendTo several times, since I don't want to fall out of sync when I update ember.js, so it'd be nice if there was a better way of prepending/appending/whatevering an element into the DOM:

App.Controllers.albumList.setup().done(function() {
  var view = App.Views.ControlPanel.AlbumList.create();

  view.appendElementLater().done(function() {
    this.$().prependTo("#albums");
  });
});

Or, am I just going about this the wrong way?

@wagenet
Copy link
Member

wagenet commented Mar 13, 2012

Why not create the view in advance with bindings and just toggle is visible when the data is ready?

@radicaled
Copy link
Author

As for why I'm creating the view after the XHR request, I'm dealing with a large and somewhat buggy 3rd party script: if the element is inserted but is empty, then the 3rd party script kind of craps out on didInsertElement, so I need to make sure that the object bindings in App.Controllers.albumList have been populated for App.Views.ControlPanel.AlbumList first.

But that's just a little aside, really this issue is about me needing to prepend the Ember.View, and not wanting to cargo cult the body of appendTo in case it changes in the future.

@stas
Copy link

stas commented Mar 13, 2012

@wagenet is right.
You can add an observer for your binding (that can be a property/method or something telling you if data is loaded) to the method you want to prepend the view.

@radicaled
Copy link
Author

An observer would fire every time the binding changes -- I just need a one-shot for the initial data load.

Anyway, this issue is about me needing Ember.View.prependTo or something similar.

@wagenet
Copy link
Member

wagenet commented Mar 14, 2012

Ember.View#appendTo is pretty simple, prependTo would essentially be the same: https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/view.js#L639-647

@pangratz
Copy link
Member

This issue is related to #574. Should I add a prependTo to my Pull Request?

@radicaled
Copy link
Author

That'd be a pretty cool thing to do. :)

@wagenet
Copy link
Member

wagenet commented Apr 17, 2012

Closing in favor of #627.

@wagenet wagenet closed this as completed Apr 17, 2012
@wagenet
Copy link
Member

wagenet commented Apr 23, 2012

@radicaled After thinking about this more, I don't think you should be using DOM insertion anyway. This is what ContainerView is designed for.

@radicaled
Copy link
Author

Is the purpose of EmberJS to have all HTML elements encapsulated within a JavaScript backed view? I was under the impression I could freely mix-match freestanding HTML with EmberJS-backed HTML views together freely, but this and #627 implies we're not supposed to do that.

@wagenet
Copy link
Member

wagenet commented Apr 23, 2012

In general, you want one parent view for each app, though there may be exceptions. There's no harm in putting HTML into that parent view that Ember doesn't directly control, just make sure you aren't trying to control the same stuff both from Ember and from elsewhere at the same time.

@wagenet
Copy link
Member

wagenet commented Apr 23, 2012

If you tell me a bit more about your app I may be able to help clarify things.

@radicaled
Copy link
Author

I have a regular, garden variety CMS that is using EmberJS to drive some of the more app-like bits -- using it to control the behavior of a "media player" widget is one of the things its doing.

In the context of this ticket, I needed the functionality to prepend this widget to an existing HTML structure, and be notified when the element was rendered so I could run some 3rd party JS that only worked right with visible elements. I didn't want to cargo cult the method definition of view.append everywhere I wanted to do a view.prepend or a view.after or a view.before, etc.

@wagenet
Copy link
Member

wagenet commented Apr 23, 2012

@radicaled Have you seen Ember.View#didInsertElement?

@radicaled
Copy link
Author

@wagenet Are you proposing that I Ember.View#append somewhere, then on the Ember.View#didInsertElement callback I should move the element with jQuery's regular prepend function?

@wagenet
Copy link
Member

wagenet commented Apr 24, 2012

No. You said you depend on 3rd party JS that needs visible elements. I was suggesting you make an Ember.View with the right HTML and then trigger the 3rd party JS on didInsertElement.

@radicaled
Copy link
Author

Whoops! My bad.

@wagenet
Copy link
Member

wagenet commented Apr 24, 2012

@radicaled Does this work for your case? I want to make sure you have a good solution to this.

@radicaled
Copy link
Author

I think so. Just one quick question related:

<div id='music-player-container'>
<!-- Need to insert App.View.PlayerControls here -->
<div id='progress-bar'> ... </div>
<div id='outer-shell'> ... </div>
</div>

Assuming I can't change the structure of the markup, and I don't want to wrap music-player-container in its own Ember.View, is this the right way to append the element?

view = App.View.PlayerControls.create()
view._insertElementLater(function() { this.$().prependTo('#music-player-container'); });

@pangratz
Copy link
Member

I haven't come up with a use case for #627 yet but this would be one ...

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

4 participants