ilteris
ilteris

Reputation: 457

return first element from array as computed property from Ember controller subclass

I am trying to return the first element of my array as a computed property to my template from my controller. My code is below. I am 100% about my array and template. Problem is my syntax about in the controller. Basically my array is works made of Work objects. And I would ideally return the first element Work. Is that even possible in javascript?

Best.

//controller works.js

import Ember from "ember";
  export default Ember.Controller.extend({
  firstElement: function () {
    var arr = this.get('model');
    return arr[0];
    console.log(arr[0]);
  }.property('Work')
});

//template works.js

<div class="right">
  {{#liquid-with model as |currentModel|}}
    {{firstElement}}
  {{/liquid-with}}
</div>

//route works.js

import Ember from 'ember';

var Work = Ember.Object.extend({
  name: '',
  year: '',
  description:'',
  image:'',
  logo:'',

  work_id: function() {
    return this.get('name').dasherize();
  }.property('name'),


});

var minibook = Work.create({
  id: 1,
  name: 'MINIBOOK',
  year: '2014',
  description:'MiniBook is an iphone app that explores storytelling in its own format. The format',
  image:'assets/images/minibook_iphone.png',
  logo:'assets/images/minibook_logo.png'
});

var poetics = Work.create({
  id: 2,
  name: 'POETICS',
  year: '2013',
  description:'Lorem Ipsum Poetics',
  image:'assets/images/poetics_iphone.png',
  logo:'assets/images/poetics_logo.png'
});


var WorksCollection = Ember.ArrayProxy.extend(Ember.SortableMixin, {
  sortProperties: ['id'],
  sortAscending: true,
  content: []
 });


var works = WorksCollection.create();

works.pushObjects([poetics, minibook]);


export default Ember.Route.extend({
  model: function() {
    return works;
  }


});

Upvotes: 3

Views: 6950

Answers (2)

snewcomer
snewcomer

Reputation: 2135

A bit more updated (or different) example

import Controller from '@ember/controller';
import { readOnly } from '@ember/object/computed';

export default Controller.extend({
  firstElement: readOnly('model.firstObject')
});

Or if you want bidirectional data flow (can set firstElement)

import Controller from '@ember/controller';
import { alias } from '@ember/object/computed';

export default Controller.extend({
  firstElement: alias('model.firstObject')
});

Upvotes: 2

artych
artych

Reputation: 3669

This would work.

Long way (just to improve your computed property code):

// controller work.js
import Ember from "ember";
export default Ember.Controller.extend({
  firstElement: function () {
    return this.get('model').get('firstObject'); // or this.get('model.firstObject'); 
  }.property('model.[]')
});

1) you set works as model in route, so you could get it as model in controller

2) .property(model.[]) means computed property on array, so adding and deleting array element will fire update. You could also choose some specific property i.e. .property([email protected])

3) fistObject is proper method (not [0]), since you are working with Ember.ArrayProxy, see http://emberjs.com/api/classes/Ember.ArrayProxy.html

4) you could use {{firstElement}} in template

Lazy way:

1) set model in route as array or as promise resolved in array

// works = ... as is
export default Ember.Route.extend({
  model: function() {
    return works;
  }
});

2) get model.firstObject in directly in template

//template works
{{model.firstObject}} {{!-- first object of model array --}}
{{model.firstObject.name}}  {{!-- name of first object --}}

UPDATE: use proper iteration syntax http://ef4.github.io/liquid-fire/#/helpers/liquid-with/10

{{#liquid-with model as currentModel}}
  {{currentModel.firstObject.name}}
{{/liquid-with}}

Upvotes: 6

Related Questions