0

I started going down the road of having a route that returns a collection of different models (i.e. collection contains App.Person, App.Place, App.Thing, etc.) I have been able to deal with this by providing a generic view that renders the appropriate template based on the context. Here is the basic idea:

    App.SearchView = Ember.View.extend({

        templateName:function(){
            var item = this.get('context');// get the model
            var itemName = item.constructor.toString();// get the type

            if(itemName == "App.Person"){
                return "personTemplate";// this is the name of the template
            }
            if(itemName == "App.Place"){
                return "placeTemplate";
            }
        }.property().cacheable()


    }

Is this the right thing to do with a collection that includes multiple model types? Or should I be using a different collection or technique?

Ben
  • 37
  • 1
  • 1
  • 4

1 Answers1

1

When I have multiple models, here is the approach I take.

RSVP, Ember's promise library lets you return a hash of promises. The model hook will not return until all promises have been fulfilled. If one of the properties on the hash doesn't return a promise (ie just returns a value right away), everything still works fine.

model: function(){
    Ember.RSVP.hash({
        person: getPersonLogic,
        place: getPlaceLogic,
        thing: getThingLogic
    });
}

Then in your template:

{{render 'personTemplate' model.person}}
{{render 'placeTemplate' model.place}}
{{render 'thingTemplate' model.thing}}

If you only want to display one at a time:

//route
renderTemplate: function(controller,model){
    this.render();
    //render person by default
    this.render("personTemplate", {outlet: "named", into: "routeThatContainsOutlet", model: model.person})
},
actions: {
    showPerson: function(){
        this.render("personTemplate", {outlet: "named", into: "routeThatContainsOutlet", model: model.person})
    },
    showPlace: function(){
        this.render("placeTemplate", {outlet: "named", into: "routeThatContainsOutlet", model: model.place})
    },
    showThing: function(){
        this.render("thingTemplate", {outlet: "named", into: "routeThatContainsOutlet", model: model.thing})
    }
}

In your template:

<button {{action showPerson}}>Show Person</button>
<button {{action showPlace}}>Show Place</button>
<button {{action showThing}}>Show Thing</button>
{{outlet named}}

It's unclear your actual use case, but this should nudge you in the right direction

mistahenry
  • 8,554
  • 3
  • 27
  • 38
  • I think I understand and thanks for the answer. I will have to dig a little deeper into the RSVP promise hash to make sure I understand that. Does your getPersonLogic return a promise itself? Maybe an App.Person.find() call? – Ben Aug 22 '14 at 15:24
  • Yeah if you are using Ember data, the find method will return a promise. In that case, getPersonLogic would be a find call on your data store. I don't use Ember data for various reasons, so I make .getJSON calls that also return promises. Hence getPersonLogic because I wasn't sure what your logic for getting the data is – mistahenry Aug 22 '14 at 15:44