PDA

View Full Version : Ext.ux.Wizard Component for Ext Js 2x



chalu
10 Apr 2008, 9:17 PM
Ext.ux.Wizard Component for Ext Js 2x

If it's just a navigable set of text or html content, or a paginated form (for forms with very many input fields) or a help system, or even a complex wizard with dynamic content and validation .... this component should be helpful.

This extension requires the following extensions :

SlickCardLayout (http://extjs.com/forum/showthread.php?t=15299)
ToolbarLayout (http://extjs.com/forum/showthread.php?t=26480)
Ext.ux.Image (http://code.google.com/p/ext-ux-image/)
Ext.ux.FormGroup (http://extjs.com/blog/2008/05/14/form-group/)
Ext.ux.XMetaForm (http://code.google.com/p/ext-ux-xmetaform/)

Project Home and source is here (http://code.google.com/p/ext-ux-wizard/)

Regards.

wm003
10 Apr 2008, 9:56 PM
Looks very promising! =P~ Keep it up!

sinma
10 Apr 2008, 11:19 PM
Great plugin!

Thanks for share it!

Just a comment, it works with FF, but it shows a javascript exception in IE7.

vahid4134
14 Apr 2008, 9:26 AM
www.petterson-clor.com
is currently UNAVAILABLE
Contact us or login to your account (Website Owner)
:s:s:s

lupin85.luca
16 Apr 2008, 11:21 PM
www.petterson-clor.com (http://www.petterson-clor.com)
is currently UNAVAILABLE
Contact us or login to your account (Website Owner)
:s:s:s

:((:((:((

mdm-adph
17 Apr 2008, 5:50 AM
Coulda uploaded it here, too! I would have liked to see how it stacked up against my "PowerWizard!" :))

chalu
17 Apr 2008, 6:01 AM
Sorry for the expired account, I am working on fixing things, just keep your fingers crossed for a few days. Thanks for waiting.

chalu
18 Apr 2008, 7:59 PM
I have gotten some free web host, you can now view, test and (constructively) criticise this extension.:D:D:D

vahid4134
18 Apr 2008, 11:18 PM
very thx=D>

chalu
21 Apr 2008, 1:41 PM
Recent Updates
1. Resolved IE bug, was due to a trailing comma
2. Added better start up logic to navigation buttons

KRavEN
30 Apr 2008, 4:08 AM
As a note to anyone having problems using this. It requires 2 other extensions and a layout.

Ext.ux.MetaForm.js
Ext.ux.SlickCardLayout.js
Ext.layout.ToolbarLayout.js

KRavEN
30 Apr 2008, 4:29 AM
I've been looking at this and I'm wondering if there is a way to get the next step of the wizard from the selection results of the current page. So if I choose no I would get a different next step than if I were to choose yes.

Itse_Moihnoha
30 Apr 2008, 5:54 AM
Chalu,

Thanks for the code. It was just what I need right now.
Is it possible to at the questionmark tooptip next to a textfield (or other form fields). Can you give an example of json-code that must be send to the script to handle the tooltips.

kind regards

KRavEN
30 Apr 2008, 7:39 AM
I wedged in the sequence control from Ext.ux.PowerWizard so you can skip to different pages depending on the form input.

This enables a config like this:


index: 1,
sequenceControl: [{
key: "opt01", //form element name
values: {
"on": 3 //if the value is on then go to page 3
}
}],
layout: form,
items: [{
xtype: 'checkbox',
name: 'opt01',
fieldLabel: 'Sequence Demo'
}]


One thing I would still like to see is a way to post the form from each panel to get the next panel configuration. This would keep the load size down for very large wizards.

here is my version with sequence control.


/**
* CardLayout Implementation for wizards, uses Saki's MetaForm extension to
* allow dynamic metadata configurations.
*
* @author Charles Opute Odili (chalu)
* @class Ext.ux.Wizard
* @extend Ext.Panel
* @version 1.0
*/

Ext.ux.Wizard = Ext.extend(Ext.Panel, {

/**
* Holder for page sequence order
*/
sequence : {
current : null,
next : null,
stack : []
},

/**
* @cfg Label text for the back navigation button, default is 'Back'
*/
backBtnText : 'Back',

/**
* @cfg Label text for the foward navigation button, default is 'Continue'
*/
nextBtnText : 'Continue',

/**
* Label text for the foward navigation button on the last page / view,
* defaults to null
*/
endBtnText : null,

/**
* Alignment for the navigation buttons, options are 'left' or 'right',
* default is 'right'
*/
buttonAlign : 'right',

/**
* If to animate the navigation, default is true
*/
animate : true,

/**
* Extra buttons to add to the default navigation buttons, defaults to null
*/
extraBtns : null,

initComponent : function() {

var tBar = [];
if (this.extraBtns) {
if (this.extraBtns instanceof Array) {
tBar = this.extraBtns;
} else {
tBar.push(this.extraBtns);
}
}

this.cards = new Ext.ux.MetaForm({
loadingText : this.loadingText,
savingText : this.savingText,
layout : this.animate ? 'slickcard' : 'card',
activeItem : this.activeItem || 0,
region : 'center',
frame : false,
defaults : {
border : false,
bodyStyle : 'padding:10px'
},
autoInit : this.autoInit != undefined ? this.autoInit : false,
url : this.url,
items : this.items
});

this.cards.onMetaChange = this.onMetaChange;

Ext.apply(this, {
layout : 'border',
defaults : {
border : false
},
items : [Ext.apply(new Ext.Panel(this.west || {}), {
region : 'west'
}), Ext.apply(new Ext.Panel(this.north || {}), {
region : 'north'
}), this.cards],
bbar : tBar
});

Ext.ux.Wizard.superclass.initComponent.apply(this, arguments);

this.addEvents({
'start' : true,
'finish' : true,
'beforefinish' : true,
'afternavigate' : true,
'beforenavigate' : true
});

// setup default listeners
this.on({
'beforenavigate' : {
scope : this,
fn : this.onBeforeNavigate
},
'afternavigate' : {
scope : this,
fn : this.onAfterNavigate
},
'beforefinish' : {
scope : this,
fn : this.onBeforeFinish
},
'finish' : {
scope : this,
fn : this.onFinish
},
'start' : {
scope : this,
fn : this.onStart
}
});

this.backBtn = new Ext.Toolbar.Button({
disabled : true,
id : 'move-page-back',
text : this.backBtnText || 'Back',
handler : this.onNavigate.createDelegate(this, [-1])
});

this.nextBtn = new Ext.Toolbar.Button({
id : 'move-page-next',
text : this.nextBtnText || 'Continue',
handler : this.onNavigate.createDelegate(this, [1])
});
},

onMetaChange : function(form, meta) {
this.removeAll();
var activeItem = null;
var pages = meta.pages;
var doConfig = function(config) {
var oConfig;
if (config.items) {
var items = config.items;
if (items instanceof Array) {
Ext.each(items, function(item) {
doConfig(item);
});
} else {
doConfig(items);
}
} else {
// handle plugins
if (config.plugins) {
var plugins = config.plugins;
delete config.plugins;
if (plugins instanceof Array) {
config.plugins = [];
Ext.each(plugins, function(plugin) {
config.plugins.push(Ext.ComponentMgr.create(plugin));
});
} else {
config.plugins = Ext.ComponentMgr.create(plugins);
}
}

// handle regexps
if (config.regex) {
config.regex = new RegExp(config.regex)
}

// to avoid checkbox misalignment
if ('checkbox' === config.xtype) {
Ext.apply(config, {
boxLabel : ' ',
checked : config.defaultValue
});
}

Ext.apply(config, meta.fieldConfig || {});
}
return config;
};

Ext.each(pages, function(page) {
if (!activeItem) {
activeItem = page.isActiveItem ? page.index : 0;
}

var oConfig = doConfig(page);
Ext.apply(oConfig, meta.formConfig || {});
this.add(new Ext.Panel(oConfig));

}, this);

this.getLayout().setActiveItem(activeItem);
this.doLayout(true);
},

getToolbar : function() {
return this.getBottomToolbar();
},

onRender : function() {
Ext.ux.Wizard.superclass.onRender.apply(this, arguments);

var bbar = this.getBottomToolbar();
var lft = this.buttonAlign == 'left' ? '' : '->';
var rgt = this.buttonAlign == 'right' ? '' : '->';
bbar.add(lft, this.backBtn, '', '-', '', this.nextBtn, rgt);
bbar.doLayout();

this.fireEvent('start', this);
},

onNavigate : function(dir) {
var activeItem = this.cards.getLayout().activeItem;
var _self = this;
(function() {
_self.navigate(dir);
}).createInterceptor(function() {
return this.fireEvent('beforenavigate', _self, dir);
}, this)();
},

navigate : function(dir) {
var _self = this;
var layout = this.cards.getLayout();
var currentPage = layout.activeItem;
var cardItems = this.cards.items;
var pageIndex = currentPage.index;
var seqCon = this.sequence;

if (pageIndex != undefined) {
seqCon.current = parseInt(pageIndex)
seqCon.next = this.getSequenceControl(currentPage);
if (!seqCon.next)
seqCon.next = seqCon.current + dir;

this.backBtn.setDisabled(seqCon.next == 0);
if (dir != 1) {
// a back navigation was isssued
seqCon.next = seqCon.stack.pop();
currentPage = this.moveNext(layout, seqCon.next);
if (this.nextBtn.disabled) {
// executed when a back navigation is initiated after the last page
// is reached, so we turn it back on and reset it's label.
// Only disable it in the finish event handler.
this.nextBtn.enable();
this.nextBtn.setText(this.endBtnText);
} else {
if ((this.endBtnText != this.nextBtnText) && (this.nextBtn.getText() == this.endBtnText)) {
this.nextBtn.setText(this.nextBtnText);
}
}
} else if (this.endBtnText && (seqCon.next == cardItems.length - 2)) {
currentPage = this.moveNext(layout, seqCon.next);
seqCon.stack.push(seqCon.current);
this.nextBtn.setText(this.endBtnText);
} else if (seqCon.next == cardItems.length - 1) {
(function() {
currentPage = _self.moveNext(layout, seqCon.next);
seqCon.stack.push(seqCon.current);
_self.fireEvent('finish', _self);
}).createInterceptor(function() {
return this.fireEvent('beforefinish', _self, 1);
}, this)();
} else {
// just move on
currentPage = this.moveNext(layout, seqCon.next);
seqCon.stack.push(seqCon.current);
}

this.fireEvent('afternavigate', _self, seqCon.next);
}
},

moveNext : function(layout, dir) {
layout.setActiveItem(dir);
return layout.activeItem;
},

getSequenceControl : function(panel) {
var returnValue = null;
var nextCard = null;
if (panel.sequenceControl) {
var ext_formValues = this.cards.getForm().getValues();
Ext.each(panel.sequenceControl, function(field) {
// if this sequence field's key is present in this panel's values,
// check to see if its value has a corresponding sequence number, and
// log it
// (will iterate through all sequence fields, grabbing the last one)
nextCard = field.values[ext_formValues[field.key]];
if (nextCard) {
returnValue = nextCard;
}
}, this);
}
return returnValue;
},

/**
* Called before a navigation occurs, implementations can return false to stop
* the navigation, Same can be achieved by listening for the 'beforenavigate'
* event.
*
* @param wizard
* {Ext.ux.Wizard} The wizard object
* @param dir
* {Number} The navigation direction
* @return {Boolean} True to proceed with the navigation, false to cancel it
*/
onBeforeNavigate : function(wizard, dir) {
return true;
},

/**
* Called after a navigation occurs, implementations can use this to
* pre-configure the activeItem Same can be achieved by listening for the
* 'afternavigate' event.
*
* @param wizard
* {Ext.ux.Wizard} The wizard object
* @param dir
* {Number} The navigation direction
*/
onAfterNavigate : function(wizard, dir) {

},

/**
* Called when the last page is reached, Implementations can add more
* functionality like closing the panel's container window (if any). The
* default is to disable the 'next' navigation button at this page.
*
* @param wizard
* {Ext.ux.Wizard} The wizard object
*/
onFinish : function(wizard) {
this.nextBtn.setDisabled(true);
},

/**
* Called immediately after the panel is rendered and is ready to start
* navigation.
*
* @param wizard
* {Ext.ux.Wizard} The wizard object
*/
onStart : function(wizard) {

},

/**
* Called when the penultimate page is reached, a form implementation can use
* this for validation, and submiting of the values, then the finish event can
* be handled to display results of the submission if needed. Return false to
* prevent navigation to the final page.
*
* @param wizard
* {Ext.ux.Wizard} The wizard object
* @param dir
* {Number} The navigation direction
* @return {Boolean} True to proceed with the navigation, false to cancel it
*/
onBeforeFinish : function(wizard, dir) {
return true;
}
});

Ext.reg('wizard', Ext.ux.Wizard);

KRavEN
1 May 2008, 4:12 AM
Just found out no version works in IE6.

KRavEN
1 May 2008, 7:16 AM
It's a problem with the border layout. West needs a width or center will render off screen in IE6. I gave it a width of 0 and it's working now. It's also important to do autoHeight: true, autoScroll: true in the defaults of this.cards to resolve height issues for the hidden cards.

chalu
2 May 2008, 2:34 AM
I will take a look at the 'sequence control' feature you talked about, though I intended for implementations to do stuff like that by listening for the wizard's events and handling them as necessary. With the wizard (in theory) you can have a handler for the 'beforenavigate' event, handlers get called with a reference to the wizard and the navigation direction, you can now inspect what ever field value you wish in the current page and route to a desired page as necessary. This (in theory) should be handy also if you wish to do other things apart from 'routing' the wizard, things like making XHR and doing stuff with the response to the wizard.

Thanks for your inputs.

KRavEN
2 May 2008, 6:06 AM
The sequence control just gives the added functionality of handling the next page in the config instead of writing a listener to do it. It's not required, so either way will work.

chalu
3 May 2008, 10:16 AM
MetaForm (though sinsible) breaks the
standard for form submission in the Ext library, by requiring that the packet returned
by the server always contain a 'data' property else a failure type of
Ext.form.Action.LOAD_FAILURE is assumed.
Application of this extension therefore requires a 'data' property in the
packet sent from the server (even if it is empty) to function properly.

KRavEN
6 May 2008, 9:20 AM
Here's a quick little validate method for the wizard. You can use this to validate each form field in the beforenavigate listener.

/**
* Validates each form field
*
* @return {Boolean} false if validation failed on any field, true if no invalid fields
*/
validate : function() {
var valid = Ext.each(this.cards.findBy(function(c){return c.isFormField === true}), function(field) {
field.validate();
return field.isValid();
});
return (valid >= 0)?false:true;
},

then I just do a "return wizard.validate()" in the beforenavigate listener.

KRavEN
6 May 2008, 11:50 AM
And another to check just the form on the active card.


/**
* Validates the active card form only
*
* @return {Boolean} false if validation failed on any field, true if no invalid fields
*/
validateCard : function() {
var active = this.cards.getLayout().activeItem;
var valid = Ext.each(active.findBy(function(c){return c.isFormField === true}), function(field) {
field.validate();
return field.isValid();
});
return (valid >= 0)?false:true;
}

KRavEN
7 May 2008, 9:42 AM
If you have columns in any of your forms then you will need to do:

wizard.cards.getLayout().activeItem.doLayout();

in an afternavigate listener. This is required or the columnWidth and anchor properties won't be applied to the form.

Might be a good idead to add this to the onAfterNavigate method in Ext.ux.Wizard. I don't see where it would harm anything.

chalu
7 May 2008, 1:03 PM
I will consider these suggestions in due time, have been 'away' on some project, please bear and thanks for holding on=D>
I think the issue for columns on the 'cards' is from the MetaForm extension implementation which they are based on.
I have done some re-work on it but it's barely finished

KRavEN
3 Jun 2008, 4:59 AM
I've done some rework on MetaForm myself, mainly with suggestions you had made in the other thread plus some tweaks.

I've also done a great deal of work on Ext.ux.Wizard to suit my needs including adding additional cards from the server and a ton of convenience methods.

I've attached both plus all the required templates, extensions, and css.

chalu
3 Jun 2008, 8:25 AM
I am about uploading my current changes for the wizard, and a new metaform. I'll look at your code. cheers.

chalu
3 Jun 2008, 8:49 PM
Take a look at post #1 to grab the latest updates, I am hoping to finish off very soon.
Must say a big thank you to KRaVEN and all others for their contributions thus far.

chalu
5 Jun 2008, 4:40 AM
I've done some rework on MetaForm myself, mainly with suggestions you had made in the other thread plus some tweaks.

I've also done a great deal of work on Ext.ux.Wizard to suit my needs including adding additional cards from the server and a ton of convenience methods.

I've attached both plus all the required templates, extensions, and css.

How did you implement adding additional cards from the server, is it with the 'metacomplete' event you added to metaform ??

KRavEN
5 Jun 2008, 4:49 AM
Did you see my changes in onMetaChange in Ext.ux.Wizard? They allow you to load extra pages from the server via metaform. It gets your current page number and adds other pages in sequence.

So if you have a wizard with pages 0 through 6 and you're at page 3, do a load, and the metadata gets a return of pages 0 through 6. It removes page 4 through 6 already in the wizard, renumbers the received pages to 4 through 10, and adds them to wizard.

KRavEN
5 Jun 2008, 5:00 AM
I did a lot of work with metaform yesterday.

It still needs some work with the onMetaChange method as right now things don't work quite right if there isn't a fieldset or tabpanel defined to hold the form fields.

I was able to fix the form handling so all the expected metaform.form methods work no matter how deeply nested the form elements are in the metadata.

Attached is what I have. I'm thinking on the best way to fix onMetaChange so it will work with Saki's original simple form example as well as complex forms with tabpanels and fieldsets.

KRavEN
5 Jun 2008, 5:11 AM
How did you implement adding additional cards from the server, is it with the 'metacomplete' event you added to metaform ??
Ohh, metacomplete is a convenience event I added because I'm loading an empty tabpanel in my metadata and needed to know when it was done so I could add some grids to the tabpanel. onactioncomplete could have almost worked but I needed something that fired only after new metadata had been loaded and processed.

KRavEN
5 Jun 2008, 5:15 AM
I usually hang out in #extjs and #sfExtjsThemePlugin on undernet if you wanted to work together on this realtime.

chalu
5 Jun 2008, 8:03 AM
I usually hang out in #extjs and #sfExtjsThemePlugin on undernet if you wanted to work together on this realtime.
Yeah I'd love that, I was about saying that we merge our 'files' into 'one' and work on that set till we are okay. We need to be able to access that single set anytime, instead of attaching every update to this thread, which will be hard to track. I am very new to SVN, I am in Nigeria, with not so good internet access, so 'work together on this realtime' may not be easy. I am thinking google code :):)

I really don't understand '#extjs and #sfExtjsThemePlugin on undernet'
grab latest updates again from post #1
Thanks.

KRavEN
6 Jun 2008, 3:21 AM
Yeah I'd love that, I was about saying that we merge our 'files' into 'one' and work on that set till we are okay. We need to be able to access that single set anytime, instead of attaching every update to this thread, which will be hard to track. I am very new to SVN, I am in Nigeria, with not so good internet access, so 'work together on this realtime' may not be easy. I am thinking google code :):)

I really don't understand '#extjs and #sfExtjsThemePlugin on undernet'
grab latest updates again from post #1
Thanks.

undernet is irc.undernet.org, which is an irc chat server. #extjs is a chat channel.

But yeah, if you're not comfortable with SVN googlecode is fine with me.

JEBriggs
7 Jun 2008, 7:45 AM
Interesting...do you have any examples?

chalu
8 Jun 2008, 11:03 AM
Interesting...do you have any examples?
The download in post #1 has an example

JEBriggs
9 Jun 2008, 6:39 AM
The download in post #1 has an example

Thanks, I got it and got it up and running quickly. Originally, I was unable to unzip the files using WinZip which always works for me. I used a another tool, BitZipper, and that unzipped the files.

chalu
13 Aug 2008, 2:43 AM
I tried the new release on the wizard and discovered several issues :

1. combo boxes initialized with arrays no longer show their selection lists. When I click on the trigger button I get these errors :


ls.push is not a function http://localhost/lib/extjs/ext_2_2/ext-all-debug.js Line 1524
// and then this on a second attempt
this.view is undefined http://localhost/lib/extjs/ext_2_2/ext-all-debug.js Line 27812


2. the Ext.ux.ScreenshotField component no longer works within the wizard (it seems ok as standalone). I keep getting :


ls.push is not a function http://localhost/lib/extjs/ext_2_2/ext-all-debug.js Line 1524

this is thrown from inside the addListener function of Ext.

I have re-uploaded the zip file. In the far left region of the sample page, click the 'wizard' tree node then click the 'basic usage' child-node. From the wizard window try to use the gender combo.

You can also uncomment the last set of 'pages' in the wizard config to see similar set of errors.

chalu
14 Aug 2008, 12:43 AM
For the Ext.ux.ScreenshotField component, the errors are raised from the methods where I attach event handlers, strange :-/:-/.


addClipListeners: function(){
this.clipEl.on({
'mousemove': this.onButtonMouseMove,
'mouseover': this.onButtonMouseMove,
scope: this
});
}

.......

createInputFile: function(){
....

// setup events
this.inputFileEl.on({
'click': this.onInputFileClick,
'change': this.onInputFileChange,
'focus': this.onInputFileFocus,
'select': this.onInputFileFocus,
'blur': this.onInputFileBlur,
scope: this
});
}


These are standard ways of using event handlers in Ext why do there fail in this component :-/ If I comment these blocks of code the wizard gets rendered (with the passport field non-functional of course).

For the not-populated combo dropdown, I am yet to figure out what the issue is :-/:-/

KRavEN
15 Aug 2008, 10:33 AM
Yeah. I'm seeing the same thing with the combos and static stores. I can say the problem is not in Combobox.js. Thread here with people having similar issues: http://extjs.com/forum/showthread.php?p=208829

I'm thinking it might be combo when a child of a panel other than formpanel

chalu
10 Feb 2009, 9:39 PM
Announcing a new development release, see post #1

Scorpie
12 Feb 2009, 6:00 AM
Nice extension!

Jangla
31 Mar 2009, 5:58 AM
The download in post #1 has an example
Unless I'm missing something, I can't see a download in post #1 - just a link to the project page which in turn has no examples to download.

Jangla
2 Apr 2009, 7:19 AM
I've managed to overome my stupidity and get the source for this now but there's a funny little "glitch" with it: there's a little blue dot just below the header to the left of the panel. It's evident on the screen shots in post #1 too. Can't get rid of it for the life of me - any clues?

I'd also like a couple of pointers on another issue I'm having with it: I've used the version that uses the metaform extension to load items from a php file. All fine and dandy. Only thing is, now I want one of the panels that is defined in this php file to call another php file to populate a CheckTree extension that's on step 2 of my wizard. From what I've seen and tried, I don't think this is possible so I'm resorting to try and load this data after the wizard has got it's card definitions. Without much luck. Pointers appreciated. Code snippets below.



win = new Ext.Window({
id: Ext.id(),
layout:'fit',
height: 500,
width: 280,
modal: true,
shadow: 'frame',
shadowOffset: 4,
constrain: true,
center: true,
title: 'Availability search',
items: {
id: 'availabilility-search-wizard',
xtype: 'wizard',
animate: true,
height: 350,
helpBtn: null,
reviewEntries: false,
headerConfig: {
titleText: 'Search for availabile properties',
titleImg: 'fileadmin/templates/scripts/extJS/resources/images/default/s.gif'
},
autoInit: {
url: 'fileadmin/templates/scripts/wizardconfig.php',
params: {
query: 'get',
mode: 'userprofile'
}
}
,
listeners: {
'afterrender': function(){
alert("rendered"); // placeholder - can't get this to fire at all

}
}
});
win.show();

tree = new Ext.ux.tree.CheckTreePanel({
title:'Countries/regions',
id:'tree',
width:300,
height:250,
autoScroll:true,
rootVisible:false,
root:{
nodeType:'async',
id:'root',
text:'root',
expanded:true,
uiProvider:false
},
loader:{
url:'get-regions.php'
}]
});


and this was my initial attempt at using the metaform idea to load a further php file:



..............
array(
'index' => 1,
'layout' => 'form',
'trailText' => 'Country/region',
"defaults"=>array(
"width"=>130
),
'items' => array(
'title' => 'Countries/regions',
'id' => 't2',
'width' => 245,
'height' => 300,
'autoScroll' => true,
'rootVisible' => false,
'root' => array(
array(
'nodeType' => 'async',
'id' => 'root',
'text' => 'root',
'expanded' => true,
'uiProvider' => false
)
),
'loader' => array(
array(
'url' => 'process-request.php',
'baseParams' => array(
array(
'cmd' => 'getTree',
'treeTable' => 'tree',
'treeID' => 1
)
)
)
),
'tools' => array(
array(
'id' => 'refresh',
'qtip' => 'Reload Tree',
'handler' => 'function() {t2.getRootNode().reload();' // this is where I started to realise that this probably wasn't going to work!
)
)
)
)
............

xadag
3 Apr 2009, 12:39 AM
Hi,

Nice extension but in the source i can't found the css used for the wizard in the example : ToolbarLayout.css and Ext.ux.FormGroup.css
Where are them?

Thanks!

Jangla
6 Apr 2009, 12:52 AM
I have a few questions regarding validation - which seems to be one of the most powerful and yet least documented features of Ext.

Essentially I'm looking for good learning resources for general setting up of new validation vtypes for Ext.

In addition, some guidance on validation specifics for this wizard may also be a great help. For example, I'd like to set the validation on my wizard so the date range picker I've added to step three have a minimum range based on the value of a number field in the previous step. Or I'd like to make the selection of at least one node on a Check Tree mandatory, for example.

So, anyone able to help with validation bits? :D

ec-cts
7 Apr 2009, 6:45 AM
I created a wizard with this extension, which essentially consists of 4 steps, which are four formPanel with forms inside.

In the first form, I have a field that is a combobox in which I select a customer, once selected to make a request to the server of the customer data and the data to fill in all fields of the first form, and some fields of the remaining forms.

The problem is that I do not populated the data from the first form.

However, that first form (a formpanel) delivered through a single window, without any change, it works perfectly, but in the wizard, do not populated fields.

Is this normal operation of wizard?

I do something special for me to work or is that the very definition of the wizard, does not allow it?

I put the script completely.



(function(){

var ruta = 'modulos/aplicaciones/contabilidad/1.-archivos/3.-nueva_empresa/script.php';

var storeListarClientes = new Ext.data.JsonStore({
url: ruta
,method: 'POST'
,baseParams: { action: 'listarClientes' }
,autoLoad: true
,fields: [
{name: 'numcliente'}
,{name: 'nomcliente', type: 'string'}
]
});

var storeTipoPlanes = new Ext.data.JsonStore({
url: ruta
,method: 'POST'
,baseParams: { action: 'listarTipoPlanes' }
,autoLoad: true
,fields: [
{name: 'NumPlan'}
,{name: 'Nombre', type: 'string'}
]
});

var formIdentificacion = new Ext.form.FormPanel({
index: 0
,title: 'Identificación'
,layout: 'form'
,labelWidth: 130
,border: false
,reader: new Ext.data.JsonReader({
fields: [
{name: '__id'},
{name: 'nif'},
{name: 'nombre'},
{name: 'municipio'},
{name: 'provincia'},
{name: 'cpostal'}
]
})
,items: [{
xtype: 'textfield'
,fieldLabel: 'Núm. Empresa'
,name: 'numempresa'
,anchor: '20%'
,allowBlank: false
},{
xtype: 'combo'
,fieldLabel: 'Cliente'
,id: 'idcliente'
,name: 'cliente'
,hiddenName: 'cliente'
,store: storeListarClientes
,displayField: 'nomcliente'
,valueField: 'numcliente'
,triggerAction: 'all'
,mode: 'local'
,anchor: '50%'
,emptyText: 'Seleccione un Cliente por favor...'
,listeners: {
'select': function(cmb, data, idx) {
formIdentificacion.form.load({
url:ruta
,waitMsg:'Cargando ...'
,method: 'POST'
,params: {
action: 'cargarDatosClientes'
,cliente: this.value
}
});
}
}
},{
xtype: 'textfield'
,fieldLabel: 'Nif'
,name: 'nif'
,id: 'nif'
,anchor: '25%'
},{
xtype: 'textfield'
,fieldLabel: 'Nombre Cliente'
,name: 'nombre'
,id: 'nombre'
,anchor: '50%'
},{
xtype: 'textfield'
,fieldLabel: 'Dirección'
,name: 'direccion'
,anchor: '50%'
},{
xtype: 'textfield'
,fieldLabel: 'Población'
,name: 'municipio'
,id: 'municipio'
,anchor: '50%'
},{
layout: 'column'
,anchor: '50%'
,border: false
,items:[{
columnWidth: .6
,layout: 'form'
,labelWidth: 130
,autoHeight: true
,border: false
,items: [{
xtype: 'textfield'
,fieldLabel: 'Provincia'
,name: 'provincia'
,id: 'provincia'
,anchor: '92%'
},{
xtype: 'textfield'
,fieldLabel: 'Teléfono'
,name: 'telefono'
,anchor: '92%'
}]
},{
columnWidth: .4
,layout: 'form'
,labelWidth: 130
,autoHeight: true
,labelWidth: 80
,border: false
,items: [{
xtype: 'textfield'
,fieldLabel: 'Código Postal'
,name: 'cpostal'
,id: 'cpostal'
,anchor: '100%'
},{
xtype: 'textfield'
,fieldLabel: 'Fax'
,name: 'fax'
,anchor: '100%'
}]
}]
},{
xtype: 'textfield'
,vtype: 'email'
,fieldLabel: 'Email'
,name: 'email'
,anchor: '50%'
},{
xtype: 'combo'
,fieldLabel: 'Plan de Contabilidad'
,store: storeTipoPlanes
,triggerAction: 'all'
,name: 'placon'
,mode: 'local'
,anchor: '50%'
,emptyText: 'Seleccione un Plan de Contabilidad por favor...'
,displayField: 'Nombre'
,valueField: 'NumPlan'
}]
});

var formFiscalesRegistrales = new Ext.form.FormPanel({
layout: 'fit'
,index: 1
,title: 'Fiscales/Registrales'
,autoHeight: true
,frame: false
,border: false
,bodyStyle: 'padding: 10px;'
,items: [{
xtype: 'fieldset'
,title: 'Datos Fiscales'
,collapsible: false
,collapsed: false
,autoHeight: true
,anchor: '98%'
,items: [{
layout: 'form'
// ,labelWidth: 120
,border: false
,autoHeight: true
,items: [{
xtype: 'combo'
,fieldLabel: 'Cnae'
// ,store: storeListarClientes
,triggerAction: 'all'
,mode: 'local'
,anchor: '50%'
},{
layout: 'column'
,anchor: '50%'
,border: false
,items:[{
columnWidth: .4
,layout: 'form'
,autoHeight: true
,border: false
,items: [{
xtype: 'combo'
,fieldLabel: 'Delegación'
,anchor: '92%'
}]
},{
columnWidth: .6
,layout: 'form'
,autoHeight: true
,labelWidth: 80
,border: false
,items: [{
xtype: 'textfield'
,hideLabel: true
,anchor: '100%'
}]
}]
},{
xtype: 'combo'
,fieldLabel: 'Administración'
,triggerAction: 'all'
,mode: 'local'
,anchor: '50%'
},{
layout: 'column'
,anchor: '60%'
,border: false
,items:[{
columnWidth: .7
,layout: 'form'
,autoHeight: true
,border: false
,items: [{
xtype: 'textfield'
,fieldLabel: 'Respresentante'
,anchor: '92%'
}]
},{
columnWidth: .3
,layout: 'form'
,autoHeight: true
,labelWidth: 30
,border: false
,items: [{
xtype: 'textfield'
,fieldLabel: 'Nif'
,anchor: '100%'
}]
}]
}]
}]
},{
xtype: 'fieldset'
,collapsible: false
,collapsed: false
,autoHeight: true
,anchor: '98%'
,items: [{
layout: 'form'
,labelWidth: 120
,border: false
,autoHeight: true
,items: [{
xtype: 'textfield'
,fieldLabel: 'Cuenta Ingreso'
,anchor: '98%'
},{
xtype: 'textfield'
,fieldLabel: 'Cuenta Devolución'
,anchor: '98%'
}]
}]
},{
xtype: 'fieldset'
,collapsible: false
,collapsed: false
,autoHeight: true
,anchor: '98%'
,items: [{
layout: 'column'
,anchor: '100%'
,border: false
,items:[{
columnWidth: .2
,layout: 'form'
,labelWidth: 120
,border: false
,autoHeight: true
,items: [{
xtype: 'checkbox'
,fieldLabel: 'Enlace con diario'
}]
},{
columnWidth: .2
,layout: 'form'
,border: false
,autoHeight: true
,items: [{
xtype: 'checkbox'
,fieldLabel: 'Sin actividad'
}]
},{
columnWidth: .2
,layout: 'form'
,labelWidth: 120
,border: false
,autoHeight: true
,items: [{
xtype: 'checkbox'
,fieldLabel: 'Dev.Mensual Iva'
}]
},{
columnWidth: .4
,layout: 'form'
,labelWidth: 80
,border: false
,autoHeight: true
,items: [{
xtype: 'radiogroup'
,fieldLabel: 'Modo Pago'
,items: [{
boxLabel: 'Efectivo'
,name: 'rb-auto'
,checked: true
,inputValue: 'Efectivo'
},{
boxLabel: 'Adeudo Cta'
,name: 'rb-auto'
,inputValue: 'Adeudo Cta'
}]
}]
}]
}]
},{
xtype: 'fieldset'
,collapsible: false
,collapsed: false
,autoHeight: true
,anchor: '98%'
,items: [{
layout: 'column'
,anchor: '100%'
,border: false
,items:[{
columnWidth: .2
,layout: 'form'
,labelWidth: 40
,border: false
,autoHeight: true
,items: [{
xtype: 'textfield'
,fieldLabel: 'Tomo'
,anchor: '90%'
}]
},{
columnWidth: .2
,layout: 'form'
,labelWidth: 40
,border: false
,autoHeight: true
,items: [{
xtype: 'textfield'
,fieldLabel: 'Folio'
,anchor: '90%'
}]
},{
columnWidth: .2
,layout: 'form'
,labelWidth: 40
,border: false
,autoHeight: true
,items: [{
xtype: 'textfield'
,fieldLabel: 'Hoja'
,anchor: '90%'
}]
},{
columnWidth: .4
,layout: 'form'
,labelWidth: 50
,border: false
,autoHeight: true
,items: [{
xtype: 'textfield'
,fieldLabel: 'Registro'
,anchor: '95%'
}]
}]
}]
}]
});


//with this vindow, populated ok the fields of form
/*The same form (first) in different windows, it works differently. */

var window = new Ext.Window({
title: 'Ventana de prueba',
iconCls: 'edit',
id: 'window',
width: 550,
height:230,
layout: 'fit',
buttonAlign:'center',
closable: false,
resizable: true,
items: formIdentificacion,
buttons: [{
text: 'Grabar',
iconCls:'icon-disk'
},{
text: 'Cancelar',
iconCls:'icon-cancelar'
}]
});
return window;


//THE WIZARD, DON'T POPULATED THE FIELDS
/*//////////////////////////////////////////////////////////////*/
/*
var wizard = new Ext.ux.Wizard({
xtype: 'wizard'
,animate: true
,frame: false
,border: false
,reviewEntries: true
,helpBtn: false
,baseCls: 'x-panel-mc'
,reviewTitle: 'Resumen'
,backBtnText: 'Anterior'
,nextBtnText: 'Siguiente'
,endBtnText: 'Finalizar'
,replayBtnTxt: 'Crear y Continuar'
,replayTo: 1
,headerConfig: {
titleText: 'Crear una nueva Empresa'
,stepText : 'Paso {0} de {1} {2}'
}
,items: [formIdentificacion, formFiscalesRegistrales]
,listeners: {
'finish': function(){
this.submit({
success: function(form, action, mode){
win.close();
}
});
}
,'replay': function(index){
this.submit({
success: function(form, action, mode){
this.doReplay(index);
}
});
}
}
});

return wizard;
*/
/*//////////////////////////////////////////////////////////////*/


})()


Thanks in advance.

Carlos Torres

Jangla
14 Apr 2009, 5:40 AM
I have a question regarding validation on this extension: my wizard has a checkbox group on one card of the wizard. I need to allow users to select none or sequential check boxes. I've tried adding a validator function to the checkboxgroup but that doesn't seem to be a valid option. So how else can I do it? Basically the wizard should act as if it's valid when nothing is checked, valid whilst checks are being made by the user and instantly invalid if they select a box that's non-sequential with their previous selections. Oh, and one more thing - the checkboxgroup I'm using is to pick days of the week therefore selecting monday and sunday (or any other selection that rolls over) is also valid.

So, cutting the crap - how do I attach a function to a checkboxgroup to validate it and disable the wizard's next button when an invalid state is detected?

chalu
14 Apr 2009, 6:28 AM
Sorry guys, I really did not mean to ignore you, I am yet to fully recover from a malaria attack. Will get back to active development when I am strong again. Thanks for your interest.

Jangla
22 Apr 2009, 7:37 AM
Whoa - malaria! Nasty. Guess I'd better ask anyone else who's subscibed to this thread in cast they can help then.

Say I've got a control on a form on a step in the wizard. This control doesn't usually have validation but I've managed to put something basic together by marking the control as invalid, adding an event listener to call a function to validate and then that function calling clearInvalid if required.

Only trouble is, the Next button doesn't go disabled when markInvalid() is called.

Any advice from anyone?

descheret
24 Apr 2009, 8:02 AM
hello when I implement this extensions its overwriting all the button styles on the rest of the page. (if I remove the JS file: Ext.layout.ToolbarLayout.js it's ok...)

but the bigger problem I have - with all examples I could find is that the trigger button is on the wrong side of the combos - the selectlist is also not visable...

with the meta example I have also problems with the label width. it's fixed to 100px but I gave them 250:



$formConfig = array(
'labelAlign' => 'left',
'labelWidth' => 250,
'defaults' => array(
'msgTarget' => 'qtip',
'labelSeparator' => ''
)
);
I'm using the latest EXT 2.x js downloads. maybe I haven't the latest files or it isn't working well with the latest ext 2.x version?

In IE6 it looks good - but not in FF 3

does any one has an idea? I really like to use this extension :o)

thanks
ronald

chalu
27 Apr 2009, 11:12 PM
Looking at these issues, will give feedback soon.

descheret
28 Apr 2009, 12:53 AM
hi chalu,

I found a "hot fix" for this in the ext-all.css in line 794:




.ext-safari .x-form-field-wrap .x-form-trigger,.ext-gecko .x-form-field-wrap .x-form-trigger{
right:0;
}

If I commented out this lines it works.

I could fix also my problem with the lablewidth - I didn't realized that each fileset needs his own labelwidth tag - copying this in each fileset definition works.

But there is another problem popped up if I'm using checkboxes AND the reviewEntries function of the wizard the review table isn't there. If I remove the page with the checkboxes it's working :(




array(
'index' => 6,
'items' => array(
array(
'xtype' => 'label',
'autoHeight' => true,
'html' => 'We need to request some personal information before you can register. <br /><br />'
),
array(
'xtype' => 'checkbox',
'name' => 'opt_in',
'autoHeight' => true,
'hideLabel' => true,
'boxLabel' => 'I agree to my personal information being processed',
'inputValue' => 1
),
array(
'xtype' => 'checkbox',
'name' => 'agb',
'autoHeight' => true,
'hideLabel' => true,
'boxLabel' => 'YES. I would like to receive letters',
'inputValue' => 1
)



)
)


I removed nearly all pages and arrays - even if there is a checkbox it doesn't work :(

thanks guys
ronald

Fabyo
30 Apr 2009, 3:31 AM
Where is the source?

I can not download it

Jangla
30 Apr 2009, 3:35 AM
How can I force a card to be invalid (so the Next button is disabled)? I have a control on a form on a card and it has no proper validation so I need to run a little code on the control's click event to check for validation. I can then disable the card to begin with and enable once it passed validation. The control is a checkboxgroup in case that helps.

Sesshomurai
2 May 2009, 9:07 PM
To the author of this extension.

Its really nice! But some of the form field types do not work in Ext 3. Like datefield and combo. The field icons are on the left and do not trigger. I suppose its the same problem as the poster above.

When I switch to Ext2 it works again. I will see if I can fix it, but not sure where to look.

------------------------------------------------

The hot fix suggested by descheret corrects the errant trigger button.

----------------------------------------------

Is it possible to load the form field data from the server? I was looking for a .load() method similar to form, but didn't see. I don't load my forms from server, but need the fields filled in with data before viewing. Thanks for any tips, otherwise I will try to add this ability.

Jangla
9 Oct 2009, 6:25 AM
To the author of this extension.

Its really nice! But some of the form field types do not work in Ext 3. Like datefield and combo. The field icons are on the left and do not trigger. I suppose its the same problem as the poster above.

When I switch to Ext2 it works again. I will see if I can fix it, but not sure where to look.

I've got other problems in Ext3 - form fields, if hidden still show their label!

For example, I have a card that has a couple of radio buttons that should flick between what's visible on the card.

Have a look at the screen shots - you can see that all the labels are visible no matter what. The fields hide perfectly but the labels don't.

Also, msgTarget doesn't work properly. The element is there but entering invalid data into a field doesn't show the element.

Mthor
18 Nov 2009, 8:16 AM
Jangla

did you ever get the card validation with your checkbox group?


show the code that is relevant to your problem above and i can look at it

Mthor
18 Nov 2009, 2:45 PM
jangle I fiqured out the disable the next button when coming to the current card


wizPhone.on('afternav', function(direction) {
if (this.getActiveCard().index == 3) {
Ext.getCmp('move-page-next').setDisabled(true);
}
});

Mthor
24 Nov 2009, 7:35 AM
I came across a problem in the validation when I skipped cards that had AllowBlank: true or a validate on textfield . The wizard would not submit at the end if I skipped over a card with validation. the scenario was, some times the user could add a user or sometimes add a user and a phone. or some times add a user and an existing phone to the user. since there will need to be validation on all form fields and some were skipped we were at a problem.

what i did to make validation happen on each card as you go through the wizard

Ext.ux.Wizard.js change


validate: function () {
// return this.cards.isValid(true, false);
return true;
},
just comment out and return true and then add


clientValidation: false

in your onFinish

Jangla
25 Feb 2010, 4:13 AM
Jangla

did you ever get the card validation with your checkbox group?


show the code that is relevant to your problem above and i can look at it

I did - I employed animal to re-script my checkboxgroup control so it would validate when users clicked any box, negating the need to check validity when the user clicks next in the wizard.

BTW - anyone know if this has been officially updated to v3 yet? I'm experiencing issues with mine after attempting to upgrade and I'm not sure whether it's just this control that's the problem or something else.

chalu
2 Mar 2010, 11:34 PM
I am very sorry folks for been away, I have not been active with ExtJs for a very long time now, I am sure that in a few weeks I'll be back here, thanks for your continued interest.

Jangla
19 Mar 2010, 3:09 AM
I've got an issue in IE (unsurprisingly!). The header isn't visible. For some reason it's coming through with an in-line style of height 0.

Here's a link: http://www.holiday-chateau.com/index.php?id=10790

Works perfectly in FF and Chrome but not in IE - any fixes out there?

Mthor
1 Apr 2010, 10:38 AM
I tried to add the code below to skip a card by skip:true what am I doing wrong, or is there skip card already in this wizard


setSkip: function(skip) {
if (this.wizard.cards[this.wizard.currentCard] == this)
return false;
if (this.skip != skip) {
this.skip = skip;
this.wizard.headPanel.initIndicators();
this.wizard.headPanel.updateStep();
return true;
}
return false;
}