ExtJS5: Checkbox afterSubTpl wraps icons - javascript

The snippet below will not run on this site, but you can access a working demo here on JSFiddle.
I am trying to get the icon to appear to the right of the checkbox, but it appears to be wrapping. Is there a property that I need to set so that it will appear in-line? This worked in ExtJS4, but after I switched to ExtJS5 this does not work.
afterSubTpl Documentation
Ext.form.field.Checkbox -> config -> afterSubTpl
An optional string or XTemplate configuration to insert in the field markup after the subTpl markup. If an XTemplate is used, the component's render data serves as the context.
Code
Ext.require(['*']);
Ext.define('App.view.MainView', {
extend: 'Ext.panel.Panel',
xtype: 'mainView',
alias: 'widget.mainview',
title: 'Checkbox Template Example',
referenceHolder: true,
layout: {
type: 'border'
},
initComponent: function () {
var me = this,
tooltip = me.getHelpIconWithTooltip();
me.items = [{
region: 'center',
xtype: 'panel',
title : 'A Panel Title',
margin : 20,
bodyStyle: 'padding: 8px;',
layout : 'vbox',
items : [{
xtype: 'checkbox',
fieldLabel : 'Checkbox',
afterSubTpl: tooltip
}]
}],
me.callParent();
},
getHelpIconWithTooltip: function () {
return this.getFormIconWithTooltip('help-icon help-form-icon',
'This is a help tooltip...');
},
getFormIconWithTooltip: function (iconClassList, toolTipText) {
var getSpan = function(cl, qt) {
return '<span class="'+cl+'" data-qtip="'+qt+'"></span>';
}
return [
'<tpl>',
getSpan(iconClassList, toolTipText),
'</tpl>'
];
}
});
Ext.define('App.app.App', {
extend: 'Ext.app.Application',
name: 'App',
launch: function () {
Ext.create('Ext.Viewport', {
layout: 'fit',
flex: 1,
items: [{
xtype: 'mainview'
}]
});
}
});
Ext.onReady(function () {
Ext.application('App.app.App');
});
.help-icon {
display: inline-block;
background: url(http://www.famfamfam.com/lab/icons/silk/previews/index_abc.png) -705px -1125px no-repeat;
width: 16px;
height: 16px;
}
.help-form-icon {
/*margin-left: 5px;*/
}
<link href="https://extjs.cachefly.net/ext/gpl/5.1.0/packages/ext-theme-crisp/build/resources/ext-theme-crisp-all-debug.css" rel="stylesheet" />
<script src="http://cdn.sencha.com/ext/gpl/5.1.0/build/ext-all.js"></script>
Edit
It looks like if I add a class to the checkbox, I can prevent it from wrapping, but now the icon is positioned too high.
{
xtype: 'checkbox',
fieldLabel: 'Checkbox',
afterSubTpl: tooltip,
cls: 'no-wrap-tooltip'
}
.no-wrap-tooltip .x-form-cb-wrap-inner {
display: inline-block;
}

I may have figured it out, but this solution uses magic numbers which make it work in this instance.
Demo
{
xtype: 'checkbox',
fieldLabel: 'Checkbox',
afterSubTpl: tooltip,
cls: 'no-wrap-tooltip'
}
.no-wrap-tooltip .x-form-cb-wrap-inner {
display: inline-block;
line-height: 28px;
}

Related

Ext JS header placement order

I want to have a button in panel header. This is a part of my code:
var dashboardPanel4 = Ext.create('Ext.Panel', {
renderTo: Ext.getBody(),
margin: '0 0 50 0',
glyph: 'xf2a0#FontAwesome',
layout: {
type: 'table',
columns: 4,
tableAttrs: {
width: '100%'
}
},
defaults: {
// applied to each contained panel
bodyStyle: 'padding:10px',
border: 0
},
title: '<span class="requests" id="requests">Requests</span>',
header: {
xtype: 'header',
titlePosition: 0,
defaults: {
margin: '0 10px'
},
items: [
{
xtype: 'button',
text: "Test Button",
tooltip: "Add something",
iconCls: 'add',
handler: Ext.bind(function() {
}, this)
}
]
},
But the problem is that fontawesome icon aligns into right position. Is there a way how to set FA icon before this title 'Requests'.
At the moment it is like this:
It should be: FA icon, Request and Button on right side.
You want to have in the header the things align like this:
<icon> <title> <other things>
I would do it with the config titlePosition: 1, which sets the title as a second item. Next thing what is needed is to just add the icon not by using glyph config but rather add it as own item in the header config.
So you would get something like this:
header: {
xtype: 'header',
titlePosition: 1,
items: [{
xtype: 'image',
glyph: 'xf2a0#FontAwesome',
}, {
xtype: 'button',
text: "Test Button",
tooltip: "Add something",
iconCls: 'add',
handler: Ext.bind(function () {}, this)
}]
},
Here is fiddle https://fiddle.sencha.com/#view/editor&fiddle/2h99 (the font awesome icons are not loaded in the example) but it should work in your own code.
Btw there might be more solutions to this problem.

Add buttons in ExtJS menu item

Is it possible to add buttons inside a menuitem using ExtJS 4.2?
I need to achieve the following:
(To have an edit and delete buttons next to the checkbox of each menuitem. These will have their own handlers and will open new panels when clicking on them)
I've tried to achieve it by creating a container per each employee and inside it add the buttons needed plus the menuitem but it's not working properly since I can't click the custom menuitem anymore after doing it and the design didn't look good at all.
However, I found a possible "hint" in the following StackOverflow answer:
https://stackoverflow.com/a/11213707/1178686
(But this is not entirely what I expect since I don't need just an icon, I need a button with its own handler plus I don't know if interacting with the DOM is a good approach for this)
Here's what I got so far and where I'm doing my tests:
Live demo:
http://jsfiddle.net/oscarj24/hmqjqtqs/
ExtJS code:
Ext.define('Namespace.view.Panel', {
extend: 'Ext.panel.Panel',
title: 'Panel',
frame: true,
floating: true,
draggable: true,
resizable: false,
closable: true,
employees: null,
layout: {
type: 'vbox',
align: 'stretch'
},
constructor: function(cfg) {
Ext.apply(this, cfg || {});
this.items = [{
xtype: 'container',
border: false,
items: this.createItems()
}];
this.callParent(arguments);
},
createItems: function() {
var items = [];
items.push({
xtype: 'button',
text: 'Employees',
menu: {
xtype: 'menu',
items: this.createMenuItems()
}
});
return items;
},
createMenuItems: function() {
var employees = this.employees || [],
items = [];
for (var i = 0; i < employees.length; ++i) {
var employee = employees[i];
if (employee) {
items.push({
xtype: 'menucheckitem',
text: Ext.String.format('{0} {1}', employee.name, employee.lastname),
employeeId: employee.id,
listeners: {
scope: this,
checkchange: this.onMenuItemCheckChange
}
});
}
}
items.push({
xtype: 'menuitem',
iconCls: 'add',
text: 'Add'
});
return items;
},
onMenuItemCheckChange: function(item, checked, eOpts) {
console.log('Employee Id: %o was checked: %o', item.employeeId, checked);
},
destroy: function() {
delete this.employees;
this.callParent(arguments);
}
});
Ext.onReady(function() {
Ext.create('Namespace.view.Panel', {
employees: [
{id: 1, name: 'Oscar', lastname: 'Jara'},
{id: 2, name: 'Foo', lastname: 'Bar'}
]
}).show();
});
CSS:
.add {
background-image: url('http://icons.iconarchive.com/icons/awicons/vista-artistic/16/add-icon.png') !important; width: 16px; height: 16px; display: block;
}
.edit {
background-image: url('http://icons.iconarchive.com/icons/designcontest/outline/16/Pencil-icon.png') !important; width: 16px; height: 16px; display: block;
}
.delete {
background-image: url('http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-edit-delete-icon.png') !important; width: 16px; height: 16px; display: block;
}
If someone knows a "proper" way to achieve this please let me know since I am not sure if one of the configs specified in the API for this component could help and I wasn't able to find a good example on the internet:
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.menu.CheckItem
Thanks in advance.
I would probably go the route of using a container and just trying to make that work. I realize the styling might not be a nice as what the framework provides, but with enough fine-tuning, you could get it there... just make use of Sencha CMD, scss files, and their pre-defined CSS vars.
In this example, I do a quick unstyling of the buttons, so they can be clickable icons/areas, and I throw the employee record on the button itself... not really the best approach, but it works. If you don't like listeners on each individual component like that, you could make the parent container have the listener, and in that function you would check the target's CSS class... but that's besides the point. Working example:
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.define('MyPanel', {
extend: 'Ext.panel.Panel',
title: 'My Panel',
renderTo: Ext.getBody(),
employees: [{
id: 1,
name: 'Oscar',
lastname: 'Jara'
}, {
id: 2,
name: 'Foo',
lastname: 'Bar'
}],
initComponent: function() {
this.createMenuItems();
this.callParent();
},
createMenuItems: function() {
var items = [];
var employees = this.employees;
if (employees) {
for (var i = 0; i < employees.length; i++) {
var employee = employees[i];
var containerItems = [];
var checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
width: 20
});
containerItems.push(checkboxCmp);
containerItems.push({
xtype: 'button',
cls: 'my-custom-button',
employee: employee,
width: 22,
text: '',
iconCls: 'edit',
listeners: {
click: this.onClickEditButton
}
});
containerItems.push({
xtype: 'button',
cls: 'my-custom-button',
employee: employee,
width: 22,
text: '',
iconCls: 'delete',
listeners: {
click: this.onClickDeleteButton
}
});
containerItems.push({
xtype: 'component',
html: '<div style="border-left:1px solid #000;height:100%; display: inline-block;"></div>'
});
containerItems.push({
xtype: 'button',
cls: 'my-custom-button',
textAlign: 'left',
checkboxCmp: checkboxCmp,
employee: employee,
flex: 1,
text: employee.name + ' ' + employee.lastname,
listeners: {
click: this.onClickEmployee
}
});
items.push({
xtype: 'container',
layout: {
type: 'hbox',
align: 'stretch'
},
overCls: 'over-item-cls',
items: containerItems
});
}
}
this.tools = [{
xtype: 'button',
text: 'Employees',
menu: {
xtype: 'menu',
items: items,
plain: true
}
}];
},
onClickDeleteButton: function(button, event, eOpts) {
alert('clicked delete, check console for employee');
console.log('delete', button.employee);
},
onClickEditButton: function(button, event, eOpts) {
alert('clicked edit, check console for employee');
console.log('edit', button.employee);
},
onClickEmployee: function(button, event, eOpts) {
alert('employee checkbox changed, check console for employee');
console.log('employee', button.employee);
var checkboxCmp = button.checkboxCmp;
if (checkboxCmp) {
checkboxCmp.setValue(!checkboxCmp.getValue());
}
}
});
Ext.create('MyPanel');
}
});
CSS
.add {
background-image: url('http://icons.iconarchive.com/icons/awicons/vista-artistic/16/add-icon.png') !important; width: 16px; height: 16px; display: block;
}
.edit {
opacity: 0.4;
background-image: url('http://icons.iconarchive.com/icons/designcontest/outline/16/Pencil-icon.png') !important; width: 16px; height: 16px; display: block;
}
.edit:hover,
.delete:hover {
opacity: 1.0;
}
.delete {
opacity: 0.4;
background-image: url('http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-edit-delete-icon.png') !important; width: 16px; height: 16px; display: block;
}
.over-item-cls {
background-color: lightblue;
}
a.my-custom-button.x-btn-default-small {
background: none;
border: none;
}
a.my-custom-button.x-btn-default-small span {
color: #ababab;
}
a.my-custom-button.x-btn-default-small:hover span {
color: black;
}
I am not sure you are insterested in using tpl in menu items: If you are, I can improve this code below. And Fiddle: https://fiddle.sencha.com/#fiddle/tt3
Ext.define('Image', {
extend: 'Ext.data.Model',
fields: [
{ name:'buttonText1', type:'string' },
{ name:'buttonText2', type:'string' },
{ name:'menuText', type:'string' }
]
});
Ext.create('Ext.data.Store', {
id:'imagesStore',
model: 'Image',
data: [
{ buttonText1:'edit', buttonText2: 'add', menuText:'Drawing', id: '1' },
{ buttonText1:'edit', buttonText2: 'add', menuText:'Advanced', id: '2' },
]
});
var imageTpl = new Ext.XTemplate(
'<tpl for="."><table>',
'<div class="menu-row">',
'<input type="checkbox" id="check{id}">',
'<button class="{buttonText1}">{buttonText1}</button>',
'<button class="{buttonText2}" >{buttonText2}</button> {menuText}',
'</div>',
'<table></tpl>'
);
var dataview = Ext.create('Ext.view.View', {
itemId: 'idDataView',
store: Ext.data.StoreManager.lookup('imagesStore'),
tpl: imageTpl,
itemSelector: 'div.menu-row',
listeners: {
itemclick: function(dataview, record,items) {
Ext.each(items.children, function(item) {
if (item.id == 'check'+ record.get('id')) {
item.checked == false ? item.checked = true : item.checked = false;
}
});
}
}
});
var button = Ext.create('Ext.button.Split', {
text: 'menuButton',
margin: '100 100 100 100',
menu: {
//plain: true,
items: [dataview],
listeners: {
afterrender: function(menu) {
var task = new Ext.util.DelayedTask(function(){
Ext.each(menu.down('#idDataView').getEl().dom.children, function(nodes) {
Ext.each(nodes.children, function(node) {
if (node.className == 'edit') {
node.addEventListener('click', function() {
alert('edited');
});
} else if (node.className == 'add') {
node.addEventListener('click', function() {
alert('added');
});
}
})
});
});
task.delay(100);
}
},
},
renderTo: Ext.getBody()
});

How to align header items to the right in ExtJs

This is my header with it's items; as you can see I tried adding a style property but it doesn't help - the link is still aligned to the left whereas I want it to align right:
items: [
{
region: 'north',
xtype: 'header',
items:[
{
xtype: 'component',
autoEl: {
html: 'View All Services'
},
style: {
textAlign: 'right',
left: 'auto',
right: '0'
},
listeners: {
render: function(component) {
component.getEl().on('click', function(e) {
alert('test');
});
}
}
}
],
padding: 6
}
How can I align my items to the right in my header?
Set header titlePosition configuration property to 0. By default items in header component are added before header title. If you set titlePosition config to 0, items will be added after title:
items: [
{
region: 'north',
xtype: 'header',
titlePosition: 0,
items:[
{
xtype: 'component',
autoEl: {
html: 'View All Services'
},
listeners: {
render: function(component) {
component.getEl().on('click', function(e) {
alert('test');
});
}
}
}
],
padding: 6
}

Extjs fill fields inside a tabpanel with config variables

I am trying to populate a tabpanel with an extension I've created. Inside this extension i have a panel with 2 fields (timefield and datefield) which may have the values from my store.
Each of these fields may have different values in each tab. I am passing these values from the extended component via config. So far I can see these values in the console.log() but I can't put these values inside the fields.
This is how my extended component is:
Ext.define('PlaylistGrid', {
extend: 'Ext.panel.Panel',
alias: 'widget.playlistgrid',
border: false,
config: {
plIndex: 0,
plDate: '1970-10-10',
plTime: '00:00:00'
},
constructor: function(cfg) {
Ext.apply(this, cfg);
this.callParent(arguments);
},
items: [{
layout: 'hbox',
bodyStyle: 'padding: 5px',
border: false,
xtype: 'form',
name: 'myForm',
items: [{
xtype: 'datefield',
fieldLabel: 'Data de início',
name: 'datefld',
itemId: 'datefld'
}, {
xtype: 'timefield',
fieldLabel: 'Horário de início',
name: 'timefld'
}, {
xtype: 'button',
iconCls: 'save',
style: 'margin-left: 10px',
tooltip: 'Salvar data e hora',
handler: function() {
Ext.Msg.alert('Salvando...', 'Implementar');
}
}]
}, {
xtype: 'grid',
border: false,
width: '100%',
height: 476,
columns: [{
header: 'Ordem',
dataIndex: 'order',
width: 50
}, {
header: 'Video',
dataIndex: 'video',
width: 308
}, {
header: 'Duracao',
dataIndex: 'duration',
width: 100
}, {
header: 'Formato',
dataIndex: 'format',
width: 75
}]
}],
listeners: {
render: function(e, eOpts) {
console.log(e.getPlDate());
}
}
});
And this is how I am adding this component inside the tabpanel:
var plSt = Ext.getStore('playlistStore');
plSt.load();
plSt.on('load', function(store, records, successful, eOpts) {
plSt.each(function(record, idx) {
var playlist = {
xtype: 'playlistgrid',
title: 'Playlist ' + (records[idx].data.playlistId),
name: 'playlist' + idx,
plIndex: records[idx].data.playlistId,
plDate: records[idx].data.playlistDate,
plTime: records[idx].data.playlistTime
};
e.add(playlist);
});
if (records.length > 0) {
e.setActiveTab(1);
}
})
The data seems to be ok, but it does not display in the datefield... Do you have any point about it?
I have already search how to do this, but couldn't find the answer at all.
SOLVED
OK, I got it. The solution was simple. I just added a new config var that passes the current tab index, and the afterRender method.
I did this
afterRender: function(e, eOpts) {
var idx = e.getTabIdx();
var dateFld = Ext.ComponentQuery.query('datefield[name=datefld]');
dateFld[idx].setValue(new Date(e.getPlDate()));
//console.log(e.getPlDate());
}
Thank you!

is it possible to implement moveable Toolbar with Ext.js, if yes, how to do that with my code?

it is my toolbar which i want to move free in any position of my desktop.
what i need to change for it? maybe xtype'toolbar' or different extend'Ext.panel.Panel'??
Ext.define('test.view.desktop.Toolbar', {
bodyStyle: "background: #CAE1FF; border: 4px solid red;",
width: 500,
height: 200,
extend: 'Ext.panel.Panel',
title: 'test',
alias: "widget.testtoolbarX",
requires: [
"Ext.form.FieldSet"
],
dockedItems: [
{
xtype: 'toolbar',
dock: 'top',
items: [
{
xtype: 'tbtext',
text: '<b style="font-size: 20px; margin-left: 300px; color: red;">I am Toolbar</b>',
},
{
xtype: 'tbfill',
},
{
text: 'Report',
menu: {
items: [
{
text: 'Export'
,
menu: {
items: [
{
text: 'PDF'
}, {
text: 'Excel'
}
, {
text: 'CSV'
}
]
}
}, {
text: 'Filter'
}
]
}
},
{
xtype: 'cycle',
text: 'File',
menu: {
xtype: 'menu',
width: 120,
items: [
{
text: 'Upload'
},
{
text: 'Share'
},
{
text: 'Popout'
}
]
}
},
{
xtype: 'button',
text: 'Help',
url: 'http://test/faq.html',
//baseParams: {
// q: 'html+anchor+tag'
//},
tooltip: 'Get the answers to frequently asked questions about'
}
,
//{
// xtype: 'htmleditor',
// text: 'Help'
//}
]
}
]
});
Create a window with a fixed width and add a toolbar to it.
Kyle Fransham pointed this out but I'll show it with a code snippet:
Ext.create('Ext.window.Window', {
layout: 'fit',
width : 500,
dockedItems: {
xtype: 'toolbar',
items: [{
text: 'Button'
},
'->',
{
xtype : 'textfield',
name : 'field1',
emptyText: 'enter search term'
},
'-','text 1',
{ xtype: 'tbspacer' },
'text 2'
]
}
}).show();
An easy way to accomplish this is to:
Add the toolbar to a panel, and the panel to a window.
Play with the size of the window so that only the toolbar can be seen.
In the window's config, add headerPosition: 'right' to move the titlebar/header off to the right of the window.
Now you have a toolbar that can be dragged anywhere on your desktop by the handle on the right (the titlebar of the window.)

Categories