Угловой контроллер не отображает данные из JSON
Я использую Angular и TingoDB (Mongo) внутри Node Webkit для одностраничного приложения. Однако у меня есть странная проблема, которую я не смог решить.
Когда я использую литерал объекта (вариант 2), данные корректно отображаются на html-странице. Однако при изменении кода для возврата данных из базы данных (вариант 1) результаты не отображаются на html-странице. Я преобразовал оба стиля данных в строку JSON, чтобы доказать согласованность, а затем использовал angular.fromJSON, чтобы вернуть объект. Оба метода возвращают одну и ту же строку JSON в console.log, и, прежде чем кто-либо спросит, я закомментировал вариант 1 или 2, поэтому оба они не работают одновременно.
Я скопировал строку JSON, основанную на данных, переданных из TingoDB, в console.log и повторно ввел ее в приведенный ниже код, чтобы убедиться, что между двумя версиями данных не было никаких различий без изменения какого-либо другого кода, но проблема по-прежнему сохраняется.
Может кто-нибудь пролить свет на то, почему это происходит и как это исправить?
var app = angular.module('myApp', []);
var Engine = require('tingodb')(),
assert = require('assert');
var db = new Engine.Db('./db', {});
var collection = db.collection("clean.db");
app.controller('tingoDataCtrl', ['$scope', function($scope) {
function getData(callback) {
//Option 1
collection.find().toArray(function(err, docs){
callback (JSON.stringify(docs));
});
//Option 2
var docs = [
{name:"tingo1", description:"56",_id:2},
{name:"tingo2", description:"33",_id:3},
{name:"tingo3", description:"22",_id:4},
{name:"tingo4", description:"76",_id:5},
{name:"tingo5", description:"99",_id:6}
];
callback (JSON.stringify(docs));
}
function info(b) {
// I'm the callback
console.log(b);
$scope.items = angular.fromJson(b)
}
getData(info);
}]);
И HTML
<body ng-app="myApp" id="main">
<div class="page page-data ng-scope">
<section class="panel panel-default" ng-controller="tingoDataCtrl">
<div class="panel-heading"><span class="glyphicon glyphicon-th"></span> Tingo Data</div>
<table class="table">
<thead>
<th class="col-md-4">
Name
</th>
<th class="col-md-8">
Description
</th>
<th class="col-md-8">
ID
</th>
<th></th>
<tr>
</tr>
</thead>
<tbody>
<!-- <tr class="reveal-animation" ng-repeat="item in items | filter:query"> -->
<tr ng-repeat="item in items | filter:query">
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item._id}}</td>
</tr>
</tbody>
</table>
</section>
</div>
<script src="js/tingo_problem.js"></script>
</body>
1 ответ
TingoDB - это асинхронный API, который будет работать в фоновом режиме без остановки вашего приложения. Это означает, что у синхронного кода нет времени ждать ответа, а взамен он дает неопределенное.
В вашем случае вы выполнили асинхронный вызов, и он правильно возвращает ответ в память, но слишком поздно, DOM уже обновлен с неопределенным, даже если ваш javascript имеет данные (попробуйте console.log, чтобы увидеть, что это было там).
В Angular есть способ принудительно обновить DOM новыми элементами контроллера. это называется $apply. И лучший способ использовать его, чтобы избежать неожиданного поведения:
function info(b) {
// I'm the callback
console.log(b);
$scope.items = angular.fromJson(b);
if (!$scope.$$phase) {
$scope.$apply(); //forces update the view
}
}//$scope is NECESARY to be defined in the controler, avoid using it with "ControlerAs"