Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Angular 1.4 filtered promises support #12337

Closed
mgcrea opened this issue Jul 13, 2015 · 4 comments
Closed

Angular 1.4 filtered promises support #12337

mgcrea opened this issue Jul 13, 2015 · 4 comments

Comments

@mgcrea
Copy link
Contributor

mgcrea commented Jul 13, 2015

Angular 1.4.0 started to throw errors when the ng.filter filter started to throw on non-array objects (#9992). This type check broke promise usage with filters, the following expression is now throwing errors before resolving the promise:

getAddress($viewValue) | filter:"Al" | limitTo:6
  $scope.getAddress = function() {
    return $q(function(resolve, reject) {
      resolve(['Alabama', 'Alaska', ...]);
    });
  }

More specifically, this broke AngularStrap typeahead with remote source example.

Looking at the source code, it looks like filters where probably not correctly applied in previous version of Angular, anyone could confirm this? Maybe there is another way around this issue?

Anyway, promises should be first class citizen across the framework. So it would be nice to have full support for them.

@mgcrea mgcrea changed the title Angular 1.4 broke filtered promises (regression) Angular 1.4 filtered promises support Jul 13, 2015
@lgalfaso
Copy link
Contributor

@mgcrea from what version of Angular are you upgrading from? Automatic resolution of promises in expressions was deprecated in 1.3.

@mgcrea
Copy link
Contributor Author

mgcrea commented Jul 13, 2015

@lgalfaso, this code used to "work" (not fail) for both 1.2 and 1.3 branches. Indeed it probably correctly worked in 1.2 and failed silently in 1.3 (but the results were fine du to the filter being also handled by the promise handler) and currently throws in 1.4.

Too bad it's unsupported anymore, it was a nice API. Any ideas on how to achieve that in 1.4? For now, I'm trying with a custom filter like:

  .filter('bsAsync', function($filter) {
    return function(array, expression, comparator) {
      if(array && angular.isFunction(array.then)) {
        return array.then(function(results) {
          return $filter('filter')(results, expression, comparator)
        });
      } else {
        return $filter('filter')(array, expression, comparator)
      }
    }
  })

@gkalpak
Copy link
Member

gkalpak commented Jul 14, 2015

@mgcrea, well, it didn't actually work in 1.2/1.3 either (it just didn't throw an error).
Pre 1.4, filterFilter would silently return the input unchanged if it wasn't an array/array-like, but it would not throw an error.

As a result, you would get back the original promise (see parse-options.js#L35) and then bind the async resolved values to $parseOptions.$values. So there would be no filtering going on.
(Demo of sync vs async typeahead - notice that in the sync case the items are properly filtered, while in the async the original list is displayed unfiltered.)

So, the current throwing behaviour is better (in that it revealed a silent bug).
I don't think this can be improved in core, without automatic promise resolution or a new async filter.

If I wanted to support filtering async loaded data in my typeahead component I would try one of 2:

  1. Change my parsing to separate the actual expression from the filtering part, resolve the expression (if it's a promise) and then pass the result through the filtering pipe.
  2. Provide an async filter, that returns an empty array which will be populated with data when they arrive (pretty much what ngResource does).

Option 2 is more clear/straightforward and maintainable imo, but it has the downside that one should use an extra filter: bd-options="item in getItemsAsync() | async | filter:... | ..."
(I'd still go for option 2 anyway !

@lgalfaso
Copy link
Contributor

This issue talks about a use case that was never supported and was already broken. There is nothing actionable here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants