3

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;
  }


});

2 Answers 2

6

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}}
Sign up to request clarification or add additional context in comments.

5 Comments

thanks so much for your detailed answer. I learned a lot just reading that response and I am tempted to accept it as true answer. However, when I try each ways I am getting <(unknown mixin):ember562> error in my template where I put the {{firstElement}} or {{model.firstObject}} respectively. It's most probably not your fault :) Here's my gist for the complete works.hbs just in case. I would appreciate any directions.
In the lazy way, do I have to make any changes to my route? Your 1) looks identical to how I return the array currently. Am I missing something? Thank you so much again.
your iterations look strange, I need to google how {{#liquid-with}} works
hey I made it work. apparently I had to do {{firstElement.name}} to get rid off the unknown mixin error. liquid-with is just liquid fire to bring animations really. Thanks so much!
TLDR; Just use .get('firstObject') when accessing ember data objects to get the first item of an array
2

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')
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.