2013-06-26 7 views
7

Ich verwende Durandal, die wiederum von Knockout profitiert.Knockout-Validierung: Dynamische Einschränkungen

Ich möchte Änderungsprüfung können Längen dynamisch

enter image description here

Fiddle

Die Geige etwas anders zu sein scheint zu verhalten, als meine „Arbeit“ Lösung, aber es ist noch nicht zu tun was ich will/erwarte es.

Ansichtsmodell JS:

[Versuch 1]

define(function() { 

    var self = this; 

    self.userInfo = {  
     IdOrPassportNumber: ko.observable().extend({ 
      required: true, 
      pattern: { 
       message: 'A message', 
       params: /some regex/ 
      } 
     }), 
     IdType: ko.observable() 
    }, 

    self.isIdValid = ko.validatedObservable({ 
     IdOrPassportNumber: self.userInfo.IdOrPassportNumber 
    }); 

    self.userInfo.IdOrPassportNumber.subscribe(function (value) { 
      if (isIdValid.isValid()) { 
       console.log('YOLO!'); 
      } 
    }); 

    self.userInfo.IdType.subscribe(function (value) { 
     console.log(value); 
     if (value === 'Passport') { 
      self.userInfo.IdOrPassportNumber.extend({ maxLength: 15 }); 
     } else { 
      self.userInfo.IdOrPassportNumber.extend({ maxLength: 13 }); 
     } 
    });  

    var viewModel = { 
     userInfo: self.userInfo 
    }; 

    viewModel["errors"] = ko.validation.group(viewModel.userInfo); 
    viewModel["errors"].showAllMessages(); 

    return viewModel; 
}); 

Was passiert zu sein scheint, ist, dass, wenn ich die Eingabe starten ich die max & min Validierung von 13, aber wenn i fahre fort, die Validierungsänderungen auf 15 zu tippen. Ich habe einen anderen Weg ausprobiert, indem ich die minimale Länge in der ersten beobachtbaren Ausdehnung EG, direkt nach der Regex, und dann die Min- und Max-Länge gesetzt habe, um eine Observable zu verwenden Erfolg.

[Versuch 2]

self.userInfo = {  
     IdOrPassportNumber: ko.observable().extend({    
      maxLength: self.maxLength(), 
      minlength: self.maxLength() 
     }), 
     IdType: ko.observable() 
    }, 

    self.maxLength = ko.observable(); 

    self.userInfo.IdType.subscribe(function (value) { 

      if (value === 'Passport') { 
      self.maxLength(15) 
      } else { 
       self.maxLength(3) 
      } 
    }); 
+2

Können Sie http://cdnjs.com/ zu Nimm das Knockout-Validierungs-Plugin ... – nemesv

+1

Fertig. +1 Ps sehr coole Seite. Lesezeichen für sicher :) –

Antwort

3

Sie waren so nah :-) Sie müssen die beobachtbare selbst, nicht den unverpackten Wert bereitstellen. Entfernen Sie einfach die () von maxLength() - die Validierungsbibliothek wird es automatisch für Sie auspacken.

self.userInfo = {  
    IdOrPassportNumber: ko.observable().extend({    
     maxLength: self.maxLength, 
     minlength: self.maxLength 
    }), 
    IdType: ko.observable() 
}, 

Hier ist ein weiteres Beispiel mit dynamischen Regex-Mustern.

zipPostalPattern = ko.pureComputed(() => this.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : ''); 
    zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
    { 
     required: true, 
     pattern: { 
      message: 'This is not a valid postcode for the country', 
      params: this.zipPostalPattern 
     } 
    }); 

oder (wenn Sie keine Nachricht möchten).

zipPostalPattern = ko.pureComputed(function() { return this.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : ''}); 
    zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
    { 
     required: true, 
     pattern: self.zipPostalPattern 
    }); 

Wichtige: Wenn Sie die message Parameter keine benutzerdefinierte Nachricht wollen nicht nur entfernen und lassen pattern = { params: this.zipPostalPattern }, weil es wird nicht funktionieren. Wenn Sie keine Nachricht haben, müssen Sie die Regex/Zeichenfolge direkt für den Parameter pattern festlegen.

Oder natürlich kann man einfach die berechnete beobachtbaren Ort definieren (hier ist es ok countryCode() als Funktion zu nennen, weil das, wie die Arbeit berechnet ist)

zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
    { 
     required: true, 
     pattern: ko.pureComputed(function() { 
        return self.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : '' 
        }) 
    }); 
+2

Für jeden, der dies liest. Das kann ich in dieser Phase nicht mehr testen (nicht mehr bei diesem Projekt). Ich bevorzuge die Lösung von @ Simon_Weaver als akzeptierte Lösung und werde sie als solche kennzeichnen. –

+1

Danke. Ich muss sagen, dass mir heute nur aufgefallen ist, dass ich ein Observable als Parameter einer Regel übergeben könnte, und ich wurde sehr aufgeregt - dann wurde mir klar, dass es vielleicht nicht funktionieren würde - aber dann wurde ich wieder aufgeregt, dass es so scheint funktionieren sehr gut :-) Soweit ich mich erinnere, ist es nicht klar dokumentiert, aber es ist sehr einfach, wenn Sie bereits wissen, wie man Knockout verwendet und fügt einige große Flexibilität hinzu. –

6

Hier ist die Lösung, die für mich gearbeitet:

I Verwendung des custom validation Features gemacht, genauer gesagt die single use custom validation, da dies wird nicht wiederverwendet werden anderswo.

[Versuch 3]

self.userInfo = {  
     IdOrPassportNumber: ko.observable().extend({ 
      required: true, 
      pattern: { 
       message: 'A message', 
       params: /some regex/ 
      }, 
      validation: { 
       validator: function (val) { 
        if (self.userInfo.IdType() === 'Id') { 
         return val.length === 13; 
        } else { 
         return val.length === 15; 
        } 
       }, 
       message: function() { 
        if (self.userInfo.IdType() === 'Id') { 
        return 'Required: 13 characters'; 
        } else { 
        return 'Required: 15 characters'; 
        } 
       } 
      } 
     }) 
    } 
+3

Als eine Randnotiz. Mir ist aufgefallen, dass auch die Reihenfolge der Validierungen von Bedeutung ist. Sagen Sie also, dass Ihr Custom Validator (oder ein anderer) zuerst ausgelöst werden soll. Bestellen Sie ihn entsprechend. –

+0

Ist es nicht besser, zwei verschiedene Felder mit fester Validierung zu verwenden und die Bindung zu ändern auf der Seite ''? Beim Speichern schreibe einfach 'var idOrPassword = id() || password()'. – blazkovicz

4

betrachten diese

self.iDNumber = ko.observable('').extend({ 
     required: { 
      params: true, 
      message: 'ID Number is a required field.', 
      insertMessages: false 
     }, 
     SouthAfricanIDNumber: { 
      message: 'Please enter a valid South African ID number.', 
      onlyIf: function() { 
       return self.identityType() === 'SAID'; 
      } 
     } 
    }); 

wo SouthAfricanIDNumber eine benutzerdefinierte Validierung ist die regex verwendet.

+1

Willkommen in SO :), aber sehen Sie meine akzeptierte Antwort. (Ich bin nicht mehr am Projekt. Aber ich werde es für die Zukunft im Hinterkopf behalten) –

+1

+1 zu ermutigen 'Spacerogue' mit seinem/ihrem ersten Beitrag. – hirikarate