Здравствуйте. Я больше бэкенд разработчик. Столкнулся с backbone + marionette.
Вопрос следующий:
Есть вкладки, шаг 1 шаг 2 и т.д. Пока пользователь на каждой вкладке по очереди на заполнит форму дальше нелья перейти на следующую вкладку. Это работает. Но начиная со со второго шага у вкладки есть еще под вкладки(под шаги), при заполнении которых валидация не срабатывает и можно гулять по ним вперед назад, а нужно перейти на следующую подвкладку только после заполения всех полей.
Когда ставлю брекпоинт на сработку события перехода по вкладкам срабатывает только для вкладок а не для повкладок.
Вот сам код:
views/inputs/steps.jsLib.ns('Views.Inputs', function(Inputs) {
'use strict';
var Empty = Mn.ItemView.extend({
tagName: 'li',
template: function() { return ''; }
});
var Tab = Mn.ItemView.extend({
template: '#Inputs-StepTabTemplate',
tagName: 'li',
triggers: {click: 'select'},
ui: {index: '[data-ui="index"]'},
bindings: {'[data-ui="title"]': 'title'},
onRender: function() {
this.stickit();
this.ui.index.html(this.getOption('index') + 1);
}
});
var Tabs = Mn.CollectionView.extend({
tagName: 'ul',
className: 'special',
childView: Tab,
childEvents: {select: 'selectHandler'},
filter: function(child) {
return child.get('name') !== 'active_step';
},
childViewOptions: function(item, index) {
return {index: index};
},
selectHandler: function(view) {
this.triggerMethod('select', this.collection.indexOf(view.model));
},
select: function(index) {
this.$('li').removeClass('uk-active');
this.children.findByModel(this.collection.at(index)).$el.addClass('uk-active');
}
});
var Parent = Inputs.Container;
var Steps = Parent.extend({
tagName: 'ul',
className: 'uk-switcher special',
defaultChild: Empty,
initialize: function() {
Parent.prototype.initialize.apply(this, arguments);
this.collection = this.model.get('fields');
},
childViewOptions: function(item) {
var opts = Parent.prototype.childViewOptions.apply(this, arguments);
opts.tagName = 'li';
opts.showTitle = item.has('showTitle') ? item.get('showTitle') : false;
opts.formSection = false;
return opts;
}
});
Inputs.Steps = Mn.LayoutView.extend({
className: 'steps',
template: '#Inputs-StepsTemplate',
behaviors: {
Messageable: {el: '[data-region="messages"]'},
},
regions: {
tabs: '[data-region="step-tabs"]',
panes: '[data-region="step-panes"]'
},
ui: {
prev: '[data-ui="prev"]',
next: '[data-ui="next"]',
save: '[data-ui="save"]'
},
events: {
'click @ui.prev': 'prevClickHandler',
'click @ui.next': 'nextClickHandler',
'click @ui.save': 'saveClickHandler'
},
childEvents: {
next: 'nextHandler'
},
initialize: function() {
var fields = this.model.get('fields');
this.activeStep = this.model.find('active_step');
if (!this.activeStep) {
fields.add({name: 'active_step', type: 'integer', visible: false});
this.activeStep = this.model.find('active_step');
this.activeStep.setValue(0);
}
var step = this.getOption('step');
if (step == null) { step = this.activeStep.getValue(); }
if (step == null) { step = 0; }
this.activeStep.setValue(step);
},
select: function(index) {
if (!this.switcher) { return; }
this.scrollTop();
this.tabs.select(index);
this.switcher.show(index);
this.activeStep.setValue(index);
},
onRender: function() {
var opts = {
rootView: this.getOption('rootView') || this,
collection: this.model.get('fields')
};
this.tabs = new Tabs(opts);
this.listenTo(this.tabs, 'select', this.selectHandler);
this.fakeTabs = new Tabs(opts);
this.steps = new Steps(_.extend(opts, {model: this.model}));
this.getRegion('tabs').show(this.tabs);
this.getRegion('panes').show(this.steps);
this.fakeTabs.render();
var step = this.activeStep.getValue();
this.index = step;
this.updateNavigation();
_.defer(function(view) {
view.switcher = UIkit.switcher(view.fakeTabs.$el, {
connect: view.steps.$el,
animation: 'slide-horizontal'
});
view.switcher.on('show.uk.switcher', _.bind(view.switchHandler, view));
view.select(step);
}, this);
},
updateNavigation: function(index) {
if (index == null) { index = this.index; }
if (index === 0) {
this.ui.prev.attr('disabled', 'disabled');
} else {
this.ui.prev.removeAttr('disabled');
}
// this.tabs.collection.length - active_step - 1
if (index === this.tabs.children.length - 1) {
this.ui.next.find('span').html('Подготовить');
} else {
this.ui.next.find('span').html('Следующий шаг');
}
},
setRegistered: function(registered) {
this.registered = registered;
if (registered) {
this.ui.save.show();
} else {
this.ui.save.hide();
}
},
switchHandler: function(event, item) {
this.index = $(item).index();
this.updateNavigation();
},
prevClickHandler: function() {
if (this.index === 0) { return; }
this.select(this.index - 1);
},
nextClickHandler: function() {
var view = this.getOption('rootView') || this;
if (this.index === this.tabs.children.length - 1) {
if (!this.validateCurrentStep()) {
this.scrollTop();
return;
}
view.triggerMethod('create');
} else {
if (this.index === 0 && !this.registered) {
view.triggerMethod('register', 1);
return;
}
if (!this.validateCurrentStep()) {
this.scrollTop();
return;
}
this.select(this.index + 1);
view.triggerMethod('save');
}
},
validateCurrentStep: function() {
return this.model.get('fields').at(this.index).validate();
},
saveClickHandler: function() {
var view = this.getOption('rootView') || this;
view.triggerMethod('save');
},
selectHandler: function(index) {
if (!this.registered) {
var view = this.getOption('rootView') || this;
view.triggerMethod('register', index);
return;
}
if (this.index < index && !this.validateCurrentStep()) {
this.scrollTop();
return;
}
this.select(index);
},
nextHandler: function(view) {
if (this.steps.children.last() === view) {
this.triggerMethod('next');
return;
}
var index = this.model.get('fields').indexOf(view.model);
if (index >= 0) { this.select(index + 1); }
},
scrollTop: function() {
// stop scroll animation on any user action
var stopEvents = 'scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove';
var stop = function() {
UIkit.$('html,body').stop();
$('html,body').off(stopEvents, stop);
};
$('html,body').on(stopEvents, stop);
UIkit.Utils.scrollToElement(this.tabs.$el, {
complete: function() { $('html,body').off(stopEvents, stop); }
});
}
});
});
Cрабатывают обработчики в файле steps.js при переходе по вкладкам. По подвкладкам нет.
Например при переходе на другую вкладку сработал обработчик из файла
steps.jsselectHandler: function(view) {
this.triggerMethod('select', this.collection.indexOf(view.model));
},
По подвкладкам он не срабатывает
Для вкдадок и подвкладок используется одна вьюшка:
var Steps = Parent.extend({
tagName: 'ul',
className: 'uk-switcher special',
defaultChild: Empty
Заранее спасибо за ответ.