How to choose an object from a nested model in a template

There are three approaches that jump to mind, at least to me… After typing this all out I think I prefer #3:

1. Use computed properties

on the controller/component OR on the models. This would work best for a finite and small set of predetermined/preordered groups. It also assumes there is only one group of each ‘code’ per document:

vitalSignsGroup: Ember.computed.filterBy('model.document.groups', 'code', 'vital_signs'),
patientIdGroup: Ember.computed.filterBy('model.document.groups', 'code', 'patient_id'),
//... etc. 

Then reference them in your template like:

<ul>
  <li>{{vitalSignsGroup.name}}<li>
  <ul>
    <li>{{input type="text" value=vitalSignsGroup.heart_rate}}</li>
    <li>{{input type="text" value=vitalSignsGroup.temperature}}</li>
  </ul>
...
</ul>

(You may need to do vitalSignsGroup.firstObject, or instead of using filterBy in the controller/component you could use a computed property to do the same thing but instead of returning an array just return the value, like return this.get('model.document.groups').findBy('code', 'vital_signs');, etc.)

Also you’d need to extrapolate for observations since you have multiple levels of the same basic problem, aka you need to reference the children by a code.

2. Write a custom helper

to use in your template, with an interface similar to what you wrote above. Actually because you’ll need block structure you may want to use components. This could get kinda verbose and messy though.

3. Use computed properties along with the “with” helper:

I’d actually put this computed property on your document model, and put a similar one on the group model (which collects the observations instead of the groups):

/* this would return an object of all your groups, keyed by the code, e.g.:
{
  vital_signs: <DS.Model Group>,
  patient_id: <DS.model Group>,
}
*/
codedGroups: Ember.computed('groups.@each.code', function(){
  return this.get('groups').reduce(function(collector, item){
    collector[item.get('code')] = item; 
    return collector;
  }, {});
}),

Then in your template:

{{#with model.document.codedGroups.vital_signs as |vitals|}}
  <li>{{vitals.name}}<li>
  <ul>
    <li>{{input type="text" value=vitals.codedObservations.heart_rate.value}}</li>
    ...
  </ul>
{{/with}}