【问题标题】:How to filter Firebase JSON using AngularJS?如何使用 AngularJS 过滤 Firebase JSON?
【发布时间】:2017-03-29 01:11:07
【问题描述】:

我在 AngularJS 中调用我的 Firebase 数据库 JSON 并尝试过滤代码。我不断看到数组错误,例如:

Error: [filter:notarray] http://errors.angularjs.org/1.4.9/filter/notarray?

我的 HTML:

<form>
      <div class="form-group">
        <div class="input-group">
          <div class="input-group-addon"><i class="fa fa-search"></i></div>
          <input type="text" class="form-control" placeholder="Search" ng-model="searchTranslation">
        </div>      
      </div>
    </form>

    <table class="table table-bordered table-striped">
        <thead>
            <tr>
                <th>ID</th>
                <th>English</th>
                <th>Arabic</th>
                <th>Status</th>
                <th>Settings</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="i in translations | filter:searchTranslation track by $index">

                <td>{{$index}}</td>
                <td>{{i.transNameEn}}</td>
                <td class="textarabic">{{i.transNameArabic}}</td>
                <td class="{{i.transStatus}}">{{i.transStatus}}</td>
                <td>
                    <a ng-href="{{url}}pages-edit-translation/{{i.transId}}"
                    class="btn caps btn-warning">
                    EDIT
                    </a>
                </td>
            </tr>
        </tbody>
    </table>

我的 JS 代码

// @pages-home-translation
cmsApp.controller('pages-home-translation', function ($scope, $http) {

    $scope.sortType     = 'English'; // set the default sort type
    $scope.sortReverse  = false;  // set the default sort order
    $scope.searchTranslation   = '';     // set the default search/filter term

    $http.get(firebase_url+'cms/translations.json'+randstatus).success(function(data) {
        $scope.translations=data; // or data.data
    });

});

我的 JSON:

{
    "00hym5km2tf08s38fr-ivjgnsw6": {
        "notes": "",
        "transCreation": "11/15/2016, 4:14:07 PM",
        "transId": "00hym5km2tf08s38fr-ivjgnsw6",
        "transModified": "11/15/2016, 4:14:07 PM",
        "transNameArabic": "استخدم كعنوان الدفع الافتراضي",
        "transNameEn": "Use as my default billing address",
        "transStatus": "FIXED"
    },
    "08zq3t9411zaketnpnwmi-ivjhzz5q": {
        "notes": "",
        "transCreation": "11/15/2016, 4:51:35 PM",
        "transId": "08zq3t9411zaketnpnwmi-ivjhzz5q",
        "transModified": "11/15/2016, 4:51:35 PM",
        "transNameArabic": "احذية كرة القدم",
        "transNameEn": "Football Shoes",
        "transStatus": "FIXED"
    },
    "0aoycw0b0c9v8ov6xbt9-ivjhwnv6": {
        "notes": "",
        "transCreation": "11/15/2016, 4:49:00 PM",
        "transId": "0aoycw0b0c9v8ov6xbt9-ivjhwnv6",
        "transModified": "11/15/2016, 4:49:00 PM",
        "transNameArabic": "جينز واسع",
        "transNameEn": "Flared Jeans",
        "transStatus": "FIXED"
    }
}

注意:如果我删除

<tr ng-repeat="i in translations | filter:searchTranslation track by $index">

这样做反而会起作用:

<tr ng-repeat="i in translations">

但显然我希望使用搜索表单过滤结果。使用data.data 在控制台中显示没有错误。

我尝试在http.get 上执行setTimeOut 并且还延迟,以便它首先加载JSON,但它仍然无法正常工作。

谢谢

【问题讨论】:

  • 附加 JSON 一次。
  • 如何以及为什么会加载两次?
  • 看起来你得到的数据不是一个数组。 ng-repeat 需要一个数组来重复。首先检查数据是否为数组。如果不是,则将其转换为数组并使用。
  • 我该怎么做@suzo
  • 使用data.data,它将包含数据。传递给success 回调的对象是response 对象,其中包含您所追求的data 属性。

标签: angularjs json firebase firebase-realtime-database


【解决方案1】:

问题是filter 默认不过滤对象,即使ng-repeat 可以遍历对象属性。因此,这个问题有两种解决方法:在将对象设置为模型之前将其转换为数组,或者您可以创建一个自定义过滤器(可重用性不大)来过滤对象属性。

首先

要创建自定义过滤器,您可以:

Html

<ANY ng-repeat="item in items | filterObject:myModel">

JS

angular.filter('filterObject', function () {
    return function (obj, myModel) {
        // filter logic, bla bla bla
    };
});

第二

要将对象转换为数组,您可以在控制器端执行此操作(或创建辅助函数、服务等),也可以创建自定义过滤器来执行此操作。例如:

Html

<ANY ng-repeat="item in items | asArray | filter:myModel">

JS

.filter('asArray', function() {
  return function(obj /*, addKey*/ ) {
    // in case of undefined just return the same object to pass through
    if (!obj) return obj;
    // return an object maped as array of key as an item
    return Object.keys(obj).map(function(key) {
      return obj[key];
    });
  };
});

使用过滤器将数组转换为对象,您可以重复使用$filter 逻辑,而无需再次实现过滤器解决方案。因此,我认为这比为任务使用自定义过滤器更好。

稍微便宜一点的方法是在将其发送到模型之前将其转换为数组。但是,您可能希望保留原始属性名称(id 或其他名称)。

$http.get(firebase_url+'cms/translations.json'+randstatus).success(function(data) {    
    var myData = Object.keys(data).map(function(key) {
        return obj[key];
    });    
    $scope.translations = myData;    
});

以下示例实现了此解决方案,使用第二种方法(模拟服务器响应或填充 translations 模型有 1 秒延迟):

var cmsApp = angular.module('cmsApp', []);

cmsApp.filter('asArray', function() {
  return function(obj /*, addKey*/ ) {
    // in case of undefined just return the same object to pass through
    if (!obj) return obj;
    // return an object maped as array of key as an item
    return Object.keys(obj).map(function(key) {
      return obj[key];
    });
  };
});

// @pages-home-translation
cmsApp.controller('pages-home-translation', function($scope, $http, $timeout) {

  $scope.sortType = 'English'; // set the default sort type
  $scope.sortReverse = false; // set the default sort order
  $scope.searchTranslation = ''; // set the default search/filter term

  var data = {
    "00hym5km2tf08s38fr-ivjgnsw6": {
      "notes": "",
      "transCreation": "11/15/2016, 4:14:07 PM",
      "transId": "00hym5km2tf08s38fr-ivjgnsw6",
      "transModified": "11/15/2016, 4:14:07 PM",
      "transNameArabic": "استخدم كعنوان الدفع الافتراضي",
      "transNameEn": "Use as my default billing address",
      "transStatus": "FIXED"
    },
    "08zq3t9411zaketnpnwmi-ivjhzz5q": {
      "notes": "",
      "transCreation": "11/15/2016, 4:51:35 PM",
      "transId": "08zq3t9411zaketnpnwmi-ivjhzz5q",
      "transModified": "11/15/2016, 4:51:35 PM",
      "transNameArabic": "احذية كرة القدم",
      "transNameEn": "Football Shoes",
      "transStatus": "FIXED"
    },
    "0aoycw0b0c9v8ov6xbt9-ivjhwnv6": {
      "notes": "",
      "transCreation": "11/15/2016, 4:49:00 PM",
      "transId": "0aoycw0b0c9v8ov6xbt9-ivjhwnv6",
      "transModified": "11/15/2016, 4:49:00 PM",
      "transNameArabic": "جينز واسع",
      "transNameEn": "Flared Jeans",
      "transStatus": "FIXED"
    }
  };

  $timeout(function() {
    $scope.translations = data; // or data.data
  }, 1500);

});

angular.element(document).ready(function() {
  angular.bootstrap(document, ['cmsApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<div ng-controller="pages-home-translation">
  <form>
    <div class="form-group">
      <div class="input-group">
        <div class="input-group-addon"><i class="fa fa-search"></i>
        </div>
        <input type="text" class="form-control" placeholder="Search" ng-model="searchTranslation">
      </div>
    </div>
  </form>

  <table class="table table-bordered table-striped" border="1" cellpadding="4" style="border-collapse: collapse;">
    <thead>
      <tr>
        <th>ID</th>
        <th>English</th>
        <th>Arabic</th>
        <th>Status</th>
        <th>Settings</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="i in translations | asArray | filter:searchTranslation track by $index">

        <td>{{$index}}</td>
        <td>{{i.transNameEn}}</td>
        <td class="textarabic">{{i.transNameArabic}}</td>
        <td class="{{i.transStatus}}">{{i.transStatus}}</td>
        <td>
          <a ng-href="{{url}}pages-edit-translation/{{i.transId}}" class="btn caps btn-warning">EDIT</a>
        </td>
      </tr>
    </tbody>
  </table>
</div>

【讨论】:

  • 多么壮观的答案和解释。我希望我增加了我会给你更多的赏金。再次感谢
【解决方案2】:

根据您的代码需要进行一些更改。首先 $scope.translations 应该是一个数组,但根据您的 JSON,它不是一个数组。 ng-repeat 指令只接受一个数组来重复data

您的$scope.translations 应该与您的HTML 结构相同:

$scope.translations = [
  {
    "notes": "",
    "transCreation": "11/15/2016, 4:14:07 PM",
    "transId": "00hym5km2tf08s38fr-ivjgnsw6",
    "transModified": "11/15/2016, 4:14:07 PM",
    "transNameArabic": "استخدم كعنوان الدفع الافتراضي",
    "transNameEn": "Use as my default billing address",
    "transStatus": "FIXED"
  },
  {
    "notes": "",
    "transCreation": "11/15/2016, 4:51:35 PM",
    "transId": "08zq3t9411zaketnpnwmi-ivjhzz5q",
    "transModified": "11/15/2016, 4:51:35 PM",
    "transNameArabic": "احذية كرة القدم",
    "transNameEn": "Football Shoes",
    "transStatus": "FIXED"
  },
  {
    "notes": "",
    "transCreation": "11/15/2016, 4:49:00 PM",
    "transId": "0aoycw0b0c9v8ov6xbt9-ivjhwnv6",
    "transModified": "11/15/2016, 4:49:00 PM",
    "transNameArabic": "جينز واسع",
    "transNameEn": "Flared Jeans",
    "transStatus": "FIXED"
  }
];

工作演示:

var cmsApp = angular.module('myApp',[]);
cmsApp.controller('pages-home-translation', function ($scope, $http) {

    $scope.sortType     = 'English'; // set the default sort type
    $scope.sortReverse  = false;  // set the default sort order
    $scope.searchTranslation   = '';     // set the default 
    
    $scope.translations = [
    {
        "notes": "",
        "transCreation": "11/15/2016, 4:14:07 PM",
        "transId": "00hym5km2tf08s38fr-ivjgnsw6",
        "transModified": "11/15/2016, 4:14:07 PM",
        "transNameArabic": "استخدم كعنوان الدفع الافتراضي",
        "transNameEn": "Use as my default billing address",
        "transStatus": "FIXED"
    },
    {
        "notes": "",
        "transCreation": "11/15/2016, 4:51:35 PM",
        "transId": "08zq3t9411zaketnpnwmi-ivjhzz5q",
        "transModified": "11/15/2016, 4:51:35 PM",
        "transNameArabic": "احذية كرة القدم",
        "transNameEn": "Football Shoes",
        "transStatus": "FIXED"
    },
    {
        "notes": "",
        "transCreation": "11/15/2016, 4:49:00 PM",
        "transId": "0aoycw0b0c9v8ov6xbt9-ivjhwnv6",
        "transModified": "11/15/2016, 4:49:00 PM",
        "transNameArabic": "جينز واسع",
        "transNameEn": "Flared Jeans",
        "transStatus": "FIXED"
    }
];
    
});
table,th,td {
  border:1px solid black;
  }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="pages-home-translation">
  <form>
      <div class="form-group">
        <div class="input-group">
          <div class="input-group-addon"><i class="fa fa-search"></i></div>
          <input type="text" class="form-control" placeholder="Search" ng-model="searchTranslation">
        </div>      
      </div>
    </form>

    <table class="table table-bordered table-striped">
        <thead>
            <tr>
                <th>ID</th>
                <th>English</th>
                <th>Arabic</th>
                <th>Status</th>
                <th>Settings</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="i in translations | filter:searchTranslation">

                <td>{{$index}}</td>
                <td>{{i.transNameEn}}</td>
                <td class="textarabic">{{i.transNameArabic}}</td>
                <td class="{{i.transStatus}}">{{i.transStatus}}</td>
                <td>
                    <a ng-href="{{url}}pages-edit-translation/{{i.transId}}"
                    class="btn caps btn-warning">
                    EDIT
                    </a>
                </td>
            </tr>
        </tbody>
    </table>
</div>

【讨论】:

    猜你喜欢
    • 2012-08-09
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多