zakmac / ember-cli-filter-component

A simple Ember.js component used to filter an array based on user input.
MIT License
14 stars 4 forks source link

Support for Ember model in addition to arrays #6

Closed manuel-reil closed 9 years ago

manuel-reil commented 9 years ago

Hi,

I was able to replicate the airports example (plain array) easily - great. However, when I try to hand over the model from the route or an Ember.ArrayProxy, it does not show any results whether I query or not.

  1. The first error I detected was in contentComputed as isEmberObj is not defined/implemented: if (this.isEmberObj(content)) {

I commented this out temporarily. Then no errors show up.

  1. As next step I verified that model is of type instance. So the following if clause is entered `} else if (type === 'instance') {``
  2. Then I tried to verify if the content gets "handed over".

           var content = !Ember.isNone(this.get('content')) ? this.get('content') : [];
    

    var type = Ember.typeOf(content); console.log("Type: "+type); //debug console.log(content.get('firstObject')); //debug ...```

In the console this shows "null".

Is currently only an array supported or is it my fault/misunderstanding? Thank you, Manuel

zakmac commented 9 years ago

Hi Manuel,

I do not believe you are doing anything incorrectly, and will look into your use cases.

The examples page itself uses content from the model without issue. What you are seeing may be the result of applying unresolved promises to the component, which may be resulting in the unintended behavior. This should be a supported use case however so it will require a harder look.

As for ArrayProxy not functioning, I am not clear why it would not behave as expected and will also be looking at this.

Thanks for taking the time to document your trouble.

manuel-reil commented 9 years ago

Just a few bits of more information:

route.js

import Ember from 'ember';

export default Ember.Route.extend({

    setupController: function(controller) {
        controller.set('model', this.store.findAll('glossaryitem'));
    },
});

controller.js: I am sorting and grouping the items of the model.

import Ember from 'ember';
import groupBy from 'ember-group-by';

export default Ember.Controller.extend({

    gitemsSorted: function() {
        return Ember.ArrayProxy.extend(Ember.SortableMixin).create({
          sortProperties: ['l_char'],
          sortAscending: true,
          content: this.get('model')
        });
    }.property('model'),

    // Grouping the glossary items by leading char in order for the grouped view
    gitemsByChar: groupBy('gitemsSorted', 'l_char'),

});

template.js

        {{#filter-list content=model properties="items.term items.abbr" query=gQuery showInput=false as |filteredGitems|}}
            {{#each filteredGitems.filteredContent as |gitemgroup|}}  
                <div class="row">                               
                    <div class="col-lg-1 glossary-leading-char">
                            <h1><b>{{gitemgroup.value}}</b></h1>
...

Can you detect any error on my side there? Thank you, Manuel

manuel-reil commented 9 years ago

Hi again,

here an excerpt of the model gitemsByChar:

    [{
        "value":"A",
        "items": [
            {
            "term":"Term1",
            "explanation":"bliblibli"
            },
            {
            "term":"Term2",
            "explanation":"blablabla"
            },
        ]
    },
    {
        "value":"B",
        "items": [
            {
            "term":"Term3",
            "explanation":"blobloblo"
            },
            {
            "term":"Term4",
            "explanation":"blublublu"
            },
        ]
    }]

Our goal is to display only top level entries (the outer object including the value and the items) in case the query is matched in the term or explanation.

We accomplished it by a hack:

    {{#each gitemsByChar as |gitemgroup|}}
        {{#filter-list content=gitemgroup.items properties="term abbr also_see explanation" query=gQuery showInput=false as |filteredGitems|}}

            <div class="row">
                {{#if filteredGitems.filteredContent.length}}
                    <div class="col-lg-1 glossary-leading-char">
                        <h1><b>{{gitemgroup.value}}</b></h1>

So, we switched positions of the each and the filter-list (your component) and check in the if clause if the itemgroup should be displayed.

So the filter-list is not invoked once for the whole list, but around 30 times (once for each itemgroup). We have the feeling that by modifying the content and the properties accordingly (e.g. via an adequate @each construction in the properties) our goal above could be reached. But, we do not know how.

Any ideas? Thank you, Manuel

zakmac commented 9 years ago

Hey Manuel,

I've created a gist using the example you've provided. You can see that the property items.@each.term is used to check against term on the array items. The default behavior of filter-content is to show the root element that contains the sought after match.