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.

È stato utile?

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
  }
});
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top