#javascript #jquery #html #knockout.js #foreach
#javascript #jquery #HTML #knockout.js #foreach
Вопрос:
Я получаю json
ответ от своего сервера и пытаюсь сопоставить его с наблюдаемым массивом, а затем отобразить результаты внутри HTML
таблицы. Что я получаю от сервера, так это эту строку:
{"ids":[1,2,3,4],"names":["1","2","test tracker","test1"],"creators":["1","test","test","test"],"projectNames":["1","1","test project","test"]}
Теперь вот что я пытаюсь сделать в своей модели представления:
У меня есть этот объект, который должен содержать значения:
trackersObj = function(item){
this.trackerId = item.ids;
this.trackerName = item.names;
this.trackerCreator = item.creators;
this.projectNames = item.projectNames;
};
И это ko.observableArray
должно содержать результаты и зацикливать их в теле таблицы:
trackersObjArray = ko.observableArray([])
И вот как я делаю сопоставление:
loadActiveTrackers = function () {
$.ajax({
type: 'POST',
url: 'controller.php',
dataType: 'json',
data: {
action: "loadActiveTs"
},
success: function (data) {
trackersObjArray.push(new trackersObj(data));
console.log(trackersObjArray());
$('#allTrackers').show();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('Something got wrong!');
}
});
};
Наконец, это мой HTML
:
<table class="dataTable" id="CADataTable">
<thead>
<tr>
<th>Test</th>
</tr>
</thead>
<tbody data-bind="foreach: trackersObjArray">
<tr>
<td>
<input type="text" name="test" data-bind="value: trackerName">
</td>
</tr>
</tbody>
</table>
Проблема в том, что в tbody
‘s td
все результаты отображаются в одной строке.
Вот что я имею в виду:
Предполагается, что он создает столько строк, сколько количество записей. Почему это происходит? Я действительно не могу понять, что я делаю не так. Я знаю, что мне не хватает очень маленькой части, но я не могу ее обнаружить в данный момент.
PS
Вот вывод console.log(trackersObjArray());
Ответ №1:
Ваш сервер отправляет несколько объектов, а не один. Он просто делает это необычным способом:
{
"ids": [1,2,3,4],
"names": ["1","2","test tracker","test1"],
"creators": ["1","test","test","test"],
"projectNames": ["1","1","test project","test"]
}
действительно должно выглядеть так
[
{"id": 1, "name": "1", "creator": "1", "projectName": "1"},
{"id": 2, "name": "2", "creator": "test", "projectName": "1"},
{"id": 3, "name": "test tracker", "creator": "test", "projectName": "test project"},
{"id": 4, "name": "test1", "creator": "test", "projectName": "test"}
]
Следовательно, вы должны помещать свои trackersObj
объекты в цикл. Для этого есть несколько вариантов.
Сначала вы должны решить, хотите ли вы
- Обновите код вашего сервера, чтобы сразу отправить правильную структуру объекта (предпочтительно), или
- оставьте сервер как есть и преобразуйте объект на клиенте.
Поскольку я не вижу ваш серверный код, я выбираю вариант 2
loadActiveTrackers = function () {
$.post('controller.php', {
action: "loadActiveTs"
}).then(function (rawData) {
// transformation step. if you fix your server to send proper data
// you can drop the entire then().
var i, transformedData = [];
for (i = 0; i < rawData.ids.length; i ) {
transformedData.push({
id: rawData.ids[i],
name: rawData.namess[i],
creator: rawData.creators[i],
projectName: rawData.projectNames[i]
});
}
return transformedData;
}).done(function (transformedData) {
ko.utils.arrayForEach(transformedData, function (tracker) {
trackersObjArray.push(new trackersObj(tracker));
});
}).fail(function (XMLHttpRequest, textStatus, errorThrown) {
alert('Something got wrong!');
});
};
Это «ручной» способ. Вы могли бы обойтись без цикла for-each и вместо этого заменить значение trackersObjArray
за один шаг ( trackersObjArray(transformedData);)
. Вы также можете использовать плагин сопоставления для более сложных сопоставлений данных с viewmodel.
Вы не должны использовать jQuery в своей модели представления (или каким-либо иным образом ссылаться на DOM), потому что это излишне привязывает вашу модель представления к вашему представлению. Зависимость должна быть только наоборот.
Другими словами, $('#allTrackers').show();
не должно быть в модели представления. Используйте visible
привязку.
Комментарии:
1. вау. Понятно. Проблема в том, что я работаю на стороне сервера
php
, и я в некотором роде новичок в этом. Я отредактировал свой вопрос и поместилphp
туда код. Не могли бы вы взглянуть? 🙂2. Ваш PHP-код действительно легко исправить. Просто посмотрите на мой пример JSON «как это должно выглядеть» и подумайте пару минут. Вы разберетесь сами, я абсолютно уверен. (И это тоже принесет больше удовлетворения.)
3. @chility О, и еще одно: если вы на самом деле не обновляете данные на сервере (а это не похоже), используйте
$.get()
вместо$.post()
.