简体   繁体   中英

Ember.js send action to controller of a 'belongsTo' associated model

I have a "children" template like this which is rendered with an array of "child" records:

{{#each}}
    {{render "parent.edit" parent}}
{{/each}}
<button {{action="submit"}}>Submit</button>

And a "parent.edit" template like this:

{{input type="text" value=parentProp}}

Basically what I want to have happen is that when the submit button is clicked, each "child" tells its parent model to save itself by sending an action to a ParentEditController, which does some stuff based on controller state and then triggers a model save (whose property is bound to the text input).

For the controllers and models I have:

App.Child = DS.model.extend({
    parent: DS.belongsTo('parent', {async: true})
});

App.Parent = DS.model.extend({
    parentProp: DS.attr('string')
});

App.ChildrenController = Ember.ArrayController.extend({
    itemController: 'child',
    actions: {
        submit: function() {
            //How can I send 'save' to each child.parent?
            this.forEach(function(item) {
                item.send('saveParent'); //Calls ChildController, which has a model
            });
        }
    }
});

App.ChildItemController = Ember.ObjectController.extend({
    needs: ['parentEdit'],
    actions: {
        saveParent: function() {
            //Here is the problem.  How do I get a non-singleton instance (has a model) of ParentItemController?
            this.get('controllers.parentEdit').send('doStuffThenSave'); //This sends to a singleton instance of the controller without a model.
            this.get('parent').send('doStuffThenSave'); //This sends to the model directly and does not hit any controller
        }
    }
});

App.ParentEditController = Ember.ObejctController.extend({
    actions: {
        doStuffThenSave: function() {
            //Here there is some code to do some stuff that is dependent on other controller properties before I save the model.
            this.get('model').save(); //should update 'parentProp' based on the input
        }
    }
});

As in the code comments, the issue is that if I try to reference ParentEditController with 'needs', then I get a singleton instance because the controller is set up with the model in the line {{render "parentItem" parent}} . ie, the way I understand it, 'needs' only gives you a controller with a model when the controller has been set up in the route or in a parent template somewhere. If I go straight to the model, then I don't have access to the controller. How can I have both?

In App.ChildItemController you should change

this.get('controllers.parentEdit').send('doStuffThenSave'); 
this.get('parent').send('doStuffThenSave');

to

this.get('controllers.parentEdit').send('doStuffThenSave', this.get('model').get('parent'));

and

doStuffThenSave: function() {...}

to

doStuffThenSave: function(<param-name>) {...}

since you aren't sending any context to the ParentEditController and no model is defined, then it is using a proxy model with no info. By sending the context and defining a param you are sending context(in this case a parent model of the child item) for parentEdit.doStuffThenSave to work with.

See Ember.Controller.send

You will also need to change

this.get('model').save();

to

<param-name>.save();

side point, don't forget to handle error/success with then() after the save!

Guide on emberjs.com

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM