Skip to content

Instantly share code, notes, and snippets.

@stefanpenner
Last active December 17, 2015 14:49
Show Gist options
  • Save stefanpenner/5627411 to your computer and use it in GitHub Desktop.
Save stefanpenner/5627411 to your computer and use it in GitHub Desktop.

This document aims to help aggregate issues and solutions around the defaultContainer deprecation.

The Error Message:

Using the defaultContainer is no longer supported. [defaultContainer#lookup]

breaux, where's my defaultContainer?

Well it is still there, and will continue to work for some time. Likely it will be gone by 1.0.0 final

Why is this happening.

We recieved several issues, these issues were non-obvious but it appeared that they where caused by the defaultContainer leaking between tests. This obviously lead to very unexpected test failures. The quick fix was obviously to ensure the defaultContainer was purged between tests. Upon further investigation, almost all the issues turned out to be childViews which were not wired up correctly. For example not using this.createChildView on creation of childViews. Ultimately, the existence of the defaultContainer was masking the reported issues, and likely many more. In addition the obvious issues, we are trying to remove our dependency on globals (but that is another story).

migration paths: (WIP)

if you are creating dynamic views in the context of the parentView, you should be using:

this.createChildView(viewClass, viewAttributes)

if you are creating views outside the context of a parentView (this may not be recommended, but it is happening) you will want to make sure to instantiate your view via the container itself.

this.container.lookup('view:apple')
// will provide a instance of apple view.

how container lookups are resolved

Action items

  • appendTo another ember view, should then grab the container of that view.
  • continue to flush out this gist
  • improve docs/guides
  • improve deprecation warnings
  • explore methods where this works without developer thought (without perf regressions)

fixes in the wild:

But I have a legitmate usecase not expressed here.

Post a comment, describing the issue, and hopefully a jsbin or jsfiddle demonstrating the issue. As time permits, a solution or migration path will finds its way up into this document.

Q/A

Q: can we not have views get a container by default? The App gets a container right?

A: App is the root, and as such it creates the initial container.

Q: So when I do createChildView, which container is that using?

A: typically, it is using the container passed down the view hierarchy, and this typically occurs at creation.

Q: Could we set the container when you append it to a container view's childViews array?

A: likely, but its not just the container, it is a place for the framework to wire-up other things. https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/view.js#L2072

(ask questions in the comments and I will hoist them here.)

@knownasilya
Copy link

@dlpatri thanks for clarifying that. Is it possible to pass a hash to the lookup? I just used setters after the fact, which works as well.

@leonelag
Copy link

@stefanpenner Care to update the Views guide at http://emberjs.com/guides/views/defining-a-view/ ?
As an Ember noob, on my first 20 minutes following it, I have just been bitten by this commit.

@mayatskiy
Copy link

@velesin
Copy link

velesin commented Nov 12, 2013

@stefanpenner "you merely need to create a container per unit test, and ensure [...] the template can be fetched from the container". Can you provide some example how this should be correctly configured? Right now in my tests I'm using (probably not correct) hack:

Ember.View.create({ container: App.__container__ });

From your comment I understood that I should be creating a new, isolated container instance for my tests (plus configure it somehow so the template can be fetched from it) - but I have no idea what is the correct way to do this?

@stefanpenner
Copy link
Author

@velesin

container.register('view:foo', FooView , { singleton true });
container.lookup('view:foo') // instance of theview

@jmorvan
Copy link

jmorvan commented Jan 7, 2014

How should I proceed in the case where I am creating dynamic view from a loop:

switch (itm.type) {
            case "Page":
                view = Ember.ContainerView.create({classNames: itm.options.class, elementId: itm.id});
                break;
            case "Row":
                view = Ember.ContainerView.create({classNames: itm.options.class, elementId: itm.id});
                break;
            case "Container":
                view = Ember.ContainerView.create({classNames: itm.options.class, elementId: itm.options.id});
                break;
}

Am I doing this wrong by extending views in this manner?

I could potentially have dozens of different itm.type and I would like to avoid having to explicitly declare a class for each.

@H1D
Copy link

H1D commented Apr 3, 2014

Here is the setup I'm using:


post_view = container = null
module "Post View",
  setup: ->
    container = new Em.Container
    container.optionsForType 'template', { instantiate: false }
    container.register 'template:post', Ember.Handlebars.compile('{{text}}')

    post_view = App.PostView.create(context: {text:'foo'}, container: container)
    Em.run ->
      post_view.createElement()
      post_view.set 'context', step
  teardown: ->
    Ember.run ->
      post_view.destroy()
      container.destroy()

test "renders 'text' property", 1, ->
  equal post_view.$().text(), 'foo', 'rendered text doesn\'t match context'

Note container.optionsForType, otherwise ember will try to call create() on template (i.e. instantiate). Also I was surprised that Em.Container is probably the only object you have to instantiate using new

@happycollision
Copy link

I changed a bit of my code based on a suggestion by @pixelchild for @nightire to no avail:

App.SomeRoute = Ember.Route.extend({
    someFunction: function(){
        App.myViewHolder = App.MyView.create({container: this.container});
        App.myViewHolder.append();
    }
});

I am still getting this deprecation warning when someFunction is called. 😕

All I really want to do is append a couple elements to the DOM when I am in a certain route.

Update: Seems that it was actually a run loop issue. I was changing my target to window by mistake.

@tachang
Copy link

tachang commented Jun 30, 2014

I'm lost.

window.Application = Ember.Application.create();

var view = Ember.View.create({
templateName: 'info',
name: "Bob"
});
view.appendTo(''#info');

I do this and get this warning. But this is from the docs: http://emberjs.com/guides/views/defining-a-view/

Copy link

ghost commented Jul 7, 2014

Please update the guide.

@stefanpenner
Copy link
Author

@hannicolas im unsure what needs to be updated?

@richardkmichael
Copy link

@stefanpenner The example in the guide poses problems for newcomers (me). I can't tell you what it should say (because I'm just learning Ember), but as @tachang also mentions, I expected (something like the guide's example):

<!-- index.html -->
...
<head>
  <!-- Other script tags for Ember itself and dependencies omitted. -->
  <script type="x-handlebars" data-template-name="foo-view-template">
    Hello, World! from foo view
  </script>
  <script src="myapp.js"></script>
</head>
// myapp.js -- only this content, nothing else.

var app = Ember.Application.create();  // Is this even necessary?

var fooView = Ember.View.create({
  templateName: "foo-view-template"
});

fooView.append();

.. to display a page containing:

<body>
  <!-- Possibly other stuff in index.html, followed by... -->
  Hello World! from foo view
</body>

.. but instead the console prints (the git.io link points to this gist):

Uncaught Error: Container was not found when looking up a views template. This is most likely due to manually instantiating an Ember.View. See: http://git.io/EKPpnA

@supairish
Copy link

@richardkmichael I'm having the same problem, did you find a fix?

@jmdfm
Copy link

jmdfm commented Sep 7, 2014

@richardkmichael @supairish @stefanpenner I've found that changing from .create to .extend from making new view for insertion prevents the deprecation warning from being triggered when you set a templateName. YMMV.

@avaz
Copy link

avaz commented Oct 26, 2014

The docs of Route.loading event is showing an example of the old way: [http://emberjs.com/api/classes/Ember.Route.html#event_loading]
How this would be with the this.container.lookup strategy? I mean, what is the best way to pass the 'classNames' is the example in the Route.loading of create and append views?
I'm willing to update the docs but I'm don't know for what put in the example.

@markmilman
Copy link

I'm trying to use Ember component in an existing rails app as part of gradually migrating the view layer created by rails to Ember and form a single page app.
I have used the following code, which works in 1.5.0 but throws the deprecation warning (and therefore breaks in 1.8) . Will appreciate any help to get this working in 1.8.0:

Sbcx.MaterialsListComponent = Ember.Component.extend({
  layoutName: 'components/materials-list'
  materialList: null

  actions: {
    remove: (m)->
      console.log('removed ' + m.get('name'))
      m.destroyRecord()
  }
})


$(document).ready ->

  Sbcx.store.find("material").then (result) ->
    $(".component-placeholder").each ->
      # Build the component & stuff in any pre-existing value
      component = Sbcx.MaterialsListComponent.create(materialList: result)

      # Gut out the container div & replace with the component
      component.replaceIn this

@yanni4night
Copy link

This is really confused,I am going to skip this page guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment