【问题标题】:Reloading angular table does not work when the data is loaded in response to an event响应事件加载数据时,重新加载角度表不起作用
【发布时间】:2017-08-04 19:17:15
【问题描述】:

当通过调用 parent.postMessage("printComments", "*") 在另一个框架中接收到来自 websocket 的新数据时,我需要填充一个角度表:

var app = angular.module('myapp', []);
var printOperation;

function GetFromLocalStorage(key) {
    var items = localStorage.getItem(key);
    console.log(items);
    if (items === null) {
        console.log("item null");
        return null;
    } else {
        if (typeof items != "string") {
            items = JSON.stringify(items);
        }
        return items;
    }
}

app.controller('MyCtrl',
    function ($scope) {
        $scope.printComments = function () {
            //$scope.obj=GetFromLocalStorage("AllComments");
            $scope.obj = [{
                "nome": "first",
                "status": 1,
                "testo": "Rottura rullo 1!!!"
            }, {
                "nome": "second",
                "status": 0,
                "testo": "Rottura rullo fsdfsf!!!"
            }];
            console.log("ricevo evento e ricarico tabella");
            console.log($scope.obj);
        };

        console.log("assegno print operation");
        printOperation = $scope.printComments;
        printOperation();
    }
);
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
    console.log("ricevo messaggio");
    printOperation();
}, false);		
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-controller="MyCtrl" ng-app="myapp">
<table ng-table="commentsTable">
  <tr ng-repeat="item in obj track by $index">
    <td class="plantCell">{{item.nome}}: </td>
    <td class="statusCell">{{item.status}}</td>
    <td class="statusCell">{{item.testo}}</td>
  </tr>
</table>
</div>

如果我在作用域函数内部调用 printOperation,则表会正确更新,如果相反,当收到事件时调用它,则表不会更新.如果是 Swift 或 Java 程序,我会认为我在后台线程上,Javascript 中是否有这样的概念,我如何进入主线程?

【问题讨论】:

  • 我认为您必须使用回调,因为角度之外的 printOperation() 在执行时未定义。因此,您必须以某种方式等待 angulars 执行结束。
  • 不,printOperation函数内部的控制台消息实际上是打印出来的,所以它不仅被加载,而且被执行。这是很自然的,因为一旦加载表就会执行范围函数,而事件在发送事件时到达的时间要晚得多。
  • 自从你放置了 printOperation();在角度范围内。试着把它放在外面然后你就会明白我在说什么。
  • 不幸的是,该函数设置了角度表使用的数组。所以它必须位于范围内。

标签: javascript angularjs multithreading html-table


【解决方案1】:

您正在尝试更新 AngulraJS 范围之外的数据(在事件侦听器中),这就是视图不显示更新值的原因。您需要使用$apply'$applyAsync' 包装您的函数调用以显式启动消化周期。查看一个工作示例:

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

app.controller('MyCtrl',
    function ($scope) {
        //initial data
        $scope.obj = [{
                "nome": "first",
                "status": 1,
                "testo": "Rottura rullo 1!!!"
            }];
            
        //this changes data
        $scope.printComments = function () {
            //$scope.obj=GetFromLocalStorage("AllComments");
            $scope.obj = [{
                "nome": "first",
                "status": 1,
                "testo": "Rottura rullo 1!!!"
            }, {
                "nome": "second",
                "status": 0,
                "testo": "Rottura rullo fsdfsf!!!"
            }];
            console.log("ricevo evento e ricarico tabella");
            console.log($scope.obj);
        };
        
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
        eventer(messageEvent, function (e) {
            console.log("ricevo messaggio");
            //kick in $digest
            $scope.$apply($scope.printComments);
        }, false);	
        
        //emulate message in 3 secs
        setTimeout(function(){ window.dispatchEvent( new Event(messageEvent) ); }, 3000);
    }
);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-controller="MyCtrl" ng-app="myapp">
  <table>
    <tr ng-repeat="item in obj track by $index">
      <td class="plantCell">{{item.nome}}: </td>
      <td class="statusCell">{{item.status}}</td>
      <td class="statusCell">{{item.testo}}</td>
    </tr>
  </table>
</div>

【讨论】:

  • @FabrizioBartolomucci 您使用的是哪个 AngularJS 版本?
  • 我得到了 Uncaught TypeError: $scope.$applyAsync 并且只有一行打印了两个。就此而言,我也有 Uncaught TypeError: $(...).resizable 是代码的另一部分。
  • @FabrizioBartolomucci,是的 - 1.6.5 是最新的。 $applyAsync 是在 1.3 中引入的,所以如果你使用的是 1.2,你应该尝试使用 $apply 来代替它。工作示例已更新。
  • 我尝试加载:ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js,现在我没有收到任何错误,但只有很长的行列表:
【解决方案2】:

感谢大家。这是收集所有建议的有效解决方案:

<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js">
</script>
</head>

<body>
<html>
        <div ng-controller="MyCtrl" ng-app="myapp">
        <table ng-table="commentsTable">
            <tr ng-repeat="item in obj track by $index">
                <td class="plantCell">{{item.nome}}: </td>
            <td class="statusCell">{{item.status}}</td>
            <td class="statusCell">{{item.testo}}</td>
        </tr>
        </table>
        </div>
        <script language="javascript">
            var app=angular.module('myapp', []);
            var printOperation;
            function GetFromLocalStorage(key) {
                var items=localStorage.getItem(key);
                console.log(items);
                if (items===null){
                    console.log("item null");
                    return null;
                } else {
                    items = JSON.parse(items);
                    return items;
                }
            }
            var app = angular.module('myapp', []);

            app.controller('MyCtrl',
                    function ($scope) {
                    $scope.printComments = function () {
                            $scope.obj=GetFromLocalStorage("AllComments");
                    console.log("ricevo evento e ricarico tabella");
                    console.log($scope.obj);
                    };
                    var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
                    var eventer = window[eventMethod];
                    var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
                    eventer(messageEvent, function (e) {
                            console.log("ricevo messaggio");
                            $scope.$applyAsync($scope.printComments);
                    }, false);  
                }
        );      
        </script>

【讨论】:

  • 你不应该接受我的回答吗?由于它解决了原始问题,但其他问题是由GetFromLocalStorage 方法引起的,该方法甚至在问题正文中被注释掉,甚至与问题本身无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 2017-11-27
相关资源
最近更新 更多