Knockout.js 带验证的淘汰JS多步骤表单
在这里寻找一个精神检查。我最近开始学习knockout,并被指示转换现有的多步骤表单 基本思想是在允许用户继续之前验证每个步骤。还设置了某些限制(未显示),以确定是继续前进还是使用所有当前数据提交(例如:如果不符合条件) 这里是一个简化版本的提琴(实际表单包含4个步骤中的大约40个字段) HTML:Knockout.js 带验证的淘汰JS多步骤表单,knockout.js,knockout-2.0,knockout-validation,Knockout.js,Knockout 2.0,Knockout Validation,在这里寻找一个精神检查。我最近开始学习knockout,并被指示转换现有的多步骤表单 基本思想是在允许用户继续之前验证每个步骤。还设置了某些限制(未显示),以确定是继续前进还是使用所有当前数据提交(例如:如果不符合条件) 这里是一个简化版本的提琴(实际表单包含4个步骤中的大约40个字段) HTML: 关于你 名字: 姓 你的生意 企业名称: 有人介绍过你吗? 用户信息 推荐人的名字: 推荐人的姓氏: JS: $(“#寄存器”).children().hi
关于你
-
名字:
-
姓
你的生意
-
企业名称:
-
有人介绍过你吗?
用户信息
-
推荐人的名字:
-
推荐人的姓氏:
JS:
$(“#寄存器”).children().hide().first().show();
ko.validation.init({
ParseInputAttribute:true,
装饰元素:是的,
WriteInputAttribute:true,
errorElementClass:“错误”
});
函数myViewModel(){
var self=这个;
//可观测初始
self.firstName=ko.observable();
self.lastName=ko.observable();
self.businessName=ko.observable();
自参考=可观察();
self.referralFirst=ko.observable();
self.referralLast=ko.observable();
//validaiton可观测初始
self.step1=ko.validatedObservable({
名字:self.firstName,
lastName:self.lastName
});
self.step2=ko.validatedObservable({
businessName:self.businessName,
转介:自我转介
});
self.step3=ko.validatedObservable({
referralFirst:self.referralFirst,
referralLast:self.referralLast
});
//导航初始化
self.currentStep=ko.可观察(1);
self.stepfroward=函数(){
if(self.currentStep()1){
self.changeSection(self.currentStep()-1);
}
}
self.changeesection=函数(destIdx){
var validationObservable=“步骤”+self.currentStep();
if(self[validationObservable]().isValid()){
自电流阶跃(destIdx);
$(“#寄存器”).children().hide().eq(self.currentStep()-1.show();
返回true;
}否则{
self[validationObservable]()。errors.showAllMessages();
}
返回false;
}
self.resetAll=函数(){
//待办事项
返回false;
}
}
应用绑定(新的myViewModel());
我的问题是:
感谢您的澄清。这是一个好的开始。我建议您使用knockout管理可见性,只有在没有其他选项时才使用jQuery。我的意思是管理字段集的可见性:
<fieldset data-bind="visible: currentStep() === 1">
在这种情况下,表单标签是不必要的,因为您可以使用JS对象管理所有内容。看看Carl Schroedl的文章
与“优秀”结合使用时,您可以创建验证约束组,并根据需要应用它们
ko.validation.init({
parseInputAttributes: false,
decorateElement: true,
insertMessages: true,
messagesOnModified: true,
grouping: { deep: true, observable: true }
});
var myViewModel = ValidatedViewModel(function () {
var self = this;
//observable init
self.firstName = ko.observable();
self.lastName = ko.observable();
self.businessName = ko.observable();
self.referred = ko.observable();
self.referralFirst = ko.observable();
self.referralLast = ko.observable();
//navigation init
self.currentStep = ko.observable(1);
self.stepForward = function () {
if(self.currentStep()<4){
self.changeSection(self.currentStep() + 1);
}
}
self.stepBack = function () {
if (self.currentStep() > 1) {
self.changeSection(self.currentStep() - 1);
}
}
self.changeSection = function(destIdx){
//remove all constraint groups
try { self.removeConstraintGroup('step1'); } catch (e) { }
try { self.removeConstraintGroup('step2'); } catch (e) { }
try { self.removeConstraintGroup('step3'); } catch (e) { }
//apply constraint group for current step
try{self.applyConstraintGroup('step' + self.currentStep());} catch(e){}
var errorCount = self.errors().length;
self.errors.showAllMessages();
if(errorCount===0){
self.currentStep(destIdx);
return true;
}
return false;
}
self.constraintGroups = {
step1: {
firstName: { required: true },
lastName: { required: true }
},
step2: {
businessName: { required: true }
},
step3: {
referralFirst: { required: true },
referralLast: { required: true }
}
}
self.resetAll = function(){
//TODO
return false;
}
this.errors = ko.validation.group(this);
});
ko.applyBindings(new myViewModel());
在每次运行验证例程时,您将删除所有约束组,然后为给定步骤应用所需的约束组。或者订阅可观察的步骤以设置约束组
(我建议在应用/删除约束组时使用try/catch语句,因为如果约束组已应用/删除,则会出错。)
这是一个学习曲线,但它确实帮助我创建了一个篮子/结帐页面,每个步骤都有适当的验证
更新:
. 我使可视步骤依赖于currentStep observable,并删除了所需的标记。所有验证现在都在模型中处理。作为奖励,JSFIDLE中的CSS还为验证消息设置样式,而不需要额外的标记
ko.validation.init({
parseInputAttributes: false,
decorateElement: true,
insertMessages: true,
messagesOnModified: true,
grouping: { deep: true, observable: true }
});
var myViewModel = ValidatedViewModel(function () {
var self = this;
//observable init
self.firstName = ko.observable();
self.lastName = ko.observable();
self.businessName = ko.observable();
self.referred = ko.observable();
self.referralFirst = ko.observable();
self.referralLast = ko.observable();
//navigation init
self.currentStep = ko.observable(1);
self.stepForward = function () {
if(self.currentStep()<4){
self.changeSection(self.currentStep() + 1);
}
}
self.stepBack = function () {
if (self.currentStep() > 1) {
self.changeSection(self.currentStep() - 1);
}
}
self.changeSection = function(destIdx){
//remove all constraint groups
try { self.removeConstraintGroup('step1'); } catch (e) { }
try { self.removeConstraintGroup('step2'); } catch (e) { }
try { self.removeConstraintGroup('step3'); } catch (e) { }
//apply constraint group for current step
try{self.applyConstraintGroup('step' + self.currentStep());} catch(e){}
var errorCount = self.errors().length;
self.errors.showAllMessages();
if(errorCount===0){
self.currentStep(destIdx);
return true;
}
return false;
}
self.constraintGroups = {
step1: {
firstName: { required: true },
lastName: { required: true }
},
step2: {
businessName: { required: true }
},
step3: {
referralFirst: { required: true },
referralLast: { required: true }
}
}
self.resetAll = function(){
//TODO
return false;
}
this.errors = ko.validation.group(this);
});
ko.applyBindings(new myViewModel());
ko.validation.init({
ParseInputAttribute:false,
装饰元素:是的,
insertMessages:true,
messages:true,
分组:{deep:true,observeable:true}
});
var myViewModel=ValidatedViewModel(函数(){
var self=这个;
//可观测初始
self.firstName=ko.observable();
self.lastName=ko.observable();
self.businessName=ko.observable();
自参考=可观察();
self.referralFirst=ko.observable();
self.referralLast=ko.observable();
//导航初始化
self.currentStep=ko.可观察(1);
self.stepfroward=函数(){
if(self.currentStep()1){
self.changeSection(self.currentStep()-1);
}
}
self.changeesection=函数(destIdx){
//删除所有约束组
尝试{self.removeConstraintGroup('step1');}catch(e){}
尝试{self.removeConstraintGroup('step2');}catch(e){}
尝试{self.removeConstraintGroup('step3');}catch(e){}
//为当前步骤应用约束组
尝试{self.applyConstraintGroup('step'+self.currentStep());}catch(e){}
var errorCount=self.errors().length;
self.errors.showAllMessages();
如果(errorCount==0){
自电流阶跃(destIdx);
返回true;
}
<script type="text/html" id="ko-template">
<form id="register">
...
</form>
</script>
<div id="context"></div>
var template = $('#ko-template').html();
$('#context').empty().html(template);
ko.applyBindings(new myViewModel(), document.getElementById('context'));
ko.validation.init({
parseInputAttributes: false,
decorateElement: true,
insertMessages: true,
messagesOnModified: true,
grouping: { deep: true, observable: true }
});
var myViewModel = ValidatedViewModel(function () {
var self = this;
//observable init
self.firstName = ko.observable();
self.lastName = ko.observable();
self.businessName = ko.observable();
self.referred = ko.observable();
self.referralFirst = ko.observable();
self.referralLast = ko.observable();
//navigation init
self.currentStep = ko.observable(1);
self.stepForward = function () {
if(self.currentStep()<4){
self.changeSection(self.currentStep() + 1);
}
}
self.stepBack = function () {
if (self.currentStep() > 1) {
self.changeSection(self.currentStep() - 1);
}
}
self.changeSection = function(destIdx){
//remove all constraint groups
try { self.removeConstraintGroup('step1'); } catch (e) { }
try { self.removeConstraintGroup('step2'); } catch (e) { }
try { self.removeConstraintGroup('step3'); } catch (e) { }
//apply constraint group for current step
try{self.applyConstraintGroup('step' + self.currentStep());} catch(e){}
var errorCount = self.errors().length;
self.errors.showAllMessages();
if(errorCount===0){
self.currentStep(destIdx);
return true;
}
return false;
}
self.constraintGroups = {
step1: {
firstName: { required: true },
lastName: { required: true }
},
step2: {
businessName: { required: true }
},
step3: {
referralFirst: { required: true },
referralLast: { required: true }
}
}
self.resetAll = function(){
//TODO
return false;
}
this.errors = ko.validation.group(this);
});
ko.applyBindings(new myViewModel());
<form id="register">
<h1>Current Step: <span data-bind="text:currentStep()"></span></h1>
<fieldset data-bind="visible: currentStep()===1">
<h2>About You</h2>
<ul>
<li>
<label for="firstName">First Name:</label>
<input type="text" data-bind="value: firstName" />
</li>
<li>
<label for="lastName">Last Name</label>
<input type="text" data-bind="value: lastName" />
</li>
</ul>
</fieldset>
<fieldset data-bind="visible:currentStep()===2">
<h2>Your Business</h2>
<ul>
<li>
<label for="businessName">Business Name:</label>
<input type="text" data-bind="value: businessName" />
</li>
<li>
<label for="currentCustomer">Were you referred by someone?</label>
<input type="checkbox" data-bind="checked: referred" />
</li>
</ul>
</fieldset>
<fieldset data-bind="visible:currentStep()===3">
<h2>User Info</h2>
<ul>
<li>
<label for="userName">Referrer's First Name:</label>
<input type="text" data-bind="value: referralFirst" />
</li>
<li>
<label for="password">Referrer's Last Name:</label>
<input type="password" data-bind="value: referralLast" />
</li>
</ul>
</fieldset>
</form>
<div class="nav-buttons"> <a href="#" data-bind='click: stepForward'>Continue</a>
<a href="#" data-bind='click: stepBack'>Back</a>
<a href="#" data-bind='click: resetAll'>Cancel</a>
</div>