ko calcolato non mostrando in vista
-
21-12-2019 - |
Domanda
Ho alcuni problemi relativi a vincolanti al valore calcolato. Sto mostrando i dati nella tabella e riassumendo alcuni campi. Nel footer voglio visualizzare la somma di quei campi e la colonna vuota, così come una con testo di totale. I valori vengono memorizzati all'interno dei campi, oltre ad essere aggiornati quando il valore dei campi di riferimento cambia, ma non viene visualizzato nella vista. So che ho fatto qualcosa di sbagliato con Ko.Computed, ma non posso individuare quello che sarebbe.
Codice HTML:
<table>
<caption><h4 class="pull-left">Caption</h4></caption>
<thead>
<tr data-bind="foreach: ColModel">
<th data-bind="text: Caption"></th>
</tr>
</thead>
<tbody data-bind="foreach: { data: model, as: 'row' }">
<tr data-bind="foreach: { data: $root.ColModel, as: 'col' }">
<td data-bind="text: row[col.Field], css: { hidden: col.InSum != false }">
</td>
<td data-bind="css: { hidden: col.InSum != true }">
<input type="number" step="any" class="input-small" data-bind="value:row[col.Field], valueUpdate: 'afterkeydown'" />
</td>
</tr>
</tbody>
<tfoot>
<tr data-bind="foreach: footmodel">
<td data-bind="text: Value">
</td>
</tr>
</tfoot>
</table>
.
Iin mio js ho
clientViewModel.ColModel = ko.observableArray([
{
Caption: 'cap1',
InSum: false,
Field: 'FLD1'
},
{
Caption: 'cap2',
InSum: false,
Field: 'FLD2'
},
{
Caption: 'capsum1',
InSum: true,
Field: 'fldsum1'
},
{
Caption: 'capsum2',
InSum: true,
Field: 'fldsum2'
}
]);
clientViewModel.model = ko.observableArray();
clientViewModel.footmodel = ko.observableArray([
{
Value: '',
IsSum: false
},
{
Value: 'total',
IsSum: false
},
{
Value: '',
IsSum: true,
SumField: 'fldsum1'
},
{
Value: '',
IsSum: true,
SumField: 'fldsum2'
}
]);
.
La funzione Ajax è solo un minuscolo involucro intorno a $ .ajax Function che usiamo nel progetto per recuperare i dati.
ajax('modelurl'),
'GET',
true,
function (data, status) {
$.each(data.Records, function (index, value) {
var observableValue = makeObservable(value, clientViewModel.ColModel);
clientViewModel.model.push(observableValue);
});
$.each(clientViewModel.footmodel(), function (index, value) {
if (value['IsSum']) {
clientViewModel.footmodel()[index]['Value'] = ko.computed(function () {
var sum = 0;
$.each(clientViewModel.model(), function (i, data) {
sum = parseFloat(sum) + parseFloat(data[value['SumField']]());
});
return sum.toString();
}, clientViewModel);
}
else
value['Value'] = ko.observable(value['Value']);
});
});
.
Inoltre, MakeObservable viene utilizzato per rendere osservabili i campi di un oggetto. Come ho scoperto, tutti i campi collegati a calcolati devono essere osservabili, quindi l'aggiornamento può innescare.
function makeObservable(model, fields) {
var ret = {};
$.each(fields(), function (index, value) {
ret[value.Field] = ko.observable(model[value.Field]);
})
return ret;
}
.
Cosa succede è sconosciuto per me. I campi osservabili del footmodel vengono stampati, mentre calcolati non lo fanno. Tutti i campi di clientviewModel.Model L'array osservabile è osservabile, i valori vengono calcolati, ma non vengono stampati. Qual è il motivo per questo?
Una soluzione possibile, per quanto ne vedo, potrebbe essere quello di innescare la funzione che calcola i valori da riattivare e memorizza nel campo osservabile, che dovrebbe essere stampato OK. Ma preferirei farlo funzionare in questo modo e scoprire cosa causa questo comportamento.
Grazie.
Soluzione
Immagino che inizi ko.applyBindings(...)
al di fuori della chiamata Ajax, il che significa
<tr data-bind="foreach: footmodel">
<td data-bind="text: Value">
</td>
</tr>
.
Il text: Value
si lega alla stringa vuota originale, anche si sostituisce il contenuto del contenuto del Value
in Ajax con un ko.computed(...)
, il sistema di rilegatura non lo sa.
Per fissarlo, utilizzare un legame if
per forzare il knockout per re-analizzare il rilegatura (l'intera tabella) dopo Ajax.
HTML
<!-- ko ifnot: loading -->
<table> ... </table>
<!-- /ko -->
.
JS
clientViewModel.loading = ko.observable(false);
// begin ajax
clientViewModel.loading(true); // ko removes the table from DOM
$.ajax({...,
success: function(data, status) {
//... built your ko.computed
},
complete: function() {
// finish ajax
clientViewModel.loading(false); // ko re-creates the table in DOM
}
});
.