0

I am writing an app using AngularJS on the front end. I want to search through a table by any word/field; one search box for everything. I tried to follow this plunker's working example: http://plnkr.co/edit/aIuSDYlFbC4doW6pfsC9?p=preview

This is my code on the front end:

<div class = "row">
   <label>Search: <input ng-model="query"></label>
</div>

<div class = "row">
  <table ng-repeat="post in posts | orderBy: sort | filter: search">
    <tr>
       <td> {{index(post)}} </td>

       <td> {{post.title}} </td>

       <td> {{post.author}} </td>

       <td> {{post.content}} </td>

       <td> {{post.date | date: "d/M/yyyy"}} </td>
    </tr>
  </table>
</div>

And this is inside my main controller:

'use strict';
 $scope.posts = posts.posts;

 $scope.search = function (row) {
    return (angular.lowercase(row.author).indexOf($scope.query || '') !== -1 ||
    angular.lowercase(row.title).indexOf($scope.query || '') !== -1 ||
    angular.lowercase(row.content).indexOf($scope.query || '') !== -1 ||
    angular.lowercase(row.date).indexOf($scope.query || '') !== -1 ||
 };

What should I do? Thank you

7
  • filter: query. I'd also pipe the array through filter before orderBy Commented Jul 13, 2015 at 23:12
  • 1
    the example you posted appears to be using angular 1.0.3; I doubt that any new projects are using this release. Filters have changed drastically in angular, and this doesn't look like a function I would expect to work in modern angular releases. Commented Jul 13, 2015 at 23:33
  • also, you seem to have some syntax errors in that filter code, i.e. missing closing ), and a trailing || with no option after it. Commented Jul 13, 2015 at 23:35
  • @Phil: I know for a fact that the order on orderBy vs filter does not matter, and it will work the way it is now. Commented Jul 14, 2015 at 0:01
  • @VSO it might not make a functional difference but giving orderBy fewer items to sort will make it faster Commented Jul 14, 2015 at 0:12

3 Answers 3

4

Make a filter variable in your scope like so:

$scope.myFilter = "defaultFilterValue";

Bind your filter to a search field like this:

    <input type="text" ng-model="myFilter"></input>

Put the filter in your html like so:

  <table ng-repeat="post in posts | orderBy: sort | filter: myFilter">
    <tr>
       <td> {{index(post)}} </td>

       <td> {{post.title}} </td>

       <td> {{post.author}} </td>

       <td> {{post.content}} </td>

       <td> {{post.date | date: "d/M/yyyy"}} </td>
    </tr>
  </table>

And then...oh wait, that's it. Let me know if you have any problems. Tutorial here on exactly your question.


Edit: This code is TESTED, so use it exactly as is and go from there. Html:

<div class = "row">
    <label>Search: <input type="text" ng-model="myFilter"></input></label>
</div>

<div class = "row">
    <table ng-repeat="post in posts | orderBy: sort | filter: myFilter">
        <tr>
            <td> {{index.post}} </td> //you had a weird formatting mistake here

            <td> {{post.title}} </td>

            <td> {{post.author}} </td>

            <td> {{post.content}} </td>

            <td> {{post.date | date: "d/M/yyyy"}} </td>
        </tr>
    </table>
</div>

JS:

$scope.myFilter = "";

$scope.posts = [
        {index: 1, author: "Mark Twain", title: "Tom Sawyer", description: "And den Jim said some racist stuff", date:"02/05/1870"},
        {index: 2, author: "Eirch Remarque", title: "Western Front", description: "Our lost generation, bawww", date: "03/17/1955"}
];

Note: I REALLY recommend the tutorial I linked earlier. If you don't read it, then at least use table headers.

Sign up to request clarification or add additional context in comments.

6 Comments

You don't need a default filter value if the default is no filter
So I took out all that stuff I had before in the controller and just put in $scope.myFilter = ""; and binded the filter to a search field and put the filter in the html. But it is not working? @VSO
Am I missing something else? @Phil
@VSO Thank you for this. I have read the tutorial and looked through the codes multiple times. This solution doesn't work 100% for me. I don't know why. Sometimes the search works, it pulls results as expected. Sometimes it does not. For example, when my post.title is B, the search can find it. When it is A or C or D, it doesn't find them. Could it be the post.date interfering with it somehow? Btw I am using MongoDB to store the results
Are you familiar with <pre>{{yourPostData | json}}></pre> tags convention to test your data from post? You can use it to see what data is returned. If some data is returned for every field, your ng-repeat should work. If your ng-repeat works, the filter should work. Basically, what I am saying is that I don't think the date is the issue as long as you are getting data. It's not like you are bringing BSON back to the client. P.S. I don't know what the problem is at the point, those are just suggestions. I can say with fair certainty that it has nothing to do with the date, as long as its there.
|
1
<div class = "row">
   <label>Search: <input ng-model="query"></label>
</div>

<div class = "row">
    <table ng-repeat="post in posts | orderBy: sort | filter: query">
        <tr>
            <td> {{index(post)}} </td>
            <td> {{post.title}} </td>
            <td> {{post.author}} </td>
            <td> {{post.content}} </td>
            <td> {{post.date | date: "d/M/yyyy"}} </td>
        </tr>
    </table>
</div>

1 Comment

Please put an explanation saying what you changed and why it was wrong. That will help future visitors who may be having the same problem learn what to do.
0

Try this one.

HTML:

<label>Search:
  <input ng-model="searchKeyword" ng-model-options="{debounce:1000}">
</label>

<table ng-repeat="post in posts | orderBy: sort | filter: search">
  <tr>
    <td> {{post.title}} </td>
    <td> {{post.author}} </td>
    <td> {{post.content}} </td>
    <td> {{post.date}} </td>
  </tr>
</table>

Controller:

$scope.posts = [{
  title: 'Title one ',
  author: 'Author one ',
  content: 'Content one ',
  date: new Date('10.10.2010')
}, {
  title: 'Title two ',
  author: 'Author two ',
  content: 'Content two ',
  date: new Date('11.11.2011')
}, {
  title: 'Title three ',
  author: 'Author three ',
  content: 'Content three ',
  date: new Date('12.12.2012')
}];

$scope.searchKeyword = '';
$scope.sort = 'title';

var authorMatch, titleMatch, contentMatch, dateMatch;

$scope.search = function(row) {
  authorMatch = row.author.toLowerCase().includes($scope.searchKeyword);
  titleMatch = row.title.toLowerCase().includes($scope.searchKeyword);
  contentMatch = row.content.toLowerCase().includes($scope.searchKeyword);
  dateMatch = row.date.toString().toLowerCase().includes($scope.searchKeyword);

  return authorMatch || titleMatch || contentMatch || dateMatch;
};

The debounce option is explained here. Includes function is new in JavaScript and is explained here.

5 Comments

Thank you. Do I have to have Angular Strap for this approach? Because I am getting the "TypeError: Cannot read property 'toLowerCase' of undefined" error. @Sofre Garevski
Also this error: "TypeError: Cannot read property 'includes' of undefined" @Sofre Garevski
"TypeError: Cannot read property 'toLowerCase' of undefined" - means that author or title or content or date is not defined. From here comes the second error "TypeError: Cannot read property 'includes' of undefined". Make sure your data is consistent, or improve the method so it will check first if data exists.
I don't understand why they could be undefined. Because I double checked all the data names. @Sofre Garevski
But I definitely see why this would work @Sofre Garevski

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.