简体   繁体   中英

Manipulating Ember Model in Component

To control the layout of a page, I'm attempting to pass a model to an Ember component and splicing it into groups. I can't figure out how without have to access content._data and essentially recreating the model. The rough code:

parentRoute.js

export default Ember.Route.extend({
  model() {
    return this.store.findAll('item');
  }
});

parentRoute.hbs

 {{ wall model=model }}

childComponent.js

export default Ember.Component.extend({
    groupedItems: Ember.computed(function() {
        // convert model data into array of objects
        let allItemss = this.get('model.content').map(function(obj){
            let mappedObj = obj._data;
            mappedObj.id = obj.id;
            return mappedObj;
        });

        // group into arrays of up to 3 for layout
        let groupedItems = [];
        while(allItems.length){
            groupedItems.push(allItems.splice(0,3));
        }

        return groupedItems;
    })
});

childComponent.hbs

{{#each groupedItems as |items|}}
        {{#each items as |item|}}
        <div class="item-group-{{items.length}}">
            <h2 class="headliner">
                {{ item.id }} {{ item.name }}
            </h2>
        </div>
        {{/each}}
{{/each}}

Is there a better way to do this? I can't seem to get .then() to work with this.get('model') , and the item itself can't be spliced as it's an object, not an array.

You should be able to access the model directly, because the model hook will resolve the "findAll" before rendering the page. Also your computed property should to refer to the 'model', otherwise it wont recompute when the model changes. Like this:

  groupedItems: Ember.computed('model', function() {
    // convert model data into array of objects.
    let allItems = this.get('model').map((item) => {
      return item;
    });
    let result = [];
    while (allItems.length) {
      result.push(allItems.splice(0, 3));
    }
    return result;
  })

As you can see, you can use this.get('model') which I actually an ember array-like object you can do array operations on. The only thing is you can't use splice on it, so you have to convert it to a regular array format.

Or you could use ember "slice" method, and do this

  groupedItems: Ember.computed('model', function() {
    let pos = 0;
    let result = [];
    while (pos < this.get('model.length')) {
      result.push(this.get('model').slice(pos, pos + 3));
      pos += 3;
    }
    return result;
  })

I have added an ember-twiddle here for manipultaing ember model in component and group the items by length 3 .

https://ember-twiddle.com/f425ce4b7aa48529b9d7e00878e5e4db?openFiles=routes.index.js%2Ctemplates.components.wall-page.hbs .

In component the ember computed property is as follows.

import Ember from 'ember';

export default Ember.Component.extend({

  groupedItems: function() {
    let groupedItems = []
    ,   t = this
    ,   length  = this.get('alphaList.length') - 1
    ,   lastVal = length / 3;

    let allItems = this.get('alphaList').map(function(obj, index){
        if (index !== 0 && index % 3 === 0) {
          var otherArray = []; 
          for (var x = index-3; x<= index-1; x++ ) {
            otherArray.push(t.get('alphaList')[x]);
          }
          groupedItems.push(otherArray);
        }
    });

    if (length > 0) {
       var lastArray = [];
       for (var x = 3 * parseInt(lastVal); x<= length; x++ ) {
         lastArray.push(t.get('alphaList')[x]);
       }
       groupedItems.push(lastArray);
    }
    return groupedItems;
  }.property('alphaList')
});

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