如何制作 ng-repeat 过滤器

How to make ng-repeat filter

像这里一样努力实现过滤器 ngrepeatFilter

我的数据结构是这样的:

$scope.books = [
                {
                    id: 'id1',
                    contents: {
                        name: '<span>1Alain du sceau france</span><br><span> Canada Madagascar philipine</span>',
                        price: 'price1',
                        date: '111'
                    }
                },
                {
                    id: 'id2',
                    contents: {
                        name: '<span>2Name zu Long zu Schreiben Bis Here ist Ein Beispiel</span><br><span>Maneschester Canada Madagascar philipine</span>',
                        price: 'price2',
                        date: '2'
                    }
                },
                .........etc

            ];

但它似乎只适用于我用例中的 book.contents['date'] 字段,而不适用于 book.contents['name'] :我的第一个目标是能够按名称过滤,如果我能够同时按名称和日期或按所有三个字段名称日期价格进行过滤,那就更好了。

MyCodePen

在下面

 <li class="animate-repeat fc-event" ng-repeat="book in books| orderBy: book.contents['date'] | filter:q as results track by book.contents['name']"  
             id="{{book.id}}">

为了成功实施,我遇到了很多问题:

N.B: 
   1) class="animate-repeat" not included with fc-event
      means No : .animate-repeat.fc-event 
      included in CSS File.
   2) orderBy book.contents['date'] is not working: 111 
      is the first one it should be the last one.
      book.contents['date'] uses $sce.trustAsHtml 
      see 173,174,175 lines in js file.
      also it uses ng-bind-html="book.contents['name']"
      see line 38 from html file

    3) when filtering by input text : 
       1 it works
       1Alain it doesn't work  which results 
       No results found...
       2Name it doesn't work No results found...


<!DOCTYPE html>
<html ng-app="app">
  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script data-require="angular.js@1.0.x" src="https://code.angularjs.org/1.3.15/angular.min.js" data-semver="1.0.7"></script>
    <script type="text/javascript" src="https://github.com/kamilkp/angular-vs-repeat/blob/master/dist/angular-vs-repeat.js"></script>
 <script src="https://code.angularjs.org/1.3.15/angular-animate.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<div id='external-events'>
  <h4 >Draggable books</h4>
  <br><br>I have {{books.length}} Books. They are:
       <input type="search" ng-model="q" placeholder="filter books..." aria-label="filter books" />    

          <ul data-drag="true"  data-jqyoui-options="{revert: 'invalid'}" jqyoui-draggable="{index {{$index}},placeholder:true,animate:true}">
      <div class="repeater-container" vs-repeat>
        <!-- N.B: 
             1) class="animate-repeat" not included with fc-event
                means No : .animate-repeat.fc-event  included 
                in CSS File.
             2) orderBy book.contents['date'] is not working: 111 is                 the first one it should be the last one.
                book.contents['date'] uses $sce.trustAsHtml 
                see 173,174,175 lines in js file.
                also it uses ng-bind-html="book.contents['name']"
                see line 38 from html file

             3) when filtering by input text : 
                1 it works
                1Alain it doesn't work No results found...
                2Name it doesn't work No results found...
        -->
        <li class="animate-repeat fc-event" ng-repeat="book in books| orderBy: book.contents['date'] | filter:q as results track by book.contents['name']"  
             id="{{book.id}}">

        <div class="circle">{{book.contents['date']}}</div>
        <div class="left content" ng-bind-html="book.contents['name']" id="book_{{book.id}}"></div>
            <div class="left rating">2/10</div>
        <div class="clear"></div>
        </li>
        <li class="animate-repeat" ng-if="results.length === 0">
                <strong>No results found...</strong>
            </li>
        </div>
      </ul>
  </div>
<div id='calendar-container'>
  <div id='calendar'></div>
</div>
</body>
</html>    


ul {
  list-style-type: none;
}

ul>li {
  display:block;
    padding-right: 0cm;
    margin-left: 0px;
}

h4 {
  color: gray;
  display: inline; 
  border-bottom: 3px solid darken($fendersblue, 10);
  padding-bottom: 8px;
  font-size:600;
}


#calendar{
 padding: 0 10px;
 width: 650px;
 float: right;
 margin: 0px 0px 10px 55px;
}

#external-events {
  width: 500px;
  padding: 0 0px;
  border: 0px solid #ccc;/* gray moyen*/
  background: #eee;/* #5D6D7E;(Blue mat) */ /* #eee color gray*/
  text-align: left;
}

.repeater-container {
    height: 500px;
     width: 460px;
        overflow: auto;
        box-shadow: 0 0 10px;
        border-radius: 5px;
    z-index: 100;
        -webkit-overflow-scrolling: touch;

}


#external-events .fc-event {
  cursor: pointer;
  z-index: 100;
  background: #eee;
  border: solid 1px black;
  border-radius: 2px;
  margin-bottom:5px;
}

.content span
{
  color: gray;
}
.fc-event span:first-child
{
  font-size: 25px;
  font-weight: bold italic;
}



.fc-event div
{
  padding:3px;
  margin-right:5px;
  height: 100%;
}

.content
{
  float:left;
  max-width:75%;
}

.clear
{
  clear:both;
}

.circle {
  float:left;
  width: 10%;
  height: 25%;
  padding: 0 10px;
  border-radius: 360px;


  /* Just making it pretty */
  @shadow: rgba(0, 0, 0, .1);
  @shadow-length: 4px;
  -webkit-box-shadow: 0 @shadow-length 0 0 @shadow;
          box-shadow: 0 @shadow-length 0 0 @shadow;
  text-shadow: 0 @shadow-length 0 @shadow;
  background: #FFFFFF;/*color white*/
  color: #f05907;/* color red*/
  font-family: Helvetica, Arial Black, sans;
  font-size: 10;
  text-align: center;
}

.rating
{
  float:right;
  background: #FFFFFF;/*color white*/
  color: #f05907;/* color red*/
  font-family: Helvetica, Arial Black, sans;
  font-size: 10;
  text-align: center;
  border-radius: 360px;
}

.animate-repeat {
  line-height:30px;
  list-style:none;
  box-sizing:border-box;
}

.animate-repeat.ng-move,
.animate-repeat.ng-enter,
.animate-repeat.ng-leave {
  transition:all linear 0.5s;
}

.animate-repeat.ng-leave.ng-leave-active,
.animate-repeat.ng-move,
.animate-repeat.ng-enter {
  opacity:0;
  max-height:0;
}

.animate-repeat.ng-leave,
.animate-repeat.ng-move.ng-move-active,
.animate-repeat.ng-enter.ng-enter-active {
  opacity:1;
  max-height:30px;
}
(function(angular) {
  'use strict';
var app = angular.module("app", ['ngAnimate']);
app.controller("MainCtrl", ['$scope', '$sce', function($scope, $sce){

  $scope.books = [
                {
                    id: 'id1',
                    contents: {
                        name: '<span>1Alain du sceau france</span><br><span> Canada Madagascar philipine</span>',
                        price: 'price1',
                        date: '111'
                    }
                },
                {
                    id: 'id2',
                    contents: {
                        name: '<span>2Name zu Long zu Schreiben Bis Here ist Ein Beispiel</span><br><span>Maneschester Canada Madagascar philipine</span>',
                        price: 'price2',
                        date: '2'
                    }
                },
                {
                    id: 'id3',
                    contents: {
                        name: '<span>3name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price3',
                        date: '3'
                    }
                },
                {
                    id: '4',
                    contents: {
                        name: '<span>4name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price4',
                        date: '4'
                    }
            },
            {
                    id: 'id5',
                    contents: {
                        name: '<span>5name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price5',
                        date: '5'
                    }
            },
            {
                    id: 'id6',
                    contents: {
                        name: '<span>6name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price6',
                        date: '6'
                    }
            },
            {
                    id: 'id7',
                    contents: {
                        name: '<span>7name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price7',
                        date: '7'
                    }
            },
            {
                    id: 'id8',
                    contents: {
                        name: '<span>8name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price8',
                        date: '8'
                    }
            },
            {
                    id: 'id9',
                    contents: {
                        name: '<span>9name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price9',
                        date: '9'
                    }
            },
               {
                    id: 'id10',
                    contents: {
                        name: '<span>10Alain du sceau france</span><br><span> Canada Madagascar philipine</span>',
                        price: 'price10',
                        date: '10'
                    }
                },
                {
                    id: 'id11',
                    contents: {
                        name: '<span>11Name zu Long zu Schreiben Bis Here ist Ein Beispiel</span><br><span>Maneschester Canada Madagascar philipine</span>',
                        price: 'price11',
                        date: '11'
                    }
                },
                {
                    id: 'id12',
                    contents: {
                        name: '<span>12name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price12',
                        date: '12'
                    }
                },
                {
                    id: 'id13',
                    contents: {
                        name: '<span>13name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price13',
                        date: '13'
                    }
            },
            {
                    id: 'id14',
                    contents: {
                        name: '<span>14name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price14',
                        date: '14'
                    }
            },
            {
                    id: 'id15',
                    contents: {
                        name: '<span>15name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price15',
                        date: '15'
                    }
            },
            {
                    id: 'id16',
                    contents: {
                        name: '<span>16name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price16',
                        date: '16'
                    }
            },
            {
                    id: 'id17',
                    contents: {
                        name: '<span>17name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price17',
                        date: '17'
                    }
            },
            {
                    id: 'id18',
                    contents: {
                        name: '<span>18name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price18',
                        date: '18'
                    }
            },
            {
                    id: 'id19',
                    contents: {
                        name: '<span>19name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price19',
                        date: '19'
                    }
            },
            {
                    id: 'id20',
                    contents: {
                        name: '<span>20name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price20',
                        date: '20'
                    }
            }
            ];





  $scope.books.forEach(function(book) {
    book.contents.name =  $sce.trustAsHtml(book.contents.name);
  })

  $scope.h = function(html) {
    return $sce.trustAsHtml(html);
  };


 $(document).ready( function(){     
                    //Initialise external events
                    initialise_external_event('.fc-event');
                    initialise_calendar();

    });





  // initialize the external events
  // -----------------------------------------------------------------
function initialise_external_event(selector){

  $('#external-events .fc-event').each(function() {

  var reccupuredIndex=$(this).closest('li.fc-event').attr('id');
  var textContenu=$("#"+ "book_" +reccupuredIndex).html();
  /*
  $("div.left.content").each(function( index, element ) {
          // element == this
          // $( element ).css( "backgroundColor", "yellow" );
         var reccupuredIndexToSee=$(this).closest('li.fc-event').attr('id');
         var textContenuToSee=$("#"+"book_"+reccupuredIndexToSee).text();

         var myIndex="book_" +reccupuredIndexToSee;
         if ( $(this).is( "#"+myIndex) )  {

           alert($(this).text());

          }
  });
  */

    var myTitle=$.trim($(this).text());
    //$("span").text( "length:" +$("p.intro").get(0));

    // store data so the calendar knows to render an event upon drop
    $(this).data('event', {
      title: $.trim($(this).text()), // use the element's text as the event title
      stick: true // maintain when user navigates (see docs on the renderEvent method)
    });

    // make the event draggable using jQuery UI
    $(this).draggable({
      zIndex: 999,
      revert: true,      // will cause the event to go back to its
      revertDuration: 0  //  original position after the drag
    });

  });

}
  function initialise_calendar(){
  // initialize the calendar
  // -----------------------------------------------------------------

  $('#calendar').fullCalendar({
    header: {
      left: 'prev,next today',
      center: 'title',
      right: 'month,agendaWeek,agendaDay'
    },
    editable: true,
    droppable: true, // this allows things to be dropped onto the calendar
    drop: function() {
      // is the "remove after drop" checkbox checked?
      if ($('#drop-remove').is(':checked')) {
        // if so, remove the element from the "Draggable Events" list
        $(this).remove();
      }
    },
    eventDragStop: function(event, jsEvent, ui, view ) {

                      if(isEventOverDiv(jsEvent.clientX, jsEvent.clientY)) {


                          //////////
                          $('#calendar').fullCalendar('removeEvents', event._id);
                 var el = $( "<div class='fc-event'>" ).appendTo('#external-        events').text(event.id);

    }
            }            
  });
var isEventOverDiv = function(x, y) {

                    var external_events = $( '#external-events' );
                    var offset = external_events.offset();
                    offset.right = external_events.width() + offset.left;
                    offset.bottom = external_events.height() + offset.top;

                    // Compare
                    if (x >= offset.left
                        && y >= offset.top
                        && x <= offset.right
                        && y <= offset .bottom) { return true; }
                    return false;

                }
 }

}]);
})(window.angular);

非常感谢。

在您的控制器中,您遍历每本书并将名称字段的值替换为 $sce.trustAsHtml(book.content.name) 的结果,这与过滤字符串不同。

我可能会错误地选择在 DOM 中做任何 html 标记而不使用 $sce.trustAsHtml,但这是你的选择。

您可以像这样将 $sce.trustAsHtml 绑定到控制器中的范围 $scope.trustAsHtml = $sce.trustAsHtml 然后修改你的 DOM 就像我在下面做的那样。

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script data-require="angular.js@1.0.x" src="https://code.angularjs.org/1.3.15/angular.min.js" data-semver="1.0.7"></script>
    <script type="text/javascript" src="https://github.com/kamilkp/angular-vs-repeat/blob/master/dist/angular-vs-repeat.js"></script>
 <script src="https://code.angularjs.org/1.3.15/angular-animate.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<div id='external-events'>
  <h4 >Draggable books</h4>
  <br><br>I have {{books.length}} Books. They are:
       <input type="search" ng-model="searchText" placeholder="filter books..." aria-label="filter books" />    

          <ul data-drag="true"  data-jqyoui-options="{revert: 'invalid'}" jqyoui-draggable="{index {{$index}},placeholder:true,animate:true}">
      <div class="repeater-container" vs-repeat>
        <!-- N.B: 
             1) class="animate-repeat" not included with fc-event
                means No : .animate-repeat.fc-event  included 
                in CSS File.
             2) orderBy book.contents['date'] is not working: 111 is                 the first one it should be the last one.
                book.contents['date'] uses $sce.trustAsHtml 
                see 173,174,175 lines in js file.
                also it uses ng-bind-html="book.contents['name']"
                see line 38 from html file

             3) when filtering by input text : 
                1 it works
                1Alain it doesn't work No results found...
                2Name it doesn't work No results found...
        -->
        <li class="animate-repeat fc-event" ng-repeat="book in books | orderBy: book.contents.date| filter:searchText as results track by book.contents.name"  
             id="{{book.id}}">

        <div class="circle">{{book.contents['date']}}</div>
        <div class="left content" ng-bind-html="trustAsHtml(book.contents['name'])" id="book_{{book.id}}"></div>
            <div class="left rating">2/10</div>
        <div class="clear"></div>
        </li>
        <li class="animate-repeat" ng-if="results.length === 0">
                <strong>No results found...</strong>
            </li>
        </div>
      </ul>
  </div>
<div id='calendar-container'>
  <div id='calendar'></div>
</div>
</body>
</html>