PDA

View Full Version : IconCombo



jamone
24 Apr 2011, 7:20 AM
Can anyone figure out how to port the iconCombo example to ext 4.x?

I have attempted it, and I am encountering too many errors.

Thanks in advance
Cheers

lukerahl
29 Apr 2011, 3:01 PM
The following seems to work just fine for me...


/**
* Ext.ux.IconCombo Extension Class for Ext 4.x Library
*
* @author Daniel Kuhnley
* @class Ext.ux.IconCombo
* @extends Ext.form.field.ComboBox
*/
Ext.define('Ext.ux.IconCombo',{
extend:'Ext.form.field.ComboBox',
alias:'widget.iconcombo',

initComponent:function() {

Ext.apply(this, {
listConfig: {
iconClsField:this.iconClsField,
getInnerTpl: function() {
return '<tpl for=".">'
+ '<div class="x-combo-list-item ux-icon-combo-item '
+ '{' +this.iconClsField+ '}">'
+ '{' + this.displayField + '}'
+ '</div></tpl>';
},
scope:this
},
scope:this
});

// call parent initComponent
this.callParent(arguments);

}, // end of function initComponent

onRender:function(ct, position) {
// call parent onRender
this.callParent(arguments);

// adjust styles
this.bodyEl.applyStyles({position:'relative'});
this.el.down('input.x-form-field').addCls('ux-icon-combo-input');

// add div for icon
this.icon = Ext.core.DomHelper.append(this.el.down('div.x-form-item-body'), {
tag: 'div', style:'position:absolute'
});
}, // end of function onRender

setIconCls:function() {
var rec = this.store.findRecord(this.valueField, this.getValue());
if(rec) {
this.icon.className = 'ux-icon-combo-icon '+rec.get(this.iconClsField);
}
}, // end of function setIconCls

setValue: function(value) {
this.callParent(arguments);
this.setIconCls();
} // end of function setValue
});
// end of file

With css:


<style type="text/css">
.ux-flag-us {
background-image:url(images/us.png) ! important;
}
.ux-flag-de {
background-image:url(images/de.png) ! important;
}
.ux-flag-fr {
background-image:url(images/fr.png) ! important;
}
.ux-icon-combo-icon {
background-repeat: no-repeat;
background-position: 0 50%;
width: 18px;
height: 14px;
}

/* X-BROWSER-WARNING: this is not being honored by Safari */
.ux-icon-combo-input {
padding-left: 25px;
}

.x-form-item-body .ux-icon-combo-icon {
top: 3px;
left: 5px;
}
.ux-icon-combo-item {
background-repeat: no-repeat ! important;
background-position: 3px 50% ! important;
padding-left: 24px ! important;
}
</style>


And example usage:


<script type="text/javascript">
Ext.require([
'Ext.window.Window'
]);

Ext.onReady(function() {
Ext.create('Ext.Window', {
title: 'Icon Combo Ext 4.0 Extension Class Example',
width: 400,
height: 60,
x: 10,
y: 200,
plain: true,
layout: 'fit',
items: {
xtype:'iconcombo',
fieldLabel:'IconCombo',
store: new Ext.data.SimpleStore({
fields: ['countryCode', 'countryName', 'countryFlag'],
data: [
['US', 'United States', 'ux-flag-us'],
['DE', 'Germany', 'ux-flag-de'],
['FR', 'France', 'ux-flag-fr']
]
}),
valueField: 'countryCode',
displayField: 'countryName',
iconClsField: 'countryFlag',
triggerAction: 'all',
mode: 'local'
}
}).show();
});
</script>

hschaefer123
6 May 2011, 1:12 AM
Hi Luke,
thankx for the nice migration.

One thing is missing. The originial plugin was always called after rendering (it was a plugin). Therefore if a combo ist instantiatedt hidden, setIconClass is called prior to render() -> error because no this.icon exists.

I modified the setIconClass a little bit to catch this trap:



setIconCls: function() {
if (this.rendered) {
var rec = this.store.findRecord(this.valueField, this.getValue());
if (rec) this.icon.className = 'ux-icon-combo-icon ' + rec.get(this.iconClsField);
} else {
this.on('render', this.setIconCls, this, { single: true } );
}
}, // end of function setIconCls


Now the IconCombo works also on components that are instantiated hidden.

Cheers
Holger

lukerahl
8 May 2011, 1:52 PM
@hschaefer123
Nice catch! Didn't think that one through all the way.

asif.kilwani
11 Oct 2011, 6:50 AM
Hi Guys, thanks for sharing code. I've used the code but receiving "namespace is undefined"

I've put Ext.define('Ext.ux.IconCombo',{... code in IconCombo.js under ux folder

From my application I'm calling

requires: [
'Ext.ux.IconCombo'
],

and the way to call combo

xtype:'IconCombo',
fieldLabel:'IconCombo',
store: new Ext.data.SimpleStore({
fields: ['countryCode', 'countryName', 'countryFlag'],
data: [
['US', 'United States', 'ux-flag-us'],
['DE', 'Germany', 'ux-flag-de'],
['FR', 'France', 'ux-flag-fr']
]
}),
valueField: 'countryCode',
displayField: 'countryName',
iconClsField: 'countryFlag',
triggerAction: 'all',
mode: 'local'

Not sure what line code is throwing "namespace is undefined"

skirtle
11 Oct 2011, 2:43 PM
@asif.kilwani. Try switching your xtype to lower case.

sumit.madan
10 Jan 2012, 1:32 PM
IconCombo extension for ExtJS 4.1 beta 1:


Ext.define('Ext.ux.form.IconCombo',{
extend:'Ext.form.field.ComboBox',
alias:'widget.iconcombo',

initComponent:function() {
Ext.apply(this, {
listConfig: {
iconClsField:this.iconClsField,
getInnerTpl: function() {
return '<tpl for=".">'
+ '<div class="x-combo-list-item ux-icon-combo-item '
+ '{' +this.iconClsField+ '}">'
+ '{' + this.displayField + '}'
+ '</div></tpl>';
}
},
fieldSubTpl: [
'<div class="{hiddenDataCls}" role="presentation"></div>',
'<div class="ux-icon-combo-wrap"><input id="{id}" type="{type}" {inputAttrTpl}',
'<tpl if="value"> value="{value}"</tpl>',
'<tpl if="name"> name="{name}"</tpl>',
'<tpl if="placeholder"> placeholder="{placeholder}"</tpl>',
'<tpl if="size"> size="{size}"</tpl>',
'<tpl if="maxLength !== undefined"> maxlength="{maxLength}"</tpl>',
'<tpl if="readOnly"> readonly="readonly"</tpl>',
'<tpl if="disabled"> disabled="disabled"</tpl>',
'<tpl if="tabIdx"> tabIndex="{tabIdx}"</tpl>',
'<tpl if="fieldStyle"> style="{fieldStyle}"</tpl>',
'class="{fieldCls} {typeCls}" autocomplete="off" /></div>',
{
compiled: true,
disableFormats: true
}
]
});

// call parent initComponent
this.callParent(arguments);

}, // end of function initComponent

onRender:function(ct, position) {
// call parent onRender
this.callParent(arguments);

// adjust styles
this.el.down('div[class=ux-icon-combo-wrap]').applyStyles({position:'relative'});
this.el.down('input').addCls('ux-icon-combo-input');

// add div for icon
this.icon = Ext.core.DomHelper.append(this.el.down('div[class=ux-icon-combo-wrap]'), {
tag: 'div', style:'position:absolute'
})
}, // end of function onRender

setIconCls: function() {
if (this.rendered) {
var rec = this.store.findRecord(this.valueField, this.getValue());
if (rec) this.icon.className = 'ux-icon-combo-icon ' + rec.get(this.iconClsField);
} else {
this.on('render', this.setIconCls, this, { single: true } );
}
}, // end of function setIconCls

setValue: function(value) {
this.callParent(arguments);
this.setIconCls();
} // end of function setValue
});

rlovelett
9 Jul 2012, 11:48 AM
Made a gist of these. If anyone wants one.

https://gist.github.com/3078460

hschaefer123
20 Jul 2012, 3:36 AM
Currently investigating some time to move my ext 3.x to 4.1.x.

I have rewriten the extension to be more compatibel for further updates (hopefully) using standard templates and renderSelectors.

Screenshot:
037657

Update: 2012/08/01



/**
* Ext.ux.form.field.IconCombo Extension Class for Ext 4.1.x Library
*
* @author Holger Schäfer
* @class Ext.ux.IconCombo
* @extends Ext.form.field.ComboBox
*
* depends on IconLoader
* Forum: http://www.sencha.com/forum/showthread.php?234135-Ext.ux.IconLoader
*
* Usage:
* {
* xtype: 'iconcombo',
* valueField: 'field1',
* displayField: 'field2',
* iconClsField: 'field3',
* queryMode: 'local',
* store: [['de', 'Deutsch', 'flags-de'], ['en','Englisch','flags-gb']]
* }
*/

Ext.define('Ext.ux.form.field.IconCombo', {
extend: 'Ext.form.field.ComboBox',
alias: 'widget.iconcombo',

// sof IconLoader (comment this if not using IconLoader and load icons inside css)
uses: [ 'Ext.ux.IconLoader' ],
requireIcons: ['flags/de', 'flags/gb'],
// eof IconLoader

initComponent: function() {
var me = this;

// add container at the end of default template
var iconFieldSubTpl = Ext.clone(me.fieldSubTpl);
iconFieldSubTpl.push(
'<div class="ux-icon-combo-icon"></div>'
);

Ext.apply(me, {
scope: me,
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="x-boundlist-item ux-icon-combo-item {' + me.iconClsField + '}">',
'{' + me.displayField + '}',
'</div>',
'</tpl>',
{ compiled: true, disableFormats: true }
),
// add wrapping DIV container around TDs because position:relative is not defined on TD
beforeSubTpl: '<div class="ux-icon-combo-wrap">',
fieldSubTpl: iconFieldSubTpl,
afterSubTpl: '</div>',
renderSelectors: {
iconClsEl: '.ux-icon-combo-icon'
}
});

me.callParent(arguments);
},

setIconCls: function() {
if (this.rendered) {
var rec = this.store.findRecord(this.valueField, this.getValue());
if (rec) {
var newIconCls = rec.get(this.iconClsField);
this.iconClsEl.replaceCls(this.oldIconCls, newIconCls);
this.oldIconCls = newIconCls;
}
} else {
this.on('render', this.setIconCls, this, {
single: true
});
}
},

setValue: function(value) {
this.callParent(arguments);
this.setIconCls();
}
});


and the corresponding CSS



.ux-icon-combo-wrap {
position: relative;
}

.ux-icon-combo-wrap .x-form-field {
padding-left: 25px;
}

.ux-icon-combo-icon {
position: absolute;
top: 4px;
left: 5px;
background-repeat: no-repeat;
background-position: 0 50%;
width: 18px;
height: 14px;
}

/*
.ux-icon-combo-icononly {
color: transparent;
}


.ux-icon-combo-icononly .ux-icon-combo-input {
padding-left: 1px;
color: transparent;
}
*/

/* combo selection list */
.ux-icon-combo-item {
padding-left: 24px;
background-repeat: no-repeat;
background-position: 3px 50%;
}

/* SUPPORTED FLAGS (uncomment this if not using iconLoader) */
/*
.flags-de { background-image: url(/icons/flags/de.png); }
.flags-gb { background-image: url(/icons/flags/gb.png); }
*/


Maybe someone likes the update.

Cheers Holger

iNes14
21 Sep 2012, 12:02 AM
Hello!

Thanks for the update, I'll try today...

Just a remark : I guess, if you're using XTemplate, you didn't have to add "compiled:true" : http://docs.sencha.com/ext-js/4-1/#!/api/Ext.XTemplate-cfg-compiled

dekely
24 Sep 2012, 10:27 AM
How do I use IcojnCombo with dynamic image url?
I get a list of urls of images from server, how can I populate combobox with it?

Dekel

FanOfExt
20 Jan 2013, 5:39 AM
I'd like to know as well. I tried http://www.sencha.com/forum/showthread.php?136623-ComboBox-with-Images-in-ExtJS-4, but my icons never show up, just the broken image symbol appears!

adwebtiser
4 Apr 2013, 3:14 AM
Hi there,

I am using 4.2.0 but I have not been able to get this working, it keeps coming with the TypeError: el is null.

Is there any chance of checking this with 4.2?

Thank you.

hschaefer123
4 Apr 2013, 3:23 AM
Have a look into the examples!
\examples\calendar\src\form\field\CalenderCombo.js
is basically an icon combo.

For next project i will use this as a base for IconCombo.

Cheers Holger

adwebtiser
4 Apr 2013, 3:49 AM
Thank you very much for the fast reply.

Sorry for my ignorance. I am really new to Ext JS any pointers as to why I would get a TypeError? Like what would usually be the cause, so I can look into that section of Calendar js file and compare.

It looks like for 4.1.1 it got the same error but it got fixed by just changing the top define name from Ext.ux.IconCombo to Ext.ux.form.field.IconCombo but this doesn't change anything for 4.2, I assume this is more than just changing one line of code. but if you could point me in the right direction I would really appreciate it.

Thanks

hschaefer123
4 Apr 2013, 4:44 AM
The component "Ext.calendar.form.field.CalendarCombo" is something like a special IconCombo version references app specific details. Copy the class into your own ux component starting by replacing Ext.calendar.form.field.CalendarCombo through Ext.form.field.IconCombo.

Remove redundant refs to "Ext.calendar.data.CalendarMappings"

Currently the class holds color names as icon to show state of surrounding form.

Change icon classes to matching icon classes from origin icon.combo.

This is maybe not quitre simple for an ext js newbie, but maybe this hints can help you.

Cheers Holger

adwebtiser
15 Apr 2013, 6:59 AM
Hi again,

I know it took me a while but I did what you suggested and managed to get it working partly. But I am having problem with what is returned to the setValue function inside my iconcombo class.

Here is my version of iconcombo:


/**
* Ext.ux.IconCombo Extension Class for Ext 4.x Library
*
* @author Daniel Kuhnley
* @class Ext.ux.IconCombo
* @extends Ext.form.field.ComboBox
*/
Ext.define('Ext.ux.IconCombo',{
extend:'Ext.form.field.ComboBox',
alias:'widget.iconcombo',

fieldLabel: 'Language',
triggerAction: 'all',
queryMode: 'local',
forceSelection: true,
//selectOnFocus: true,

// private
defaultCls: 'ux-icon-combo-icon ',

initComponent:function() {

this.listConfig = Ext.apply(this.listConfig || {}, {
iconClsField: this.iconClsField,
defaultCls: this.getStyleClass(this.value),
getInnerTpl: this.getListItemTpl
});

// call parent initComponent
this.callParent(arguments);

}, // end of function initComponent

// private
getListItemTpl: function(displayField) {
return '<tpl for=".">'
+ '<div class="x-combo-list-item ux-icon-combo-item '
+ '{' +this.iconClsField+ '}">'
+ '{' + this.displayField + '}'
+ '</div></tpl>';
},

afterRender:function() {
console.log("into afterRender");
// call parent onRender
this.callParent(arguments);

this.bodyEl.applyStyles({position:'relative'});
this.wrap = this.el.down('.x-form-item-body');
this.el.down('input.x-form-field').addCls('ux-icon-combo-input');

this.icon = Ext.core.DomHelper.append(this.wrap, {
tag: 'div', cls:'ux-icon-combo-icon'
});
}, // end of function afterRender

getStyleClass: function(value){
console.log("into getStyleClass: "+value);
var rec = this.store.findRecord(this.valueField, value);
if (rec){
console.log("returning: ux-icon-combo-icon "+rec.get(this.iconClsField));
return 'ux-icon-combo-icon ' + rec.get(this.iconClsField);
}
return '';
},

setValue: function(value) {
console.log(value);
if(value instanceof Object){
console.log(value.getData());
}
if (this.wrap && value) {
console.log("this.getValue()"+this.getValue());
var currentClass = this.getStyleClass(this.getValue()),
newClass = this.getStyleClass(value);

this.wrap.replaceCls(currentClass, newClass);
}

this.callParent(arguments);
} // end of function setValue
});


My problem is that it returns the value as an Ext.data.Record object with my array inside it as data property, but it does not let my code to get the data array out of it, even though I try any of the methods inside the object, it keeps saying so and so function (value.getData()) is not a function, any idea on how I can get my data out of this object?

Thanks

Scorpie
29 May 2013, 5:13 AM
Hi there,

I am using 4.2.0 but I have not been able to get this working, it keeps coming with the TypeError: el is null.

Is there any chance of checking this with 4.2?

Thank you.

Try this version:




/**
* Ext.ux.IconCombo Extension Class for Ext 4.1 Library
*
* @author Daniel Kuhnley
* @class Ext.ux.IconCombo
* @extends Ext.form.field.ComboBox
*
*
* FIX BECAUSE WE HAD 4.0.7 FIRST, SEE http://www.sencha.com/forum/showthread.php?154499-v1.1-11-15-2011-Ext.ux.LoginDialog-LoginDialog-Extension&p=893481&viewfull=1#post893481
*
*/
Ext.define('Ext.ux.form.IconCombo',{
extend:'Ext.form.field.ComboBox',
alias:'widget.iconcombo',

initComponent:function() {

Ext.apply(this, {
scope:this,
listConfig: {
scope:this,
iconClsField:this.iconClsField,
getInnerTpl: function() {
return '<tpl for=".">' +
'<div class="x-combo-list-item ux-icon-combo-item ' +
'{' +this.iconClsField+ '}">' +
'{' + this.displayField + '}' +
'</div></tpl>';
}
},
fieldSubTpl: [
'<div class="{hiddenDataCls}" role="presentation"></div>',
'<div class="ux-icon-combo-wrap"><input id="{id}" type="{type}" {inputAttrTpl}',
'<tpl if="value"> value="{value}"</tpl>',
'<tpl if="name"> name="{name}"</tpl>',
'<tpl if="placeholder"> placeholder="{placeholder}"</tpl>',
'<tpl if="size"> size="{size}"</tpl>',
'<tpl if="maxLength !== undefined"> maxlength="{maxLength}"</tpl>',
'<tpl if="readOnly"> readonly="readonly"</tpl>',
'<tpl if="disabled"> disabled="disabled"</tpl>',
'<tpl if="tabIdx"> tabIndex="{tabIdx}"</tpl>',
'<tpl if="fieldStyle"> style="{fieldStyle}"</tpl>',
'class="{fieldCls} {typeCls}" autocomplete="off" /></div>',
{
compiled: true,
disableFormats: true
}]
});

// call parent initComponent
this.callParent(arguments);

}, // end of function initComponent

onRender:function(ct, position) {
// call parent onRender
this.callParent(arguments);

// adjust styles
this.el.down('div[class=ux-icon-combo-wrap]').applyStyles({
position: 'relative'
});
this.el.down('input').addCls('ux-icon-combo-input');

// add div for icon
this.icon = Ext.core.DomHelper.append(this.el.down('div[class=ux-icon-combo-wrap]'), {
tag: 'div',
style:'position:absolute'
});
}, // end of function onRender

setIconCls: function() {
if (this.rendered) {
var rec = this.store.findRecord(this.valueField, this.getValue());
if (rec) {
this.icon.className = 'ux-icon-combo-icon ' + rec.get(this.iconClsField);
}
} else {
this.on('render', this.setIconCls, this, {
single: true
} );
}
}, // end of function setIconCls

setValue: function(value) {
this.callParent(arguments);
this.setIconCls();
} // end of function setValue
});