3

I want a live search: the results are queried from web api and updated as the user types.

The problem is that the list flickers and the "No results" text appears for a fraction of second, even if the list of results stays the same. I guess I need to remove and add items with special code to avoid this, calculating differences between arrays, etc.

Is there a simpler way to avoid this flicker at least, and probably to have possibility to animate the changes?

It looks like this now:

How live search looks like

The html part is:

    <div class="list-group">
        <a ng-repeat="test in tests track by test.id | orderBy: '-id'" ng-href="#/test/{{test.id}}" class="list-group-item">
            <h4 class="list-group-item-heading">{{test.name}}</h4>
            {{test.description}}
        </a>
    </div>
    <div ng-show="!tests.length" class="panel panel-danger">
        <div class="panel-body">
            No tests found.
        </div>
        <div class="panel-footer">Try a different search or clear the text to view new tests.</div>
    </div>

And the controller:

testerControllers.controller('TestSearchListCtrl', ['$scope', 'TestSearch',
function($scope, TestSearch) {
    $scope.tests = TestSearch.query();
    $scope.$watch('search', function() {
        $scope.tests = TestSearch.query({'q':$scope.search});
    });
}]);
Andrey Moiseev
  • 3,914
  • 7
  • 48
  • 64
  • why don't you just use a filter instead of using `$watch`? the way you are doing it now, you are doing a new search every keystroke, which is a new call to the server; a filter would just filter the data client side. – Claies Apr 26 '15 at 21:40
  • I need to search in all results on the server. Filter is for quick search in a static list. I've just found out how not to search at every keystroke: `ng-model-options="{debounce: 1000}"` to the the element with `ng-model`. But when it reloads, it still flickers. – Andrey Moiseev Apr 26 '15 at 21:46

3 Answers3

2

You should use ng-animate module to get the classes you need for smooth animation. For each ng-repeat item that's moved, added, or removed - angular will add specific classes. Then you can style those classes via CSS or JS so they don’t flicker.

Aman Gupta
  • 557
  • 1
  • 8
  • 23
0

An alternative way of doing what you require is to use the angular-ui bootstrap Typeahead component (check at the bottom of the post). It has a type-ahead-wait property in milliseconds and also a template url for customising it.

sarin
  • 5,227
  • 3
  • 34
  • 63
-1
<div ng-app>
    <div ng-controller="MyController">
        <input type="search" ng-model="search" placeholder="Search...">
        <button ng-click="fun()">search</button>
        <ul>
            <li ng-repeat="name in names">{{ name }}</li>
        </ul>
        <p>Tips: Try searching for <code>ann</code> or <code>lol</code>

        </p>
    </div>
</div>



function MyController($scope, $filter) {
    $scope.names = [
        'Lolita Dipietro',
        'Annice Guernsey',
        'Gerri Rall',
        'Ginette Pinales',
        'Lon Rondon',
        'Jennine Marcos',
        'Roxann Hooser',
        'Brendon Loth',
        'Ilda Bogdan',
        'Jani Fan',
        'Grace Soller',
        'Everette Costantino',
        'Andy Hume',
        'Omar Davie',
        'Jerrica Hillery',
        'Charline Cogar',
        'Melda Diorio',
        'Rita Abbott',
        'Setsuko Minger',
        'Aretha Paige'];
    $scope.fun = function () {
        console.log($scope.search);
        $scope.names = $filter('filter')($scope.names, $scope.search);
    };
}
  • 2
    The question is about searching using *web api*, not local filtering. And local filtering is easily done by adding `| filter: search` to `ng-repeat` directive, with no additional code in controller. – Andrey Moiseev Apr 29 '15 at 10:10