Dojo Form Validation Across Tabs
Hi I am having an issue with form validation with dojo's form dijit where I have two or more tabs in the form. If I have a field that is invalid on tab 2 but I'm positioned on tab1 when i validate (by pressing the submit/ok button), the validate method does execute but it cannot find the wrong dijit (switch to the correct tab) and focus on it. The invalidMessage appears but is positioned at the top left of the window instead of where it should be. Is there a way to accomplish this or a workaround applicable for dojo 1.6? Any information you could provide would be greatly appreciat开发者_如何学Ced, thanks.
If you are using the dijit.form.Form (which it seems like you are), I think the easiest way to do this would be override the validate function of the form. Take a look at the dijit.form.Form's original validate function definition (in _FormMixin.js):
validate: function(){
// summary:
// returns if the form is valid - same as isValid - but
// provides a few additional (ui-specific) features.
// 1 - it will highlight any sub-widgets that are not
// valid
// 2 - it will call focus() on the first invalid
// sub-widget
var didFocus = false;
return dojo.every(dojo.map(this.getDescendants(), function(widget){
// Need to set this so that "required" widgets get their
// state set.
widget._hasBeenBlurred = true;
var valid = widget.disabled || !widget.validate || widget.validate();
if(!valid && !didFocus){
// Set focus of the first non-valid widget
dojo.window.scrollIntoView(widget.containerNode || widget.domNode);
widget.focus();
didFocus = true;
}
return valid;
}), function(item){ return item; });
},
You could change around the if(!valid && !didFocus){
condition to look up which tab the widget that failed validation is on and switch to it.
This works for me. It just checks if the parent is a tab (in a bit ugly way, so suggestions are welcome) and if it is, gets its parent and activates the tab. It extends scrollIntoView, because that looks the right function to me. This means if you scroll a widget into view on a tab, the tab gets automaticly activated.
Just make sure this code is run somewhere.
define([
"dojo/_base/window",
"dojo/aspect",
"dojo/dom",
"dojo/dom-class",
"dojo/window",
"dijit/registry"
], function (baseWindow, aspect, dom, domClass, win, registry) {
//extend scrollintoview to make sure, if the element resides on a tab, the tab is activated first.
aspect.around(win, "scrollIntoView", function (originalScrollIntoView) {
return function (node, pos) {
node = dom.byId(node);
var doc = node.ownerDocument || baseWindow.doc,
body = baseWindow.body(doc),
html = doc.documentElement || body.parentNode;
if (node == body || node == html) { return; }
var widget = registry.byNode(node.domNode || node);
if (typeof widget != "undefined" && widget != null) {
if (typeof widget.getParent != "undefined") {
var par = widget.getParent();
if (domClass.contains(node.domNode || node, 'dijitTabPane')) {
if (typeof par.selectChild != "undefined") {
try {
par.selectChild(widget);
} catch (e) { }
return;
}
}
if (domClass.contains(par.domNode, 'dijitTabPane')) {
this.scrollIntoView(par.domNode);
}
}
}
}
return originalScrollIntoView(node, pos);
});
});
精彩评论