使用 Jquery 步向导进行不显眼的验证
Unobtrusive validation with Jquery Steps Wizard
最近我问了一个关于如何自定义 JQuery 步骤的问题,因为我想使用部分视图而不是静态内容。我已经通过使用 jquery-steps,
支持的以下代码部分解决了该问题
<h3>Step 1</h3>
<section data-mode="async" data-url="/Formation/RenderStep1"></section>
<h3>Step 2</h3>
<section data-mode="async" data-url="/Formation/RenderStep2"></section>
现在我面临的最大问题是如何使用非侵入式验证。我不想使用 JQuery 自定义验证,必须有一些方法可以使用它。
呈现的每个局部视图都有自己的形式。我想在 jquery-steps,
的 onStepChanging 函数中验证表单
$("#my-steps").steps({
headerTag: "h3",
bodyTag: "section",
contentMode: "async",
transitionEffect: "fade",
stepsOrientation: "vertical",
onStepChanging: function (event, currentIndex, newIndex) {
return true;
}
});
我试过调用 $.validator.unobtrusvie.parse('#myform');在 onStepChanging 函数中,但 ('#myform') 未定义,我仍然不知道这是否是手动调用不显眼验证的正确方法。请指导我并告诉我实现这一目标的方向。任何帮助将不胜感激。
听起来您正在尝试在 JQuery Steps 库中管理多个表单,但我认为这不是它的目的。
当您配置 JQuery 个步骤时,您可以根据您的视图中的表单进行设置。
不引人注目 JQuery 验证是在您的视图中查看模型并自动配置 HTML 具有相关数据属性的错误处理。
此验证应在客户端自动触发。
使用局部视图应该没有问题,只要它们封装在同一个表单元素中。
将每个局部视图包装在自己的表单中有什么要求?如果您尝试在整个 JQuery Steps 表单向导中创建多个 posts,那么您将击败该对象。
在 JQuery 步骤表单中的每一步,您只验证这样一个表单:-
onStepChanging: function (event, currentIndex, newIndex) {
//Allways allow user to move backwards.
if (currentIndex > newIndex) {
return true;
}
// Remove the validation errors from the next step, incase user has previously visited it.
var form = $(this);
if (currentIndex < newIndex) {
// remove error styles
$(".body:eq(" + newIndex + ") label.error", form).remove();
$(".body:eq(" + newIndex + ") .error", form).removeClass("error");
}
//disable validation on fields that are disabled or hidden.
form.validate().settings.ignore = ":disabled,:hidden";
return form.valid();
}
一旦用户输入完数据,并且满足客户端验证,你就挂钩到 onFinished 方法和 post 表单 :-
onFinished: function (event, currentIndex) {
var form = $(this);
form.submit();
}
JQuery 步骤的目的是让用户在填写表格时拥有流畅的体验,而不是被提出的问题数量所淹没。
从开发人员的角度来看,它使我们能够将表单拆分为大小适中的块,而不必担心在屏幕之间保存进度或丢失表单数据的状态,并允许我们捕获所有需要的信息一旦满足所有验证标准,只需要制作一个 post 数据。
我试过formvalidation
插件,它会让你放松心情,不用在没有表单标签的验证中搜索,或者在没有提交表单的情况下进行验证,这是我在尝试时解决的问题。
我知道它不是免费的,但你可以从 here 开始试用,我个人喜欢它
验证后第一次更新高度
<style type="text/css">
/* Adjust the height of section */
#profileForm .content {
min-height: 100px;
}
#profileForm .content > .body {
width: 100%;
height: auto;
padding: 15px;
position: relative;
}
其次,将 data-steps
索引添加到您的部分*
<form id="profileForm" method="post" class="form-horizontal">
<h2>Account</h2>
<section data-step="0">
<div class="form-group">
<label class="col-xs-3 control-label">Username</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="username" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Email</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="email" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="password" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Retype password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="confirmPassword" />
</div>
</div>
</section>
三、javascript代码
<script>
## // to adjust step height to fit frame after showing validation messages##
$(document).ready(function() {
function adjustIframeHeight() {
var $body = $('body'),
$iframe = $body.data('iframe.fv');
if ($iframe) {
// Adjust the height of iframe
$iframe.height($body.height());
}
}
// IMPORTANT: You must call .steps() before calling .formValidation()
$('#profileForm')
// setps setup
.steps({
headerTag: 'h2',
bodyTag: 'section',
onStepChanged: function(e, currentIndex, priorIndex) {
// You don't need to care about it
// It is for the specific demo
adjustIframeHeight();
},
// Triggered when clicking the Previous/Next buttons
// to apply validation to your section
onStepChanging: function(e, currentIndex, newIndex) {
var fv = $('#profileForm').data('formValidation'), // FormValidation instance
// The current step container
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
// Do not jump to the next step
return false;
}
return true;
},
// Triggered when clicking the Finish button
onFinishing: function(e, currentIndex) {
var fv = $('#profileForm').data('formValidation'),
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the last step container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
return false;
}
return true;
},
onFinished: function(e, currentIndex) {
// Uncomment the following line to submit the form using the defaultSubmit() method
// $('#profileForm').formValidation('defaultSubmit');
// For testing purpose
$('#welcomeModal').modal();
}
})
.formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
// This option will not ignore invisible fields which belong to inactive panels
excluded: ':disabled',
fields: {
username: {
validators: {
notEmpty: {
// for asp.net i used element attribute to integerated with unobtrusive validation
// message :$('username').attr('data-val-required')
message: 'The username is required'
},
stringLength: {
min: 6,
max: 30,
message: 'The username must be more than 6 and less than 30 characters long'
},
regexp: {
regexp: /^[a-zA-Z0-9_\.]+$/,
message: 'The username can only consist of alphabetical, number, dot and underscore'
}
}
},
email: {
validators: {
notEmpty: {
message: 'The email address is required'
},
emailAddress: {
message: 'The input is not a valid email address'
}
}
},
password: {
validators: {
notEmpty: {
message: 'The password is required'
},
different: {
field: 'username',
message: 'The password cannot be the same as username'
}
}
},
confirmPassword: {
validators: {
notEmpty: {
message: 'The confirm password is required'
},
identical: {
field: 'password',
message: 'The confirm password must be the same as original one'
}
}
}
}
});
最近我问了一个关于如何自定义 JQuery 步骤的问题,因为我想使用部分视图而不是静态内容。我已经通过使用 jquery-steps,
支持的以下代码部分解决了该问题 <h3>Step 1</h3>
<section data-mode="async" data-url="/Formation/RenderStep1"></section>
<h3>Step 2</h3>
<section data-mode="async" data-url="/Formation/RenderStep2"></section>
现在我面临的最大问题是如何使用非侵入式验证。我不想使用 JQuery 自定义验证,必须有一些方法可以使用它。
呈现的每个局部视图都有自己的形式。我想在 jquery-steps,
的 onStepChanging 函数中验证表单$("#my-steps").steps({
headerTag: "h3",
bodyTag: "section",
contentMode: "async",
transitionEffect: "fade",
stepsOrientation: "vertical",
onStepChanging: function (event, currentIndex, newIndex) {
return true;
}
});
我试过调用 $.validator.unobtrusvie.parse('#myform');在 onStepChanging 函数中,但 ('#myform') 未定义,我仍然不知道这是否是手动调用不显眼验证的正确方法。请指导我并告诉我实现这一目标的方向。任何帮助将不胜感激。
听起来您正在尝试在 JQuery Steps 库中管理多个表单,但我认为这不是它的目的。
当您配置 JQuery 个步骤时,您可以根据您的视图中的表单进行设置。
不引人注目 JQuery 验证是在您的视图中查看模型并自动配置 HTML 具有相关数据属性的错误处理。
此验证应在客户端自动触发。
使用局部视图应该没有问题,只要它们封装在同一个表单元素中。
将每个局部视图包装在自己的表单中有什么要求?如果您尝试在整个 JQuery Steps 表单向导中创建多个 posts,那么您将击败该对象。
在 JQuery 步骤表单中的每一步,您只验证这样一个表单:-
onStepChanging: function (event, currentIndex, newIndex) {
//Allways allow user to move backwards.
if (currentIndex > newIndex) {
return true;
}
// Remove the validation errors from the next step, incase user has previously visited it.
var form = $(this);
if (currentIndex < newIndex) {
// remove error styles
$(".body:eq(" + newIndex + ") label.error", form).remove();
$(".body:eq(" + newIndex + ") .error", form).removeClass("error");
}
//disable validation on fields that are disabled or hidden.
form.validate().settings.ignore = ":disabled,:hidden";
return form.valid();
}
一旦用户输入完数据,并且满足客户端验证,你就挂钩到 onFinished 方法和 post 表单 :-
onFinished: function (event, currentIndex) {
var form = $(this);
form.submit();
}
JQuery 步骤的目的是让用户在填写表格时拥有流畅的体验,而不是被提出的问题数量所淹没。
从开发人员的角度来看,它使我们能够将表单拆分为大小适中的块,而不必担心在屏幕之间保存进度或丢失表单数据的状态,并允许我们捕获所有需要的信息一旦满足所有验证标准,只需要制作一个 post 数据。
我试过formvalidation
插件,它会让你放松心情,不用在没有表单标签的验证中搜索,或者在没有提交表单的情况下进行验证,这是我在尝试时解决的问题。
我知道它不是免费的,但你可以从 here 开始试用,我个人喜欢它
验证后第一次更新高度
<style type="text/css">
/* Adjust the height of section */
#profileForm .content {
min-height: 100px;
}
#profileForm .content > .body {
width: 100%;
height: auto;
padding: 15px;
position: relative;
}
其次,将 data-steps
索引添加到您的部分*
<form id="profileForm" method="post" class="form-horizontal">
<h2>Account</h2>
<section data-step="0">
<div class="form-group">
<label class="col-xs-3 control-label">Username</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="username" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Email</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="email" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="password" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Retype password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="confirmPassword" />
</div>
</div>
</section>
三、javascript代码
<script>
## // to adjust step height to fit frame after showing validation messages##
$(document).ready(function() {
function adjustIframeHeight() {
var $body = $('body'),
$iframe = $body.data('iframe.fv');
if ($iframe) {
// Adjust the height of iframe
$iframe.height($body.height());
}
}
// IMPORTANT: You must call .steps() before calling .formValidation()
$('#profileForm')
// setps setup
.steps({
headerTag: 'h2',
bodyTag: 'section',
onStepChanged: function(e, currentIndex, priorIndex) {
// You don't need to care about it
// It is for the specific demo
adjustIframeHeight();
},
// Triggered when clicking the Previous/Next buttons
// to apply validation to your section
onStepChanging: function(e, currentIndex, newIndex) {
var fv = $('#profileForm').data('formValidation'), // FormValidation instance
// The current step container
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
// Do not jump to the next step
return false;
}
return true;
},
// Triggered when clicking the Finish button
onFinishing: function(e, currentIndex) {
var fv = $('#profileForm').data('formValidation'),
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the last step container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
return false;
}
return true;
},
onFinished: function(e, currentIndex) {
// Uncomment the following line to submit the form using the defaultSubmit() method
// $('#profileForm').formValidation('defaultSubmit');
// For testing purpose
$('#welcomeModal').modal();
}
})
.formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
// This option will not ignore invisible fields which belong to inactive panels
excluded: ':disabled',
fields: {
username: {
validators: {
notEmpty: {
// for asp.net i used element attribute to integerated with unobtrusive validation
// message :$('username').attr('data-val-required')
message: 'The username is required'
},
stringLength: {
min: 6,
max: 30,
message: 'The username must be more than 6 and less than 30 characters long'
},
regexp: {
regexp: /^[a-zA-Z0-9_\.]+$/,
message: 'The username can only consist of alphabetical, number, dot and underscore'
}
}
},
email: {
validators: {
notEmpty: {
message: 'The email address is required'
},
emailAddress: {
message: 'The input is not a valid email address'
}
}
},
password: {
validators: {
notEmpty: {
message: 'The password is required'
},
different: {
field: 'username',
message: 'The password cannot be the same as username'
}
}
},
confirmPassword: {
validators: {
notEmpty: {
message: 'The confirm password is required'
},
identical: {
field: 'password',
message: 'The confirm password must be the same as original one'
}
}
}
}
});