Validação do assistente Knockout.js em cada etapa

Eu consegui criar um assistente simples baseado em uma resposta dada por Niemeyer. Isso funciona bem. Eu quero adicionar validação. Eu consegui adicionar uma validação necessária no campo Firstname. Deixar isso vazio exibe um erro. Mas o que eu não consegui fazer é o seguinte: Valide o modelo na etapa atual, e o próximo passo será habilitado ou desabilitado se houver erros. Se for muito difícil ativar ou desativar o próximo botão, tudo bem. Eu também posso viver sem o botão desativado quando houver erros. Contanto que o usuário seja impedido de prosseguir para a próxima etapa quando houver erros.

. Minha visão é assim:

 //model is retrieved from server model
 <script type="text/javascript">
     var serverViewModel = @Html.Raw(Json.Encode(Model));
 </script>


<h2>Test with wizard using Knockout.js</h2>
  <div data-bind="template: { name: 'currentTmpl', data: currentStep }"></div> 
<hr/>

<button data-bind="click: goPrevious, enable: canGoPrevious">Previous</button>
<button data-bind="click: goNext, enable: canGoNext">Next</button>

<script id="currentTmpl" type="text/html">
    <h2 data-bind="text: name"></h2>
    <div data-bind="template: { name: getTemplate, data: model }"></div> 
</script>

<script id="nameTmpl" type="text/html">
    <fieldset>
        <legend>Naamgegevens</legend>
        <p data-bind="css: { error: FirstName.hasError }">
            @Html.LabelFor(model => model.FirstName)
            @Html.TextBoxFor(model => model.FirstName, new { data_bind = "value: FirstName, valueUpdate: 'afterkeydown'"})
            <span data-bind='visible: FirstName.hasError, text: FirstName.validationMessage'> </span>
        </p>
        @Html.LabelFor(model => model.LastName)
        @Html.TextBoxFor(model => model.LastName, new { data_bind = "value: LastName" })
    </fieldset>
</script>

<script id="addressTmpl" type="text/html">
    <fieldset>
        <legend>Adresgegevens</legend>
        @Html.LabelFor(model => model.Address)
        @Html.TextBoxFor(model => model.Address, new { data_bind = "value: Address" })
        @Html.LabelFor(model => model.PostalCode)
        @Html.TextBoxFor(model => model.PostalCode, new { data_bind = "value: PostalCode" })
        @Html.LabelFor(model => model.City)
        @Html.TextBoxFor(model => model.City, new { data_bind = "value: City" })
    </fieldset>
</script>

<script id="confirmTmpl" type="text/html">
        <fieldset>
        <legend>Naamgegevens</legend>
        @Html.LabelFor(model => model.FirstName)
        <b><span data-bind="text:NameModel.FirstName"></span></b>
        <br/>
        @Html.LabelFor(model => model.LastName)
        <b><span data-bind="text:NameModel.LastName"></span></b>
    </fieldset>
    <fieldset>
        <legend>Adresgegevens</legend>
        @Html.LabelFor(model => model.Address)
        <b><span data-bind="text:AddressModel.Address"></span></b>
        <br/>
        @Html.LabelFor(model => model.PostalCode)
        <b><span data-bind="text:AddressModel.PostalCode"></span></b>
        <br/>
        @Html.LabelFor(model => model.City)
        <b><span data-bind="text:AddressModel.City"></span></b>           
    </fieldset>
    <button data-bind="click: confirm">Confirm</button>
</script>

<script type='text/javascript'>
    $(function() {
        if (typeof(ViewModel) != "undefined") {
            ko.applyBindings(new ViewModel(serverViewModel));
        } else {
            alert("Wizard not defined!");
        }
    });
</script>

A implementação do knockout.js é assim:

function Step(id, name, template, model) {
    var self = this;
    self.id = id;
    self.name = ko.observable(name);
    self.template = template;
    self.model = ko.observable(model);

    self.getTemplate = function() {
        return self.template;
    };
}

function ViewModel(model) {
    var self = this;

    self.nameModel = new NameModel(model);
    self.addressModel = new AddressModel(model);

    self.stepModels = ko.observableArray([
            new Step(1, "Step1", "nameTmpl", self.nameModel),
            new Step(2, "Step2", "addressTmpl", self.addressModel),
            new Step(3, "Confirmation", "confirmTmpl", {NameModel: self.nameModel, AddressModel:self.addressModel})]);

    self.currentStep = ko.observable(self.stepModels()[0]);

    self.currentIndex = ko.dependentObservable(function() {
        return self.stepModels.indexOf(self.currentStep());
    });

    self.getTemplate = function(data) {
        return self.currentStep().template();
    };

    self.canGoNext = ko.dependentObservable(function () {
        return self.currentIndex() < self.stepModels().length - 1;
    });

    self.goNext = function() {
        if (self.canGoNext()) {
            self.currentStep(self.stepModels()[self.currentIndex() + 1]);
        }
    };

    self.canGoPrevious = ko.dependentObservable(function() {
        return self.currentIndex() > 0;
    });

    self.goPrevious = function() {
        if (self.canGoPrevious()) {
            self.currentStep(self.stepModels()[self.currentIndex() - 1]);
        }
    };
}

NameModel = function (model) {

    var self = this;

    //Observables
    self.FirstName = ko.observable(model.FirstName).extend({ required: "Please enter a first name" });;
    self.LastName = ko.observable(model.LastName);

    return self;
};

AddressModel = function(model) {

    var self = this;

    //Observables
    self.Address = ko.observable(model.Address);
    self.PostalCode = ko.observable(model.PostalCode);
    self.City = ko.observable(model.City);

    return self;
};

E eu adicionei um extensor para a validação necessária, como usado no campo Firstname:

ko.extenders.required = function(target, overrideMessage) {
    //add some sub-observables to our observable    
    target.hasError = ko.observable();
    target.validationMessage = ko.observable();
    //define a function to do validation    

    function validate(newValue) {
        target.hasError(newValue ? false : true);
        target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
    }

    //initial validation    
    validate(target());

    //validate whenever the value changes    
    target.subscribe(validate);
    //return the original observable    
    return target;
};

questionAnswers(1)

yourAnswerToTheQuestion