2015-11-13 12 views
6

ho un problema quando vincolante valore di data al testo utilizzando eliminazione diretta, come si vede nella foto qui sotto enter image description hereBinding Data utilizzando Knockoutjs

Quando la pagina viene caricata per la prima volta, sto usando Ajax per ottenere i dati AccountStatements.

function AccountStatementViewModel(companyID) { 
    var self = this; 
    ... 
    var AccountStatement = { 
     AccountStatementID: self.AccountStatementID, 
     CompanyID: self.CompanyID, 
     Description: self.Description, 
     Amount: self.Amount, 
     ReceiptDate: self.ReceiptDate, 
     Type: self.Type 
    } 

    self.AccountStatement = ko.observable(); 
    self.AccountStatements = ko.observableArray(); 

    $.ajax({ 
     url: webroot + 'AccountStatement/GetAccountStatements', 
     contentType: 'application/json; charset=utf-8', 
     data: { id: self.CompanyID }, 
     cache: false 
    }).done(function (data) { 
     self.AccountStatements(data); 
    }); 
    ... 
    self.edit = function (accountStatement) { 
     $('#lnkAddAccountStatement').hide('blind', 1000); 
     $('#pnlAddEditAccountStatement').show('blind', 1000); 
     self.AccountStatement(accountStatement); 
    } 
    ... 
} 

Il controller restituisce il risultato in JSON:

public JsonResult GetAccountStatements(int id) 
{ 
    var accountStatementsVM = db.AccountStatements 
     .Where(a => a.CompanyID == id) 
     .Select(a => new AccountStatementViewModel 
     { 
      AccountStatementID = a.AccountStatementID, 
      CompanyID = a.CompanyID, 
      Description = a.Description, 
      Amount = a.Amount, 
      ReceiptDate = a.ReceiptDate, 
      Type = a.Type 
     }) 
     .ToList(); 

    return Json(accountStatementsVM, JsonRequestBehavior.AllowGet); 
} 

formica il risultato è:

[{"AccountStatementID":2,"CompanyID":1,"Description":"test","Amount":1000,"ReceiptDate":"/Date(1447261200000)/","Type":"Payment"}] 

nella vista, io lo mostro utilizzando questo codice:

<tbody data-bind="foreach: AccountStatements, visible: AccountStatements().length > 0"> 
    <tr> 
     <td data-bind="attr: { id: AccountStatementID }"> 
      <a href="#" class="btn btn-primary btn-xs" data-bind="click: $root.edit"><i class="glyphicon glyphicon-pencil"></i></a> 
      <a href="#" class="btn btn-danger btn-xs" data-bind="click: $root.delete"><i class="glyphicon glyphicon-remove"></i></a> 
     </td> 
     <td data-bind="text: Description"></td> 
     <td data-bind="text: Amount"></td> 
     <td data-bind="date: ReceiptDate"></td> 
    </tr> 
</tbody> 

Ecco il codice per formattare la data:

ko.bindingHandlers.date = { 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor()); 
     var textContent = moment(valueUnwrapped).format("DD/MM/YYYY"); 
     ko.bindingHandlers.text.update(element, function() { return textContent; }); 
    } 
}; 

A questo punto, la data viene visualizzata nel formato giusto, quindi se ho cliccato pulsante di modifica, il ReceiptDate nella casella di testo non è formattato.

Codice in ReceiptDate TextBox:

<input type="text" placeholder="Enter Receipt Date" class="form-control fdatepicker" readonly="readonly" data-bind="value: AccountStatement().ReceiptDate" /> 

Se cambio al data-bind="date: AccountStatement().ReceiptDate" la casella di testo sarà vuota.

Come formattare la data nella casella di testo?

UPDATE

ho cambiato la data gestore vincolante come in questo link ma il valore TextBox del ReceiptDate è ancora /Date(1447261200000)/

Cambiamenti in vista:

<input type="text" placeholder="Enter Receipt Date" class="form-control fdatepicker" readonly="readonly" data-bind="date: AccountStatement().ReceiptDate" /> 

e la data di la ricevuta nel tavolo è vuota:

<td data-bind="date: ReceiptDate"></td> 
+0

qualcosa di simile http://jsfiddle.net/LkqTU/27696 /. evviva –

+0

@supercool grazie per il collegamento ma non funziona. Nel link qui sopra, si usa il formato di data comune (gg/mm/aaaa), mentre nel mio caso il valore della data è in formato data json/data (1447261200000)/'. Ho modificato la mia domanda per fornire ulteriori informazioni. – Willy

+0

prova l'impostazione 'self.ReceiptDate = ko.observable (1447261200000);' e controlla, funziona ancora. il momento decodificherà fino alla data e il formato specificato. –

risposta

0

Nel tuo aggiornamento, $root.ReceiptDate non esiste. ReceiptDate è un membro dei dati AccountStatement. È importante tenere traccia dei livelli di contesto.

tuo date vincolante fisserà un value, quindi non è possibile utilizzarlo per qualcosa che avrebbe preso un text vincolante (come un td nel tuo esempio di aggiornamento).

Non è necessario un binding per questo, è solo bisogno di una funzione di formattazione, che è possibile utilizzare in qualsiasi associazione che si sceglie. Se si desidera poter modificare il valore, è necessario creare un valore writable computed in base al valore della data e utilizzarlo in un'associazione value. Non lo dimostro qui.

ajaxData = [{ 
 
    "AccountStatementID": 2, 
 
    "CompanyID": 1, 
 
    "Description": "test", 
 
    "Amount": 1000, 
 
    "ReceiptDate": "/Date(1447261200000)/", 
 
    "Type": "Payment" 
 
}]; 
 

 

 
vm = { 
 
    AccountStatements: ko.observableArray(ajaxData), 
 
    formatDate: function(textValue) { 
 
    return moment(textValue).format("DD/MM/YYYY"); 
 
    } 
 
}; 
 

 
ko.applyBindings(vm); 
 

 
// Add a row 
 
setTimeout(function() { 
 
    vm.AccountStatements.push({ 
 
    "AccountStatementID": 2, 
 
    "CompanyID": 1, 
 
    "Description": "test", 
 
    "Amount": 1000, 
 
    "ReceiptDate": "/Date(1448271200000)/", 
 
    "Type": "Payment" 
 
    }) 
 
}, 2500);
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script> 
 
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> 
 
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" /> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<table border=1> 
 
    <tbody data-bind="foreach: AccountStatements, visible: AccountStatements().length > 0"> 
 
    <tr> 
 
     <td data-bind="attr: { id: AccountStatementID }"> <a href="#" class="btn btn-primary btn-xs" data-bind="click: $root.edit"><i class="glyphicon glyphicon-pencil"></i></a> 
 
     <a href="#" class="btn btn-danger btn-xs" data-bind="click: $root.delete"><i class="glyphicon glyphicon-remove"></i></a> 
 

 
     </td> 
 
     <td data-bind="text: Description"></td> 
 
     <td data-bind="text: Amount"></td> 
 
     <td data-bind="text: $parent.formatDate(ReceiptDate)"></td> 
 
     <td> 
 
     <input type="text" class="form-control fdatepicker" readonly="readonly" data-bind="value: $parent.formatDate(ReceiptDate)" /> 
 
     </td> 
 
    </tr> 
 
    </tbody> 
 
</table>

+0

Ho provato a usare la scrittura scrivibile, ma ancora non funziona. Il problema è quando si fa clic sul pulsante di modifica, la data (nella casella di testo) non è formattata e il datapicker del calendario non viene visualizzato. http://jsfiddle.net/qdh9jw94/5/ – Willy

+0

Hai l'input segnato 'readonly', per uno. Il tuo datepicker probabilmente ha bisogno di un gestore di binding personalizzato. http://stackoverflow.com/questions/13629910/jquery-ui-datepicker-with-knockout-js Probabilmente hai bisogno di fare una nuova domanda. –

+0

@Willy La tua funzione di modifica riceve i suoi dati 'accountStatement' dai' dati' unwrapped che hai assegnato a 'AccountStatements'. –

1

Facendo un Biding personalizzato è un peso inutile.Il tuo binding personalizzato non sta facendo nulla degno di un binding personalizzato.

Tutto ciò che serve è un osservabile calcolato che restituisce il formato di testo della data corrente.

Diciamo che avete questa variabile da qualche parte:

var myDate = ko.observable(); 

E da qualche parte si dispone di codice che mette qualche oggetto data in esso:

myDate(input); // where input is some date object you got somehow from somewhere 

Ora tutto ciò che serve è questo:

myDate.formatted = ko.pureComputed(function() { 
    return moment(myDate()).format("DD/MM/YYYY"); 
}); 

Ora è possibile utilizzare solo una normale rilegatura di testo:

(ammesso che abbiate myDate nel modello di visualizzazione legato a questa visione)

<td data-bind="text: myDate.formatted"></td> 

NOTA:

Non c'è niente di speciale myDate.formatted. Se ci pensi, myDate è solo una funzione, e le funzioni sono oggetti in modo da poterli allegare a campi arbitrari.

E 'davvero non è diverso a tutti di creare una nuova variabile in questo modo:

var myFormattedDate = ko.pureComputed(function() { 
    return moment(myDate()).format("DD/MM/YYYY"); 
}); 

e di utilizzarlo in un vincolante:

<td data-bind="text: myFormattedDate"></td> 
+0

Questo è ancora più semplice quando viene estratto in un extender: 'ko.extenders.formattedDate = function() {...}' e quindi usato come 'myDate.extend ({formattedDate:" DD/MM/YYYY "})'. L'ovvio vantaggio è la riusabilità, l'associazione può rimanere la stessa. – Tomalak

+0

Non funziona, la data nella tabella non appare, ecco il link http://jsfiddle.net/qdh9jw94/6/. In realtà, il problema è come associare la data al TextBox ReceiptDate quando ci si trova in modalità di modifica (facendo clic sul pulsante di modifica) – Willy