Cameron
Cameron

Reputation: 28803

Searching a JSON file in AngularJS

So I have the following service/factory setup that should query a JSON file:

myappServices.factory('Result', ['$resource',
    function($resource){
        return $resource('search.json', {}, {
            query: { method:'GET', params: {}, isArray:true }
        });
    }]);

And then in my SearchCtrl I have:

    myappControllers.controller('SearchCtrl', function($rootScope, $scope, $state, Result, $location) {

    $scope.query = ($state.includes('search') ? $location.search()['q'] : '');
    $scope.filterQuery = ($state.includes('search') ? $location.search()['q'] : '');

    $scope.queryChanged = function () {
        if($scope.query){
            $state.go('search', {'q': $scope.query} );
            $scope.results = Result.query();
        } else {
            $location.search('q', null);
        }
        $scope.filterQuery = $scope.query;
    }

    if($scope.query){
        $scope.results = Result.query();
    } else {
        $location.search('q', null);
    }

});

The search results page looks like:

<ul class="ng-hide" ng-show="results.length > 0">
    <li ng-repeat="result in results">
        <a href="{{result.url}}">{{result.name}}</a>
        <p>{{result.snippet}}</p>
    </li>
</ul>

<p class="ng-hide" ng-show="results.length == 0">Nothing here!</p>

If I do a query like:

/search?=hello

Then ALL the results in the JSON file are returned REGARDLESS of what I have searched for (should only be showing results that match).

However if I don't do a query then no results are shown (correct behaviour).

Why is the query not being used against the JSON file to filter the results?


I did originally have the repeater as:

<li ng-repeat="result in results = ( results | filter:filterQuery )">

But that would be incorrect in this case, as it's would be saying show me the results but filter them using the filterQuery. But in reality there would never be any results if no query, hence removing this part of the repeater. As I don't want to filter a list but return a list filtered.


So it would seem I am missing something in my service to handle this.

Upvotes: 1

Views: 995

Answers (3)

Brent Washburne
Brent Washburne

Reputation: 13148

Edited: Simplify your resource so it doesn't define query:

myappServices.factory('Result', ['$resource',
    function($resource){
        return $resource('search.json');
    }]);

Try changing your controller to clear the results and only set them when a query has been made:

myappControllers.controller('SearchCtrl', function($rootScope, $scope, $state, Result, $location) {

    $scope.query = ($state.includes('search') ? $location.search()['q'] : '');
    $scope.filterQuery = ($state.includes('search') ? $location.search()['q'] : '');

    $scope.results = [];
    $scope.queryChanged = function () {
        if($scope.query){
            $state.go('search', {'q': $scope.query} );
        } else {
            $scope.results = Result.query({q:$scope.query});
        }
        $scope.filterQuery = $scope.query;
    }
});

Upvotes: 1

Deblaton Jean-Philippe
Deblaton Jean-Philippe

Reputation: 11388

app.factory('querySvc', ['$q', '$resource', querySvc]);

function querySvc($q, $resource) {
    var service = {
         getSearch: getSearch
    }
    return service;

 function getSearch(){
    var deferred = $q.defer();

    $resource('search.json').query( function(data){
         deferred.resolve(data);
    }, function(error){
         // handle error
    });
    return deferred.promise;
 }

Then you can call it that way:

 querySvc.getSearch().then(function (data){
     $scope.results = data;
 }, function(error){
     //handle error here
 });

About your first note : When you instantiate your controller, it executes everything inside it.

So, if you want to call this function when a user clicks somewhere, you can register a function into the scope :

$scope.querySearch = function(){
     querySvc.getSearch().then(function (data){
         $scope.results = data;
     }, function(error){
         //handle error here
     });
}

And then, into your view, you will have to call it when an event is fired. I don't remember the event you need, but I'll show you a way of doing it :

<span ng-click="querySearch()" />

This will trigger the function when you click on the span.

Upvotes: 1

Brent Washburne
Brent Washburne

Reputation: 13148

In the console, look in the Network tab to see if the request has an error and/or to see the contents of the response. If the response has a status code of 200 and the contents are correct, then check the response to see if the data is structured correctly for results.length (that it returns a list).

Upvotes: 0

Related Questions