Route not seeing URL slug


#1

Crosspost from SO: http://stackoverflow.com/questions/25331816/route-not-seeing-url-slug

I have an app that allows management of orders. The default view is a split view with orders on the left and selected order details on the right like so:

  /Orders           /Orders/:order_id
|---------------| |----------------------------------------|
|               | |                                        |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|    List of    | |            Selected Item               |
|     Items     | |               Details                  |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|               | |                                        |
|---------------| |----------------------------------------|

I’d like to be able to edit an order in “full-screen” mode so that the URL and template looks like this:

  /Orders/:order_id/edit/
|----------------------------------------------------|
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|            Order Edit Interface                    |
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|                                                    |
|----------------------------------------------------|

My routes are currently setup as follows:

this.resource('Orders.edit', { path: 'Orders/:order_id/edit' } , function () {
	this.route('customer-details');
	this.route('vendor-details');
	this.route('shipping-details');
}

this.resource('Orders', { path: 'Orders' }, function () {
	this.resource('Order', { path: ':order_id' }, function () {
		this.route('customer-details');
		this.route('vendor-details');
		this.route('shipping-details');
	}
}

And my order routes look like this:

// Orders Route
App.OrdersRoute = Em.Route.extend({
    model: function() {
        return this.store.find('order');
    },

    afterModel: function (orders) {
        this.transitionTo('orders.order', orders.get('firstObject') );
    }
});

// Order Detail
App.OrdersOrderRoute = Em.Route.extend({
    model: function(params) {
        return this.store.find('order', params.order);
    },

    setupController: function (controller, model) {
        controller.set('content', model);
    }
});

// Order Edit Route
App.OrdersEditRoute = Em.Route.extend({
    model: function(params) {
        if (typeof params.order_id !== 'undefined') {
            this.store.find('order', params.order_id).then(function (order) {
                this.controllerFor('orders.edit').set('content', order);
            });
        } else if (typeof params.order !== 'undefined') {
            this.store.find('order', params.order).then(function (order) {
                this.controllerFor('orders.edit').set('content', order);
            });
        }
    },

    afterModel: function(eo) {
        this.transitionTo('orders.edit.customer-details', order);
    }
});

// Order Edit - Customer Details Route
App.OrdersEditCustomerDetailsRoute = Em.Route.extend({
    model: function() {
        try {
            var order = this.get('order');
            return order;

        } catch (e) {
            console.log('ERROR: ' + e);
        }
    },

    beforeModel: function() {
        this.set('order', this.modelFor('orders.edit'));
    },
});

This setup works if I’m in the Orders/:order_id route/template and click the edit button which then sends me to Orders/:order_id/edit with the desired interface and data loaded. But if I try to refresh Orders/:order_id/edit in the browser window nothing loads and I get the following errors. I also don’t hit any breakpoints set inside of the Orders/:order_id/edit route when accessing the URL this way.

Uncaught Error: Assertion Failed: Cannot delegate set('classification', N/A) to the 'content' property of object proxy <Synapse.EngineeringOrdersEditDetailsController:ember1242>: its 'content' is undefined. libs.js:2870
    Ember.assert libs.js:2870
    EmberObject.extend.setUnknownProperty libs.js:23933
    set libs.js:9229
    setPath libs.js:9289
    set libs.js:9209
    trySet libs.js:9306
    (anonymous function) libs.js:3416
    tryable libs.js:5964
    tryFinally libs.js:10524
    suspendListener libs.js:5967
    _suspendObserver libs.js:8311
    Binding._sync libs.js:3415
    DeferredActionQueues.invoke libs.js:11346
    DeferredActionQueues.flush libs.js:11398
    Backburner.end libs.js:10861
    Backburner.run libs.js:10916
    apply libs.js:10745
    run libs.js:9378
    runInitialize libs.js:45596
    n.Callbacks.j libs.js:2
    n.Callbacks.k.fireWith libs.js:2
    n.extend.ready libs.js:2
    I libs.js:2

TypeError: undefined is not a function
        at http://localhost:1337/js/app.js:27936:22
        at invokeCallback (http://localhost:1337/js/libs.js:13310:19)
        at publish (http://localhost:1337/js/libs.js:12980:9)
        at publishFulfillment (http://localhost:1337/js/libs.js:13400:7)
        at http://localhost:1337/js/libs.js:18818:9
        at DeferredActionQueues.invoke (http://localhost:1337/js/libs.js:11348:18)
        at Object.DeferredActionQueues.flush (http://localhost:1337/js/libs.js:11398:15)
        at Object.Backburner.end (http://localhost:1337/js/libs.js:10861:27)
        at Object.Backburner.run (http://localhost:1337/js/libs.js:10916:20)
        at executeTimers (http://localhost:1337/js/libs.js:11241:12) libs.js:6663
    logToConsole libs.js:6663
    RSVP.onerrorDefault libs.js:49435
    __exports__.default.trigger libs.js:12274
    Promise._onerror libs.js:12998
    publishRejection libs.js:13405
    (anonymous function) libs.js:18818
    DeferredActionQueues.invoke libs.js:11348
    DeferredActionQueues.flush libs.js:11398
    Backburner.end libs.js:10861
    Backburner.run libs.js:10916
    executeTimers libs.js:11241
    (anonymous function) libs.js:11231

Uncaught Error: Assertion Failed: TypeError: undefined is not a function libs.js:2870
    Ember.assert libs.js:2870
    RSVP.onerrorDefault libs.js:49436
    __exports__.default.trigger libs.js:12274
    Promise._onerror libs.js:12998
    publishRejection libs.js:13405
    (anonymous function) libs.js:18818
    DeferredActionQueues.invoke libs.js:11348
    DeferredActionQueues.flush libs.js:11398
    Backburner.end libs.js:10861
    Backburner.run libs.js:10916
    executeTimers libs.js:11241
    (anonymous function)

I suspect it has something to do with having the Orders/order/edit route outside the hierarchy of the Orders resource but I was unable to get the outlets to play nicely to render the desired interface.

TLDR - How do I get the Orders/:order_id/edit to load the model properly from the URL slug? Using Ember 1.6.1 and Ember-data Fixture Adapter


#2

Not quite sure if it’s the case. But remember to take the scope into consideration when working with functions.

This:

// Order Edit Route
App.OrdersEditRoute = Em.Route.extend({
    model: function(params) {
        if (typeof params.order_id !== 'undefined') {
            this.store.find('order', params.order_id).then(function (order) {
                this.controllerFor('orders.edit').set('content', order);
            });
        } else if (typeof params.order !== 'undefined') {
            this.store.find('order', params.order).then(function (order) {
                this.controllerFor('orders.edit').set('content', order);
            });
        }
    },
});

Should be:

// Order Edit Route
App.OrdersEditRoute = Em.Route.extend({
    model: function(params) {
        var _this = this;
        if (typeof params.order_id !== 'undefined') {
            _this.store.find('order', params.order_id).then(function (order) {
                _this.controllerFor('orders.edit').set('content', order);
            });
        } else if (typeof params.order !== 'undefined') {
            _this.store.find('order', params.order).then(function (order) {
                _this.controllerFor('orders.edit').set('content', order);
            });
        }
    },
});