9

I'm trying to get familiar with dynamic segment here. Here is what I want to achieve:

When i access '/#/inventories', it will list the inventory model in the 'inventories' template. This is done successfully.

When i click on the individual inventory id, it will access /#/inventories/1 be 1 is the inventory id, and it will fire up the 'inventory' template. This is done successfully as well.

However when i try to access /#/inventories/1 directly from the address bar, when i press F5, it comes out this error - Error while loading route: TypeError {}

The full list of error:

Uncaught TypeError: Object function () {
    if (!wasApplied) {
      Class.proto(); // prepare prototype...
    }
    o_defineProperty(this, GUID_KEY, undefinedDescriptor);
    o_defineProperty(this, '_super', undefinedDescriptor);
    var m = meta(this);
    m.proto = this;
    if (initMixins) {
      // capture locally so we can clear the closed over variable
      var mixins = initMixins;
      initMixins = null;
      this.reopen.apply(this, mixins);
    }
    if (initProperties) {
      // capture locally so we can clear the closed over variable
      var props = initProperties;
      initProperties = null;

      var concatenatedProperties = this.concatenatedProperties;

      for (var i = 0, l = props.length; i < l; i++) {
        var properties = props[i];

        Ember.assert("Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.", !(properties instanceof Ember.Mixin));

        for (var keyName in properties) {
          if (!properties.hasOwnProperty(keyName)) { continue; }

          var value = properties[keyName],
              IS_BINDING = Ember.IS_BINDING;

          if (IS_BINDING.test(keyName)) {
            var bindings = m.bindings;
            if (!bindings) {
              bindings = m.bindings = {};
            } else if (!m.hasOwnProperty('bindings')) {
              bindings = m.bindings = o_create(m.bindings);
            }
            bindings[keyName] = value;
          }

          var desc = m.descs[keyName];

          Ember.assert("Ember.Object.create no longer supports defining computed properties.", !(value instanceof Ember.ComputedProperty));
          Ember.assert("Ember.Object.create no longer supports defining methods that call _super.", !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));

          if (concatenatedProperties && indexOf(concatenatedProperties, keyName) >= 0) {
            var baseValue = this[keyName];

            if (baseValue) {
              if ('function' === typeof baseValue.concat) {
                value = baseValue.concat(value);
              } else {
                value = Ember.makeArray(baseValue).concat(value);
              }
            } else {
              value = Ember.makeArray(value);
            }
          }

          if (desc) {
            desc.set(this, keyName, value);
          } else {
            if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
              this.setUnknownProperty(keyName, value);
            } else if (MANDATORY_SETTER) {
              Ember.defineProperty(this, keyName, null, value); // setup mandatory setter
            } else {
              this[keyName] = value;
            }
          }
        }
      }
    }
    finishPartial(this, m);
    delete m.proto;
    finishChains(this);
    this.init.apply(this, arguments);
} has no method 'find' 

Here is my app.js:

Gymi = Ember.Application.create();

// Route map
Gymi.Router.map(function() {
    this.resource('inventories', { path: '/inventories' }, function() {
        this.resource('inventory', { path: '/:inventory_id' });
    });
    this.resource('products');
});

// inventory models
Gymi.Inventory = Ember.Object.extend();
Gymi.Inventory.reopenClass({
    items: [],
    all: function() {
        this.items = [{
            id: 1,
            name: 'item1',
            cost: '20.00',
            qty: 10
        }, {
            id: 2,
            name: 'item2',
            cost: '20.00',
            qty: 10
        }, {
            id: 3,
            name: 'item3',
            cost: '20.00',
            qty: 10
        }, {
            id: 4,
            name: 'item4',
            cost: '20.00',
            qty: 10
        }];

        return this.items;
    }
})

// inventory controller
Gymi.InventoriesController = Ember.Controller.extend({
    inventories: Gymi.Inventory.all()
});

Here is the templates:

<script type="text/x-handlebars">
<h2>{{title}}</h2>

<ul>
    <li>{{#linkTo 'inventories'}}Inventories{{/linkTo}}</li>
</ul>

{{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="inventories">
<h2>Inventory</h2>

<table class="table">
<tbody>
{{#each inventory in inventories}}
    {{#with inventory}}
    <tr>
    <td>{{#linkTo 'inventory' inventory}}{{id}}{{/linkTo}}</td>
    <td>{{name}}</td>
    <td>{{cost}}</td>
    <td>{{qty}}</td>
    </tr>
    {{/with}}
{{/each}}
</tbody>
</table>

{{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="inventory">
<h4>Inventory</h4>

<ul>
    <li>{{id}}</li>
    <li>{{name}}</li>
    <li>{{cost}}</li>
    <li>{{qty}}</li>
</ul>
</script>
4

3 回答 3

14

Not an answer to the OP but to all those who are getting the error after Sept 1, 2013, it might be due to the update of Ember Data to the latest 1.0 version. So you have to use

this.store.find('model');

Instead of

App.Model.find();

Read more changes here.

于 2013-09-04T18:11:45.467 回答
2

That's an unhelpful error message, but the key part is at the end of it.

    this.init.apply(this, arguments);
} has no method 'find'

When you visit the /inventories/1 route, ember will try to lookup the record for that id, using find, in the InventoryRoute's model hook. In this case on the Inventory. Since it can't find that method you get this error.

Adding an Inventory.find method that returns the record matching params.inventory_id will fix this issue.

于 2013-06-28T13:49:22.093 回答
1

This error appears if your route is missing the parameter of the model method.

The following code works when visiting /inventory/1 from a link-to but not opening the page from the URL:

App.InventoryRoute = Ember.Route.extend({
  model: function() {
    this.store.find('inventory', params.inventory_id)
  }
});

Adding the missing params fixes. This code works both from a link-to and directly from the URL:

App.InventoryRoute = Ember.Route.extend({
  model: function(params) {
    this.store.find('inventory', params.inventory_id)
  }
});

For ember-data < 0.14 this is the code

App.InventoryRoute = Ember.Route.extend({
  model: function(params) {
    App.Inventory.find(params.inventory_id)
  }
});
于 2014-03-09T23:27:23.540 回答