Domanda

Si prega di considerare la seguente vista:

<p>Count <span data-bind="text: unreadCount()">&nbsp;</span></p>
<div data-bind='template: { name: "conversationTemplate", data: currentList }'> </div>
<script type="text/html" id="conversationTemplate">
 <table>
  <tbody>
   {{each $data}}
    <tr id="conversation_${conversation_id}" class="conversation-item ${status}">
     <td><input type="checkbox" data-bind="click: function() { alert(this.value) }, checked: read" /></td>
    </tr>
   {{/each}}
  </tbody>
 </table>
</script>

E il seguente codice:

$(function() {

 var viewModel = {
  currentList : ko.observableArray([])
 };

 ko.dependentObservable(function () {
  $.ajax({
   url: '/conversations/inbox.json', dataType: 'json',
   success: function(data) {
    viewModel.currentList(data.conversationlist);
   }
  });  
 }.bind(viewModel));

 viewModel.unreadCount = ko.dependentObservable(function() {
  var unreadCount = 0;
  for (var i = 0; i < viewModel.currentList().length; i++)
   if (viewModel.currentList()[i].read == true) {
    unreadCount++;
   }
  return unreadCount;
 });

 ko.applyBindings(viewModel);

Gli appare sopra a lavorare, anche se non sono sicuro se ho costruito questo correttamente. Quello che voglio imparare a fare è quando si modifica un casella di controllo , come avere il unreadCount essere aggiornato automaticamente per riflettere il cambiamento. Ho pensato che l'utilizzo ko fornirebbe questo automaticamente, ma forse ho bisogno di fare qualcosa in casella dei dati-bind del modello?

Inoltre, una volta posso modificare la casella di controllo e hanno che si aggiornano automaticamente il conteggio Vista Modello e non letti, qual è il modo giusto per poi Post che l'aggiornamento al server (Rails)?

Ecco un esempio risposta JSON dal server:

{
    "conversationlist": [{
        "project_name": "Proj 1",
        "preview": "xxxxx",
        "status": "unread",
        "participants": [{
            "image": "XXXXXX"
        }, {
            "image": "XXXXXX"
        }],
        "conversation_id": 193,
        "title": "Hi Ho",
        "time_ago": "1 day",
        "read": true
    }, {
        "project_name": "Proj 2",
        "preview": "xxxx",
        "status": "unread",
        "participants": [{
            "image": "XXXXXX"
        }, {
            "image": "XXXXXX"
        }],
        "conversation_id": 193,
        "title": "Hi Ho",
        "time_ago": "1 day",
        "read": true
    }, {
        "project_name": "Proj 3",
        "preview": "xxxxx",
        "status": "unread",
        "participants": [{
            "image": "XXXXXX"
        }, {
            "image": "XXXXXX"
        }],
        "conversation_id": 193,
        "title": "Hi Ho",
        "time_ago": "1 day",
        "read": true
    }]
}
È stato utile?

Soluzione

Sembra che si potrebbe eseguire una funzione in clicca (all'interno data-bind='click: function() {...}') per ciascuna voce che incrementa o decrementa il contatore non letto a seconda del valore della casella di controllo che è stato registrato. In questo modo, non avrebbe mai dovuto scorrere l'currentList e aggiornare il conteggio non letti in questo modo.

Si potrebbe anche iscriversi alla proprietà read del ViewModel in modo esplicito ed eseguire il proprio codice quando cambia read (vedere "in modo esplicito la sottoscrizione di osservabili" in mezzo al osservabili documentazione ).

Modifica : rel Ecco un thread in cui un utente descrive come impostare una matrice osservabile con elementi con proprietà osservabili. Ecco 's un esempio che l'autore (Steve Sanderson) si avvicinò con dimostrando un array osservabili con proprietà osservabili.

Con entrambi i metodi, sembra che è possibile eseguire una chiamata AJAX per POST al server.

Aggiorna : Ecco un esempio di come si potrebbe implementare questa:

$(function() {
    var initialData = {/*Data retrieved by AJAX or on page load*/};

    var markRead = function(conversation) {
        // Make AJAX POST here to update read status of
        // the conversation
    };

    // Convenience object for conversations.
    var Conversation = function(conversation_id, status, read) {
        this.conversation_id = conversation_id;
        this.status = status;
        this.read = ko.observable(read);
    };

    var initialUnread = 0;

    var viewModel = {
        // Map the conversation list to a new array containing
        // objects with observable properties.
        conversationList: ko.observableArray(ko.utils.arrayMap(
        initialData.conversationlist, function(data) {
            if (!data.read === false) {
                initialUnread++;
            }
            return new Conversation(
                data.conversation_id,
                data.status,
                data.read);
        })),
        unreadCount: ko.observable(initialUnread),

        // Executed when the user toggles a conversation's
        // read status.
        toggleRead: function(conversation) {
            // Update the unread count.
            viewModel.unreadCount(
                viewModel.unreadCount() + 
                (conversation.read() ? 1 : -1));

            // Update the conversation via AJAX
            markRead(conversation);
            return true;
        }
    };
    ko.applyBindings(viewModel);
});

Demo qui .

Note:

  • non utilizza il plug-in mapping. La logica generale dovrebbe essere lo stesso però.
  • Se la chiamata AJAX fallisce, probabilmente si dovrebbe aggiornare la casella di controllo con il suo status prima del click.
  • È possibile aggiornare la proprietà unreadCount nel ViewModel ovunque chiamando viewModel.unreadCount(<value>).
  • Questo si basa su alcuni degli esempi, in particolare questo . Gli esempi complessi sono particolarmente aprire gli occhi e dimostrano alcune cose fresco si può fare con il KO.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top