PDA

View Full Version : Way to get labelAlign : 'top' working in custom form field?



Jangla
24 Apr 2013, 2:10 PM
I have a custom flash component thingy I'm building and while it mostly works fine, I've come across a use case where having a top aligned label would be really handy to help the field fit in a much smaller space than usual.

Of course, labelAlign: 'top' is the required config but for some reason, my form field has it's label markup rendered last and appears below the component:






Ext.define( 'Ext.MyComponent', {
extend : 'Ext.form.FieldContainer',
alias : 'widget.mycomponent',


mixins : {
field : 'Ext.form.field.Field'
},


isFormField : true,


config : {
cls : 'mycmp-cls'
},


constructor : function ( cfg ){
var me = this;


me.initConfig( cfg )


var instanceIndex = me.config.instanceIndex,
batchId = me.config.batchId


me.buildFieldObjects();


me.initField();


Ext.apply( me, {
id : instanceId + 'LightUploader' || Ext.id(),
items : [
me.flashContainer,
me.imageContainer,
me.inputField = {
xtype : 'hidden',
id : instanceId,
name : submitName
},
{
xtype : 'hidden',
id : instanceId + 'containerId',
name : instanceId + 'containerId',
value : containerId
}, {
xtype : 'hidden',
id : instanceId + 'containerRefId',
name : instanceId + 'containerRefId',
value : containerRefId
}, {
xtype : 'hidden',
id : instanceId + 'batchId',
name : instanceId + 'batchId',
value : batchId
}
]
} );




me.callParent( arguments );
},




buildFieldObjects : function (){
var me = this;


me.innerContainer = {
xtype : 'flash',
height : 185,
width : 400,
cls : 'my-flash-panel',
hideMode : 'nosize',
id : me.config.instanceId + 'SWFContainer',
url : '/flash/path/mySWF.swf',
flashParams : {
wmode : 'transparent',
quality : 'high',
allowScriptAccess : 'sameDomain',
movie : 'mySWF.swf'
},
flashVars : Ext.apply({
uploaderMode : 'normal',
maxCropWindowWidth : 1200,
maxCropWindowHeight : 700,
minImageScale : 0.5,
maxImageScale : 3
}, me.config)
}


me.imageContainer = {
xtype : 'container',
isFormField : false,
id : me.config.instanceId + 'ImgContainer',
cls : 'myCompImgContainer',
hidden : true,
items : {
xtype : 'myinnerwidget',
width : 400,
tpl : GLOBAL.innerTpl,
store : GLOBAL.innerStore
}
}


}
} )



Note that I've cut out some of the methods from the above as setValue, getValue etc are unlikely to have any impact.

Regardless, the labelCell is rendered after the last hidden field you see in the code above.

So, is it simply some agressive CSS I'm missing to push the label to the top of the field? (unlikely looking at other simple components based on a FieldContainer) or is there something else I'm missing?

Arg0n
25 Apr 2013, 12:29 AM
I think it's the labelable mixin which could handle this: http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.form.Labelable

I (http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.form.Labelable) tried to get this thing working too on a custom field... and I gave up xD


My custom field is extending the fieldContainer now, which uses the labelable thing too:

http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.form.FieldContainer

So let your field extend the fieldContainer and it should work. But you have to change some methods maybe.


(http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.form.FieldContainer)

Jangla
25 Apr 2013, 12:38 AM
I'm already extending fieldContainer and have tried using the labelable mixin - same result; label cell is rendered at the bottom of the control when labelAlign: 'top' is specified.

Arg0n
25 Apr 2013, 12:56 AM
Oh... my fault...

It's hard to say what's wrong then... I can show you my custom field:




Ext.define('Ext.ux.form.field.ImagePreview', {
extend:'Ext.form.FieldContainer',


isFormField: true,


requires: [
'Ext.panel.Panel',
'Ext.button.Button',
'Ext.Img'
],


alias: 'widget.imagepreview',


layout: 'hbox',


/**
* @cfg {Object} image
*
* Config für das Bild
*/
image: null,


/**
* @cfg {Object} button
*
* Config für den Button
*/
button: null,


value: 0,


height: 100,


items: [{
xtype: 'image',
flex: 1
}, {
xtype: 'splitter'
}, {
xtype: 'button'
}],




/**
*
*/
initComponent: function()
{
var me = this;


me.initConfig();


me.callParent();
},




/**
* Gibt den Wert des Feldes zurück
*
* @returns {*}
*/
getValue: function()
{
return this.value;
},


/**
* Setzt den Wert des Feldes
*
* @param {*} value
* @param {String} [src]
*/
setValue: function(value, src)
{
this.value = value;


if (src) {
this.setSrc(src);
}
},




/**
* Setzt den Src des Bildes
*
* @param {String} src
*/
setSrc: function(src)
{
this.getImage().setSrc(src);
},




/**
* Gibt das Bild zurück
*
* @returns {Ext.Img}
*/
getImage: function()
{
return this.down('image');
},




/**
* Gibt den Button zurück
*
* @returns {Ext.button.Button}
*/
getButton: function()
{
return this.down('button')
},




/**
* Lädt die button und image Config
*/
initConfig: function()
{
Ext.apply(this.items[2], this.button);
Ext.apply(this.items[0], this.image);
},


getName: function()
{
return this.name;
},


isValid: function()
{
return true;
},


validate: function()
{
return this.isValid();
},


isFileUpload: function()
{
return false;
},


getSubmitValue: function()
{
var obj = {};


obj[this.getName()] = this.getValue();


return obj;
},


getSubmitData: function()
{
return this.getSubmitValue();
}
});


That's how I use it in a form:



fieldDefaults: {
labelAlign: 'top',
width: '99%',
labelStyle: 'font-weight: bold;'
},
items: [
{
xtype: 'imagepreview',
name: 'previewImage',
fieldLabel: 'Vorschau Bild',
button: {
text: 'Bild auswählen',
action: 'mediamanager-open'
},
image: {
maxHeight: 100,
maxWidth: 100
}
}
]


Maybe it helps you ^^

Jangla
25 Apr 2013, 1:20 AM
Thanks, I'm sure I'll crack it eventually :D

slemmon
26 Apr 2013, 8:06 AM
You might be able to save yourself some configuring as the extending of FieldContainer does a lot of the work for you (managing the field mixin, initializing the field, etc.).

See if this snippet helps at all:


Ext.define('MyContainer', {
extend: 'Ext.form.FieldContainer',
alias: 'widget.mycontainer',


initComponent: function () {
var me = this;


me.labelAlign = 'top';


Ext.apply( me, {
items : [{
xtype: 'textfield'
}, {
xtype: 'textfield'
}]
});


me.callParent(arguments);
}
});






Ext.widget('mycontainer', {
renderTo: Ext.getBody(),
fieldLabel: 'Label on Top'
});

Jangla
30 Apr 2013, 8:29 AM
You might be able to save yourself some configuring as the extending of FieldContainer does a lot of the work for you (managing the field mixin, initializing the field, etc.).


I'm already extending FieldContainer.

shadshacnego
7 Nov 2013, 10:18 AM
Did you ever figure this out? Just wondering, because I'm having the same problem. Thanks!