AngularJS中使用smart-table组件,使用时几个注意点

在一个项目中需要汉化一个老外写的前端框架, 它的列表使用了smart-table组件,给的例子中,数据是在controller本地直接定义的数组,运行一切正常,如下:

$scope.smartTableData = [
      {
        id: 1,
        firstName: 'Mark',
        lastName: 'Otto',
        username: '@mdo',
        email: 'mdo@gmail.com',
        age: '28'
      },
      {
        id: 2,
        firstName: 'Jacob',
        lastName: 'Thornton',
        username: '@fat',
        email: 'fat@yandex.ru',
        age: '45'
      },
      {
        id: 3,
        firstName: 'Larry',
        lastName: 'Bird',
        username: '@twitter',
        email: 'twitter@outlook.com',
        age: '18'
      },
      {
        id: 4,
        firstName: 'John',
        lastName: 'Snow',
        username: '@snow',
        email: 'snow@gmail.com',
        age: '20'
      },
      {
        id: 5,
        firstName: 'Jack',
        lastName: 'Sparrow',
        username: '@jack',
        email: 'jack@yandex.ru',
        age: '30'
      },
      {
        id: 6,
        firstName: 'Ann',
        lastName: 'Smith',
        username: '@ann',
        email: 'ann@gmail.com',
        age: '21'
      },
      {
        id: 7,
        firstName: 'Barbara',
        lastName: 'Black',
        username: '@barbara',
        email: 'barbara@yandex.ru',
        age: '43'
      },
      {
        id: 8,
        firstName: 'Sevan',
        lastName: 'Bagrat',
        username: '@sevan',
        email: 'sevan@outlook.com',
        age: '13'
      }
      ]

没有问题,当然实际项目中需要从数据库里取数据,于是先写一个拿数据的service:

angular.module('BlurAdmin.pages').factory('myFactory', function($rootScope, $http, $location, $window){
    var service = {};

service.host = "http://localhost:8099/"; 


//Ajax请求
    service.http_req = function (url, meth, op, cb) {
        $http({
            url: service.host + url,    
            method: meth,
            timeout: 15000,
            headers: {
                'Content-Type': 'application/json'

            },
            xhrFields: {
                withCredentials: true
            },
            crossDomain: true,
            data: op
        }).success(function (result) {
            cb("ok", result);
        }).error(function (result, data, status, headers, config) {
            if (data == 0) {
               console.log("请求超时,请重试");
               return;
            }


            //处理响应失败
            cb("server req error", result);
        });
    };


    return service;
});

之后在controller里面调用这个service,从后端拿数据:

      myFactory.http_req('demo/all', "GET", {},
                    function (err, results) {
                        if (err == "ok") {
                        //异步取得数据后,赋给smartTabelData
                            $scope.smartTableData = results;

                            console.log($scope.smartTableData);
                            console.log($scope.hasdata);

                        } else {
                            console.log("失败");
                        }
                    });

运行时发现,数据取到了,可是ng-repeat 并没有刷新表,列出异步取到的数据。

 <table st-table="smartTableData" class="table table-striped" >
  <thead>
  <tr class="sortable ">
      <th class="table-id" st-sort="id" st-sort-default="true"></th>
      <th st-sort="firstName"></th>
      <th st-sort="firstName"></th>
      <th st-sort="lastName"></th>
      <th st-sort="username">用户名</th>
      <th st-sort="email">邮件</th>
      <th st-sort="age">年龄</th>
    </tr>
  </thead>
  <tbody>
  <tr ng-repeat="item in smartTableData" >
      <td class="table-id">{{item.id}}</td>
      <td>{{item.firstName}}</td>
      <td>{{item.firstName}}</td>
      <td>{{item.lastName}}</td>
      <td>{{item.username}}</td>
      <td><a class="email-link" ng-href="mailto:{{item.email}}">{{item.email}}</a></td>
      <td>{{item.age}}</td>
      <td><button class="glyphicon glyphicon-edit" ng-click="rowform.$show()" />
        <button class="glyphicon glyphicon-remove-sign" ng-click="removeUser($index)"/></td>
    </tr>
  </tbody>
</table> 

也就是显示的空表,对前端也是刚开始接触,于是花了好几个小时排查,终于知道是这个控件的原因,开始看控件文档:

smart-table first creates a safe copy of your displayed collection: it creates another array by copying the references of the items. It will then modify the displayed collection (when sorting, filtering, etc.) based on its safe copy. So if you don’t intend to modify the collection outside of the table, it will be all fine. However, if you want to modify the collection (add item, remove item), or if you load your data asynchronously (via AJAX-Call, timeout, etc.) you will have to tell smart-table to watch the original collection so it can update its safe copy. This is where you use the stSafeSrc attribute.

翻译一下就是,控件做了一个你要显示集合的safe copy, 并使用这个safe copy进行操作。如果你不在table之外对集合进行更改,一切都ok,但是如果你要增删改查这个集合,或者你异步的取数据,那么你必须使用stSafeSrc这个属性去告诉smart-table去关注原始的集合变化,以便及时更新这个safe copy。

很简单的改一下:这里smartTableDataDisplay就是那个safe copy, 而原始数据就是使用属性标注一下: st-safe-src=”smartTableData”

<table st-table="smartTableDataDisplay" class="table table-striped" st-safe-src="smartTableData">
  <thead>
  <tr class="sortable ">
      <th class="table-id" st-sort="id" st-sort-default="true"></th>
      <th st-sort="firstName"></th>
      <th st-sort="firstName"></th>
      <th st-sort="lastName"></th>
      <th st-sort="username">用户名</th>
      <th st-sort="email">邮件</th>
      <th st-sort="age">年龄</th>
    </tr>
  </thead>
  <tbody>
  <tr ng-repeat="item in smartTableDataDisplay" >
      <td class="table-id">{{item.id}}</td>
      <td>{{item.firstName}}</td>
      <td>{{item.firstName}}</td>
      <td>{{item.lastName}}</td>
      <td>{{item.username}}</td>
      <td><a class="email-link" ng-href="mailto:{{item.email}}">{{item.email}}</a></td>
      <td>{{item.age}}</td>
      <td><button class="glyphicon glyphicon-edit" ng-click="rowform.$show()" />
        <button class="glyphicon glyphicon-remove-sign" ng-click="removeUser($index)"/></td>
    </tr>
  </tbody>
</table> 

如此的简单,花了我好几个小时的时间和精力,现在贴出来,帮助一下其他的新手,免得走弯路。

更新操作时,需要使用: scope.smartTableDataOrderItem=[].concat( scope.smartTableDataOrderItem); 来促使smart-table刷新表。

增加一项:在数据库保存后,调用push方法:

var AddItemURI = "/item";
      myFactory.http_req(AddItemURI, "POST", {
            "name": $scope.OrderItem.name,
            "price": $scope.OrderItem.price,
            "amount": $scope.OrderItem.amount
        },
            function (err, results) {

                if (err == "ok") {
                    myFactory.layerMsg({
                        "CN": "添加成功",
                        "EN": "Add Successfully"
                    }, 1);

                    $scope.smartTableDataOrderItem.push({id: results._links.self.href, name: results.name, price: results.price, amount: results.amount});
                } else {
                     myFactory.layerMsg({
                            "CN": "添加失败",
                            "EN": "Add Failed"
                        }, 5);
                }
      });

删除时:

$scope.removeOrderItem = function(orderItemId){

    myFactory.http_req_full(orderItemId, "DELETE", {}, 
      function (err, results) {

                if (err == "ok") {
                    myFactory.layerMsg({
                        "CN": "删除成功",
                        "EN": "delete Successfully"
                    }, 1);
                    var deleteIndex;

                    angular.forEach( $scope.smartTableDataOrderItem, function(element, index) {
                      if(element.id === orderItemId) {
                        deleteIndex = index;
                      }
                    });
                    $scope.smartTableDataOrderItem.splice(deleteIndex,1);
                } else {
                     myFactory.layerMsg({
                            "CN": "删除失败",
                            "EN": "delete Failed"
                        }, 5);
                }
    });

  }

运行的都没有问题,可是在修改时,数据库更改成功,$scope.smartTableDataOrderItem数组里的值也更新了,可是只有列表中的第一项可以刷新显示更改后的值,如果有其他项,都不刷新,只有在更改了第一项,或者又插入新的项目时,才会刷新:

这里写图片描述

如图,只有更新x1时,或者添加了x3时,之前对x2的更改才能显示在列表里面。试了很多办法: 先删除,再插入;重新从数据库里拿整个列表;将更新数组的方法从AJAX请求中拿到外边。。。都不起作用,最后上stackoverflow,用到了小标题上的方法:

myFactory.http_req_full(orderItemId, "PATCH", {
          "name": $scope.OrderItem.name,
          "price": $scope.OrderItem.price,
          "amount": $scope.OrderItem.amount
        },
      function (err, results) {

          if (err == "ok") {
              myFactory.layerMsg({
                  "CN": "更改成功",
                  "EN": "Modify Successfully"
              }, 1);
               var modifyIndex;
                angular.forEach( $scope.smartTableDataOrderItem, function(element, index) {
                  if(element.id === orderItemId) {
                    modifyIndex = index;
                  }
                });
                $scope.smartTableDataOrderItem[modifyIndex] = {id: orderItemId, name: results.name, price: results.price, amount: results.amount};
                $scope.smartTableDataOrderItem=[].concat($scope.smartTableDataOrderItem);
          } else {
               myFactory.layerMsg({
                      "CN": "更改失败",
                      "EN": "Add Failed"
                  }, 5);
          }
      });

原因是: smart-table同过检测数组的长度来判断数组是否有变化,而莫一条数据的变化并不能引起它更新显示(不知道为什么第一条记录更新就可以?)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值