最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS smart-table strange behavior with nested objects and st-search - Stack Overflow

programmeradmin0浏览0评论

I'm trying to implement the Smart Table module in my AngularJS app. I'd prefer this over some others mainly because the others seemed require a lot of boilerplate code in my controller and I like to keep my controllers as DRY as possible. But I'm open to other modules that can acplish the same thing without boilerplate.

It works great when dealing with a straight-up array of objects, but if some of those objects have nested objects, the filtering and sorting has strange behavior.

This will take some explaining so bear with me.

First of all, here is my array of nested objects (shortened for readability here):

$scope.products = [
    {
        'display': 'Live',
        'name': 'LC1D09',
        'category': 'Motor Control',
        'subcategory': 'Contactor',
        'manufacturer': 'Telemecanique',
        'specs': {
            'phase': 3,
            'poles': 3
        },
        'new': {
            'price': 158.95
        },
        'refurbished': {
            'price': 145
        },
        'onlineStores': {
            'amazon': true,
            'ebay': false
        },
        'isCool': true
    },
    {
        'display': 'Pending',
        'name': 'FA32020',
        'category': 'Circuit Breaker',
        'subcategory': 'Molded Case',
        'manufacturer': 'Square D',
        'specs': {
            'phase': 1,
            'poles': 2
        },
        'new': {
            'price': 217.79
        },
        'refurbished': {
            'price': 192.82
        },
        'onlineStores': {
            'amazon': true,
            'ebay': true
        },
        'isCool': false
    }
];
$scope.displayedProducts = $scope.products;

Here's my HTML:

<table st-table="displayedProducts" st-safe-src="products" class="table table-striped table-bordered table-hover">
    <thead>
        <tr>
            <th st-sort="name">Name</th>
            <th st-sort="category">Category</th>
            <th>Subcategory</th>
            <th>Manufacturer</th>
            <th>New Price</th>
            <th>Refurb. Price</th>
            <th>Display</th>
            <th>Specs</th>
            <th>Cool</th>
        </tr>
        <tr>
            <th><input st-search="'name'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'category'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'subcategory'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'manufacturer'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="new.price" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="refurbished.price" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'display'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'specs'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th>
                <select st-search="onlineStores.ebay" class="form-control">
                    <option value=""></option>
                    <option value="true">Yes</option>
                    <option value="false">No</option>
                </select>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="product in displayedProducts">
            <td>{{product.name}}</td>
            <td>{{product.category}}</td>
            <td>{{product.subcategory}}</td>
            <td>{{product.manufacturer}}</td>
            <td>${{product.new.price | number : 0}}</td>
            <td>${{product.refurbished.price | number : 0}}</td>
            <td>{{product.display}}</td>
            <td>{{product.specs}}</td>
            <td>{{product.onlineStores.ebay}}</td>
        </tr>
    </tbody>
</table>

So this all works fine if my array doesn't have nested objects. But with the nested objects (eg st-search="new.price" I get the following issues (see the screenshot):

  1. Sometimes when I enter text in a "nested object" search field, all other fields that also have nested objects inherit the same value (but the filtering still works fine). This doesn't always do this, just sometimes...
  2. Boolean values on nested objects don't pute correctly. True will show all records, but False will show only the record whose value is False.

Anybody else figured out how to deal with nested objects and the smart-table module?

I'm trying to implement the Smart Table module in my AngularJS app. I'd prefer this over some others mainly because the others seemed require a lot of boilerplate code in my controller and I like to keep my controllers as DRY as possible. But I'm open to other modules that can acplish the same thing without boilerplate.

It works great when dealing with a straight-up array of objects, but if some of those objects have nested objects, the filtering and sorting has strange behavior.

This will take some explaining so bear with me.

First of all, here is my array of nested objects (shortened for readability here):

$scope.products = [
    {
        'display': 'Live',
        'name': 'LC1D09',
        'category': 'Motor Control',
        'subcategory': 'Contactor',
        'manufacturer': 'Telemecanique',
        'specs': {
            'phase': 3,
            'poles': 3
        },
        'new': {
            'price': 158.95
        },
        'refurbished': {
            'price': 145
        },
        'onlineStores': {
            'amazon': true,
            'ebay': false
        },
        'isCool': true
    },
    {
        'display': 'Pending',
        'name': 'FA32020',
        'category': 'Circuit Breaker',
        'subcategory': 'Molded Case',
        'manufacturer': 'Square D',
        'specs': {
            'phase': 1,
            'poles': 2
        },
        'new': {
            'price': 217.79
        },
        'refurbished': {
            'price': 192.82
        },
        'onlineStores': {
            'amazon': true,
            'ebay': true
        },
        'isCool': false
    }
];
$scope.displayedProducts = $scope.products;

Here's my HTML:

<table st-table="displayedProducts" st-safe-src="products" class="table table-striped table-bordered table-hover">
    <thead>
        <tr>
            <th st-sort="name">Name</th>
            <th st-sort="category">Category</th>
            <th>Subcategory</th>
            <th>Manufacturer</th>
            <th>New Price</th>
            <th>Refurb. Price</th>
            <th>Display</th>
            <th>Specs</th>
            <th>Cool</th>
        </tr>
        <tr>
            <th><input st-search="'name'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'category'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'subcategory'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'manufacturer'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="new.price" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="refurbished.price" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'display'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th><input st-search="'specs'" placeholder="" class="input-sm form-control" type="search"/></th>
            <th>
                <select st-search="onlineStores.ebay" class="form-control">
                    <option value=""></option>
                    <option value="true">Yes</option>
                    <option value="false">No</option>
                </select>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="product in displayedProducts">
            <td>{{product.name}}</td>
            <td>{{product.category}}</td>
            <td>{{product.subcategory}}</td>
            <td>{{product.manufacturer}}</td>
            <td>${{product.new.price | number : 0}}</td>
            <td>${{product.refurbished.price | number : 0}}</td>
            <td>{{product.display}}</td>
            <td>{{product.specs}}</td>
            <td>{{product.onlineStores.ebay}}</td>
        </tr>
    </tbody>
</table>

So this all works fine if my array doesn't have nested objects. But with the nested objects (eg st-search="new.price" I get the following issues (see the screenshot):

  1. Sometimes when I enter text in a "nested object" search field, all other fields that also have nested objects inherit the same value (but the filtering still works fine). This doesn't always do this, just sometimes...
  2. Boolean values on nested objects don't pute correctly. True will show all records, but False will show only the record whose value is False.

Anybody else figured out how to deal with nested objects and the smart-table module?

Share Improve this question asked Oct 17, 2014 at 19:05 JoaoJoao 2,7462 gold badges27 silver badges36 bronze badges 2
  • the search API does not support nested properties but you can use custom filter function if you prefer rather than angular filter Filter. Refer to this issue on github for more details – laurent Commented Oct 25, 2014 at 1:30
  • Hi Joao, did you find any solution to this issue? – Yasmeen Commented Sep 18, 2015 at 7:29
Add a ment  | 

2 Answers 2

Reset to default 1

As laurent said, you need to use a custom filter

Use st-set-filter to set your filter

<table st-table="displayedProducts" st-safe-src="products" st-set-filter="customFilter" class="table table-striped table-bordered table-hover">

In your module, define a custom filter

angular.module('myModule').filter('customFilter', ['$parse', function($parse) {
    return function(items, filters) {
        var itemsLeft = items.slice();

        Object.keys(filters).forEach(function(model) {
            var value = filters[model],
                getter = $parse(model);

            itemsLeft = itemsLeft.filter(function(item) {
                return getter(item) === value;
            });
        });

        return itemsLeft;
    };
}])

You need to use a copy of your collection, so instead of doing the direct assignment $scope.displayedProducts = $scope.products; you should do $scope.displayedProducts= $scope.displayedProducts.concat($scope.products);

发布评论

评论列表(0)

  1. 暂无评论