2016-03-28 13 views
0

Mit einem KnockBack ViewModel, gibt es eine Möglichkeit, ein berechnetes Observable aus den zugrunde liegenden Methoden des Backbone-Modells zu erstellen?Kann mit KnockBack ViewModel eine berechnete Observable aus den Methoden des zugrunde liegenden Backbone-Modells erstellt werden?

Als Beispiel in javascript:

var MyModel = Backbone.model.extend({ 
     validate: function() { 
      return this.get('name').length < 0; 
     } 
    }), 
    baseModel = new MyModel({name: 'foo'}), 
    kbViewModel = kb.viewModel(baseModel), 
    modelContainer = document.querySelector('#myModel'); 
ko.applyBindings(kbViewModel, modelContainer); 

und in dem K.-o.-Markup:

<div id="myModel"> 
    <div data-bind="css:{'invalid': !validate()}"> 
     <input type="text" data-bind="value: name" /> 
    </div> 
</div> 

Wenn ich versuche, dies auszuführen, erhalte ich die Fehlermeldung:

Unable to process binding "css: function(){return {'invalid':!validate()} }" 
Message: validate is not defined 

Mache ich etwas falsch oder muss ich das Observable im ViewModel manuell erstellen?

var MyModel = Backbone.Model.extend({ 
     validate: function() { 
      return this.get('name').length > 0; 
     } 
    }), 
    MyKBViewModel = kb.ViewModel.extend({ 
     constructor: function (model) { 
      kb.ViewModel.prototype.constructor.call(this, model); 
      this.validate = ko.pureComputed(function() { 
       return this.name().length > 0; 
      }, this); 
     } 
    }), 
    baseModel = new MyModel({name: 'foo', class: 'bar'}), 
    kbViewModel = new MyKBViewModel(baseModel), 
    modelContainer = document.querySelector('#myModel'); 

ko.applyBindings(kbViewModel, modelContainer); 

jsfiddles: without observable, with observable

Antwort

1

Ein wenig Präambel: Wegstoßung das Modell in MVVM bringt, wo Knockout VVM wirklich gerade ist. Knockback gibt Ihnen auch eine automatische Synchronisation zwischen ihnen, was nett ist. Sie sollten jedoch nicht vergessen, dass das Modell und das Ansichtsmodell zwei verschiedene Teile Ihrer App sind. Das Viewmodel ist nicht nur eine Knockout-Kopie des Bootstrap-Modells. Stellen Sie keine Viewmodel-Teile in das Modell.

Sie müssen also entscheiden, ob Validierung ein Viewmodel-Verhalten oder ein Modellverhalten ist. Ich sage viewmodel, weil Sie es in der Ansicht verwenden möchten. Also entfernen Sie es aus dem Modell und definieren Sie eine berechnete.

Wie auch immer,, wenn Sie möchten, dass es Teil des Modells ist, würden Sie ein Attribut definieren, nicht nur eine Methode und einen Modell-Event-Handler, der das Attribut bei Änderung aktualisiert. Rückwirkend kopiert das Attribut pflichtbewusst in das Viewmodel, und Sie können es dort verwenden.

var MyModel = Backbone.Model.extend({ 
 
    validate: function() { 
 
     this.set('isValid', this.get('name').length > 0); 
 
    }, 
 
    initialize: function() { 
 
     this.validate(); 
 
     this.on('change:name', this.validate); 
 
    } 
 
    }), 
 
    baseModel = new MyModel({ 
 
    name: 'foo', 
 
    isValid: null 
 
    }), 
 
    kbViewModel = kb.viewModel(baseModel); 
 

 
kbViewModel.validate = ko.observable(); 
 

 
modelContainer = document.querySelector('#myModel'); 
 

 
ko.applyBindings(kbViewModel, modelContainer);
.invalid { 
 
    background-color: red; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockback/1.0.0/knockback.min.js"></script> 
 
<div id="myModel"> 
 
    <div data-bind="css:{'invalid': !isValid()}"> 
 
    <input type="text" data-bind="value: name" /> 
 
    </div> 
 
</div>