最近在使用jquery.bootstrap.wizard,由于应用场景需要以及代码复用考虑,向导步数根据新增实体类型,动态生成,这两天一直被生成后如何重新渲染的问题困扰,搜索未果,记得之前也有人问同样问题,但是找不到网址了,所以在这里写下我的第一份博客分享下我的解决过程:
<form role="form" id="entityWizard" class="form-wizard validate">
<ul class="tabs" id="entityWizardTabs">
<li class="active">
<a href="#entityTypeStep" data-toggle="tab">
<@spring.message "entityTypeSelect"/>
<span>1</span>
</a>
</li>
<li>
<a href="#basicAttributeStep" data-toggle="tab">
<@spring.message "basicAttribute"/>
<span>2</span>
</a>
</li>
</ul>
<div class="progress-indicator">
<span></span>
</div>
<div class="tab-content no-margin" id='entitywizardContent'>
<!-- Tabs Content -->
<div class="tab-pane with-bg active" id="entityTypeStep">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="control-label" for="entityTypeSelect"><@spring.message "pleaseSelectEntityType"/></label>
<select multiple="" size=10 class="form-control" name="entityTypeSelect" id="entityTypeSelect" data-validate="required">
</select>
</div>
</div>
</div>
</div>
<div class="tab-pane with-bg" id="basicAttributeStep">
<div class="row" id='attributeDiv'>
</div>
</div>
<div class="tab-pane with-bg" id="customizeStep">
</div>
<!-- Tabs Pager -->
<ul class="pager wizard">
<li class="previous">
<a href="#"><i class="fa fa-arrow-circle-left"></i> <@spring.message "previous"/></a>
</li>
<li class="next">
<a href="#"><@spring.message "next"/> <i class="fa fa-arrow-circle-right"></i></a>
</li>
<li class="finish" id="submit">
<a href="#"><@spring.message "finish"/> <i class="fa fa-check-circle"></i></a>
</li>
</ul>
</div>
</form>
前两步是固定的,第一步选择实体类型,第二步动态加载实体属性,后面的为动态步骤,维护一些关联关系之类的。
function initWizard(){
var $this = $('#entityWizard'),
$tabs = $this.find('> .tabs > li'),
$progress = $this.find(".progress-indicator"),
_index = $this.find('> ul > li.active').index();
// Validation
var checkFormWizardValidaion = function(tab, navigation, index){
if($this.hasClass('validate')){
var $valid = $this.valid();
if( ! $valid){
$this.data('validator').focusInvalid();
return false;
}
}
return true;
};
// Setup Progress
if(_index > 0){
$progress.css({width: _index/$tabs.length * 100 + '%'});
$tabs.removeClass('completed').slice(0, _index).addClass('completed');
}
$this.bootstrapWizard({
tabClass: "",
onTabShow: function($tab, $navigation, index){
var tabss = $tab.parent().find('> li');
var pct = tabss.eq(index).position().left / tabss.parent().width() * 100;
tabss.removeClass('completed').slice(0, index).addClass('completed');
$progress.css({width: pct + '%'});
if(index === 1){//约定把属性界面放到第二步
if(tempEntityTypeId != entityTypeId){
initAttributes();
tempEntityTypeId = entityTypeId;
}
}
},
onNext: checkFormWizardValidaion,
onTabClick: checkFormWizardValidaion,
onFinish: function(){
……………………
});
}
}
}
});
$this.data('bootstrapWizard').show( _index );
$this.find('.pager a').on('click', function(ev)
{
ev.preventDefault();
});
我第一步是个select选择框,根据选择不同的类型,去动态生成不同的li 和div加入到最初的wizard中。
$('#entityTypeSelect').change(function(event) {
//清空自定义step
$('[flag="customize"]').remove();
if(………………){
var rSiteLi = $('<li class="" flag="customize"></li>');
var rSiteA = $('<a href="#rSiteStep" data-toggle="tab">');
rSiteA.append($.i18n.prop('bindCodeLocationSite'));
var rSiteSpan = $('<span></span>');
rSiteSpan.append(3);
rSiteA.append(rSiteSpan);
rSiteLi.append(rSiteA);
$('#entityWizardTabs').append(rSiteLi);
var rSiteDiv = $('<div class="tab-pane with-bg" id="rSiteStep" flag="customize">');
$('#basicAttributeStep').after(rSiteDiv);
}
$('#entityWizard').data('bootstrapWizard').resetWizard();
});
加载后执行
$('#entityWizard').data('bootstrapWizard').resetWizard();
就可以重置wizard。
一开始以为重新调用initWizard即可,看源码发现源码中
if (element.data('bootstrapWizard')) return;就直接return了
,initWizard并不起作用,甚至试着直接remove掉,重新initWizard
$('#entityWizard').removeData('bootstrapWizard');
但是这样的话,下一步和上一步的click事件应该会注册两次,所以在第一页点击下一步的时候,会直接跳到第三页。
另外在解决问题的过程中还遇到一个大坑,原本我是在onShow中去动态添加li的,这样就形成了死循环,请谨慎。
希望对大家有帮助吧。