blue-sky
blue-sky

Reputation: 53826

Extending text filter

Here I'm attempting to extend the standard text filter to perform a get request and pass value to extended filter user has entered

The filter name is 'search' :

myapp.filter('search', function($filter){    
  console.log('search param'+$scope.search)
  $http.get('http-hello2.html').success(function (data) {
           return $filter;
    });

But receive error :

Error: [$http:badreq] http://errors.angularjs.org/1.4.9/$http/badreq?p0=undefined
    at Error (native)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:6:416
    at m (https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:85:218)
    at Function.c.$get.m.(anonymous function) [as get] (https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:90:109)
    at link (https://run.plnkr.co/rz2TWpQpyYaVbHXN/script.js:14:27)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:73:222
    at ca (https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:73:279)
    at I (https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:62:174)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:69:193
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js:119:221 <status-viewer url="sourceUrl" class="ng-isolate-scope">

How to extend standard AngularJS text filter to invoke custom functionality and pass parameter to this filter? The custom functionality should occur prior to the standard filter logic being invoked.

plnnkr : https://plnkr.co/edit/F0XsOPZKq5HArFo9vtFs?p=preview

src :

goob.html : 
goob

http-hello2.html
2. http-hello2.html

test.html : 
test

index.html : 
<!doctype html>
<html ng-app="app">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
    <script src="script.js"></script>
  </head> 
  <body>

  <div ng-controller="FetchCtrl">

<label>Filter: <input ng-model="search"></label> 


<div ng-repeat="sourceUrl in sourceUrls | filter:search">
  <status-viewer  url="sourceUrl">   </status-viewer>
</div>
    </div>


 </body>
</html>

mytemplate.html : 

<!--<h1>{{url}}</h1>-->
<div>
    <p>{{model}}</p> 

</div>

script.js : 
var myapp = angular.module('app', []).controller('FetchCtrl', FetchCtrl)

myapp.directive('statusViewer', function ($http , $interval) {
            return { 
                restrict: 'E',
                templateUrl: 'mytemplate.html', 
                scope: {
                    url: '='
                },  
                link: function (scope, elem, attrs, ctrl) {

                    scope.isFinishedLoading = false;

                    $http.get(scope.url).success(function (data) {
                         scope.model = data;
                    });
                }
            };
        });

myapp.filter('search', function($filter){    
  console.log('search param'+$scope.search)
  $http.get('http-hello2.html').success(function (data) {
           return $filter;
    });

}); 

function FetchCtrl($scope, $http, $q , $parse) {


$scope.sourceUrls = [
                'http-hello2.html',
            ,'test.html'
            ,'goob.html'];



} 

Upvotes: 3

Views: 163

Answers (2)

Pankaj Parkar
Pankaj Parkar

Reputation: 136154

Error comes out because initially you had no value in $scope.search value and url has passed as undefined, other thing is you were tried to use $scope inside filter, which can't be accessible

As I can see that you don't wanted to load some template on change of input value. And from your current approach you wanted to load template from filter based on input(if I understood it correctly). But it seems like you are on wrong track.

Basically filtering is used to do some manipulation on binding while showing some value(like showing normal word in uppercase will use uppercase filter). Here you are using the filter for loading template on input change(basically that would fire a filter but not because of input change, it fires on digest cycle). Every time digest cycle will run it will make an ajax to fetch that template. Technically angular filter is not meant for what you are doing there.

Extending text filter turns out to be wrong approach as you don't need to extend it.

Better I'd say you should put ng-change event on input field with some function, that will fire up that function on each input change. and it will not make any change in filter working. By making this changes this would make template call only when input is changed

Markup

<input ng-model="search" ng-change="change()" />

Code

$scope.change = function() {
    //code here.
};

Upvotes: 0

Stepan Suvorov
Stepan Suvorov

Reputation: 26196

First of all you need to inject $http Service into you filter to prevent error that you have:

myapp.filter('search', function($filter, $http){    

and second thing:

you should not do

$http.get(scope.url)

not being sure that scope.url is already set. I would suggest to do request by condition;

 if(scope.url){
   //$http.get(scope.url)...
 }

Upvotes: 1

Related Questions