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!
Related
I am using ExtJS version 5.1.0.
Problem: I have a Ext.panel.Panel in my view. In this panel's beforeRender, I am trying to add an xtype:'form' whose items contain a tabpanel with multiple tabs.
When I switch the tab after some seconds of waiting on other tab, I get this exception
Uncaught TypeError: cannot read property 'parentNode' of null
And as a result of this, entire view of the switched tab is lost(its blank).
I have been trying this for a time now, but unable to find a solution.
Any suggestions on this would be a great help.
Here is my code snippet:
Ext.define({
'myClass',
extend: 'Ext.panel.Panel',
layout: 'fit',
viewModel: {
type: 'abc'
},
beforeRender: function() {
var me = this;
me.add({
xtype: 'form',
trackResetOnLoad: 'true',
layout: {
type: 'vbox',
align: 'stretch'
},
items: [
me.getContainer()
]
});
},
getContainer: function() {
var me = this;
var tabpanel = Ext.create({
'Ext.TabPanel',
allowDestroy: false,
reference: 'abc', //being used in application somewhere
layout: 'fit',
border: 0,
activeTab: 0,
items: [{
xtype: 'container',
bind: {
data: {
abcd
}
},
title: 'tab1',
layout: 'fit',
items: [
me.createContainer1() // contains form fields
]
},
{
xtype: 'container',
title: 'tab2',
layout: 'fit',
bind: {
data: {
abcf
}
},
items: [
me.createContainer2() // contains form fields
]
}
]
});
}
});
This is not a duplicate, it is a issue related to tabpanel and not simple HTML. It uses framework related knowledge. If anyone has idea about this, then please explain.
Firstly you need to use beforerender event instead of beforeRender and beforerender will be inside of listeners.
And also you can return directly xtype instead of creating like below example
createField: function() {
return [{
xtype: 'textfield',
emptyText: 'Enter the value',
fieldLabel: 'Test'
}];//You here return Object or Array of items
}
In this FIDDLE, I have created a demo using your code and make some modification. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
//Define the viewmodel
Ext.define('ABC', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.abc',
data: {
tab1: 'Tab 1',
tab2: 'Tab 2',
tab3: 'Tab 3',
tab4: 'Tab 4',
title: 'Basic Example'
}
});
//Define the panel
Ext.define('MyPanel', {
extend: 'Ext.panel.Panel',
xtype: 'mypanel',
layout: 'fit',
//This function will return field items for container or panel
createContainer: function (fieldLabel) {
return {
xtype: 'textfield',
emptyText: 'Enter the value',
fieldLabel: fieldLabel
};
},
//This function will return tabpanel for form items.
getContainer: function () {
var me = this;
return {
xtype: 'tabpanel',
allowDestroy: false,
//reference: 'abc', //being used in application somewhere
layout: 'fit',
border: 0,
activeTab: 0,
items: [{
bind: '{tab1}',
bodyPadding: 10,
layout: 'fit',
items: me.createContainer('Tab1 field') // contains form fields
}, {
bind: '{tab2}',
bodyPadding: 10,
layout: 'fit',
items: me.createContainer('Tab2 field') // contains form fields
}, {
bind: '{tab3}',
bodyPadding: 10,
layout: 'fit',
items: me.createContainer('Tab3 field') // contains form fields
}, {
bind: '{tab4}',
bodyPadding: 10,
layout: 'fit',
items: me.createContainer('Tab4 field') // contains form fields
}]
};
},
listeners: {
beforerender: function (cmp) {
var me = this;
//Add form inside of panel
me.add({
xtype: 'form',
trackResetOnLoad: true,
layout: {
type: 'vbox',
align: 'stretch'
},
items: me.getContainer()
});
}
}
});
//Create the mypanel
Ext.create({
xtype: 'mypanel',
viewModel: {
type: 'abc'
},
bind: '{title}',
renderTo: Ext.getBody()
});
}
});
I have a grid with drag'n'drop and row editing plugins. It worked fined when it was an outer class. However, since I striped the grid from having a class and put as an inner component, it started giving me errors. If I comment out code concerning plugins, it works fine.
Ext.define('Dashboards.view.widgets.barChartAndLine.BarChartAndLineWidgetForm', {
extend: 'Dashboards.view.widgets.WidgetBaseForm',
xtype: 'barChartAndLineWidgetForm',
items : [{
xtype: 'grid',
rowEditing: null,
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop'
}
},
listeners: {
drop: function() {
this.updateData();
}
},
initComponent: function() {
var me = this;
this.rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
edit: function() {
me.updateData();
}
}
});
this.plugins = [this.rowEditing];
this.callParent(arguments);
},
store: {
fields : ['label', 'linevalue', 'barvalue'],
bind : {
data : '{widget.data.data.items}'
}
},
columns: [{
header: 'Pavadinimas',
dataIndex: 'label',
flex: 3,
editor: {
allowBlank: false
}
}, {
xtype: 'numbercolumn',
header: 'Stulpelio reikšmė',
dataIndex: 'barvalue',
flex: 1,
editor: {
xtype: 'numberfield',
allowBlank: false
}
}, {
xtype: 'numbercolumn',
header: 'Linijos reikšmė',
dataIndex: 'linevalue',
flex: 1,
editor: {
xtype: 'numberfield',
allowBlank: false
}
}, {
xtype: 'actioncolumn',
width: 30,
items: [{
iconCls: 'x-fa fa-trash',
tooltip: 'Pašalinti',
handler: function(g, ri, ci) {
var grid = this.up().up();
grid.getStore().removeAt(ri);
grid.getStore().sync();
}
}]
}],
tbar: [{
xtype: 'button',
text: 'Pridėti',
handler: function() {
var grid = this.up().up();
var r = {
label: 'label',
linevalue: '0',
barvalue: '0'
};
var modelResult = grid.getStore().insert(0, r);
}
}]
}]
});
Instead of adding the rowediting plugin inside the initComponent function, you can set the plugin with grid's configs.
Based on your code have remote data, I created a fiddle to test the view, you can apply the view structure with your data.
If you have any question, let me know.
I have this weird issue with ExtJS 4.2.1.
I have a controller whose listeners catch events from a view that it shouldn't.
Here's said controller:
Ext.define('Customer_Portal_UI.controller.NavigationMenu', {
extend: 'Ext.app.Controller',
init: function () {
this.control({
'panel': {
render: function (panel) {
panel.body.on('click', function (panel, e) {
alert('onclick');
});
}
}
});
}
});
It 'controls' this view:
Ext.define('Customer_Portal_UI.view.NavigationMenu', {
extend: 'Ext.form.Panel',
alias: 'widget.navigationmenu',
region: 'west',
layout: 'fit',
ui: 'cssmenu',
loader: {
autoLoad: true,
url: '/resources/notloggedin.html'
}
});
But it also catches panel clicks from this view:
Ext.define("Customer_Portal_UI.view.MainContent", {
extend: 'Ext.form.Panel',
alias: 'widget.maincontent',
region: 'center',
layout: 'card',
border: false,
activeItem: 0,
requires: ['Ext.grid.Panel'],
initComponent: function () {
this.items = [
{
xtype: 'panel',
title: ''
},
{
xtype: 'gridpanel',
id: 'contactlistgrid',
store: Ext.data.StoreManager.lookup('contactStore'),
columns: [
....
],
features: [{
ftype: 'grouping',
groupHeaderTpl: ['{columnName}: {name} - ({rows.length} employees)'],
hideGroupedHeader: true,
startCollapsed: false
}],
viewConfig: { id: 'contactlistgridview' }
},
{
xtype: 'gridpanel',
id: 'caselistgrid',
store: Ext.data.StoreManager.lookup('caseStore'),
columns: [
{ text: 'Title', dataIndex: 'title' },
{ text: 'Description', dataIndex: 'description' },
{ text: 'Ticket number', dataIndex: 'ticketnumber' }
],
viewConfig: { id: 'caselistgridview' }
}
]
this.callParent(arguments);
}
});
Do you see any obvious reasons why it would do this ? panel is indeed the panel I'm clicking and not the document body, which could have explained why.
Note that's in not catching clicks from other panels, just from the MainContent view, which it should not...
Thanks.
The fix was two fold as shown in here:
http://www.fusioncube.net/index.php/sencha-extjs-4-make-any-component-fire-a-click-event/comment-page-1
Then I was able to listen to 'click' for 'panel' (there's only one panel within the view) within my controller without having to refine my selector.
I'm trying to implement a simple framework for an app. The idea is to create a background viewport type 'layout' with a north region containing the page header and an interchangeable center region.
When my app starts, a Login form is shown. If the user/password is ok, the form is destroyed and the main layout should appear. The main layout should insert a nested layout in its center region.
This is my background layout code:
Ext.define('DEMO.view.BackgroundLayout', {
extend: 'Ext.container.Viewport',
alias: 'widget.background',
requires: [
'DEMO.view.Main'
],
layout: {
type: 'border'
},
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
region: 'north',
html: '<h1 class="x-panel-header">Page Title</h1>'
},
{
xtype: 'mainview',
region: 'center',
forceFit: false,
height: 400
}
]
});
me.callParent(arguments);
}
});
The main layout is this:
Ext.define('DEMO.view.Main', {
extend: 'Ext.container.Viewport',
alias: 'widget.mainview',
requires: [
'DEMO.view.MyGridPanel'
],
layout: {
type: 'border'
},
initComponent: function() {
var me = this;
console.log('bb');
Ext.applyIf(me, {
items: [
{
xtype: 'mygridpanel',
region: 'center',
forceFit: false
},
{
xtype: 'container',
height: 38,
forceFit: false,
region: 'north',
items: [
{
xtype: 'button',
height: 34,
id: 'btnLogout',
action: 'logout',
text: 'Logout'
}
]
}
]
});
me.callParent(arguments);
}
});
As you can see, the center region needs an xtype named "mygridpanel". This is the code for it:
Ext.define('DEMO.view.ui.MyGridPanel', {
extend: 'Ext.grid.Panel',
border: '',
height: 106,
title: 'My Grid Panel',
store: 'MyJsonStore',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
viewConfig: {
},
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'Id',
text: 'Id'
},
{
xtype: 'gridcolumn',
dataIndex: 'Name',
text: 'Name'
},
{
xtype: 'gridcolumn',
dataIndex: 'Sales',
text: 'Sales'
}
],
dockedItems: [
{
xtype: 'toolbar',
dock: 'top',
items: [
{
xtype: 'button',
disabled: true,
id: 'btnDelete',
allowDepress: false,
text: 'Delete'
},
{
xtype: 'button',
disabled: true,
id: 'btnEdit',
allowDepress: false,
text: 'Edit'
}
]
}
]
});
me.callParent(arguments);
}
});
My problem is that when I call Ext.create('DEMO.view.BackgroundLayout', {}); it only shows the nested layout, and the background layout is hidden, also I get this error in Chrome's console:
Uncaught Error: HIERARCHY_REQUEST_ERR: DOM Exception 3
What I'm doing wrong?.
Thanks in advance,
Leonardo.
I'm creating a simple SCRUM system in order to teach myself to use EXT 4, so it goes without saying that I'm very new to the framework.
I have a little experience with MVC3 but I'm having some trouble adapting to the way EXT4 works.
My idea is to have 4 grids in a column layout Viewport. Each of the grids is currently its own View. However the Views are almost completely identical. Below is my first View. I've marked the lines that I have to change for the other 3 views.
Ext.define('AM.view.card.BacklogList', { // *** Variable
extend: 'Ext.grid.Panel',
alias: 'widget.backlogcardlist', // *** Variable
title: 'Backlog', // *** Variable
store: 'BacklogCards', // *** Variable
selType: 'cellmodel',
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
columns: [
{
header: 'ID',
dataIndex: 'external_id',
field: 'textfield',
width: 50
},
{
header: 'Name',
dataIndex: 'name',
field: 'textfield',
width: 200
},
{
header: 'Priority',
dataIndex: 'priority_id',
renderer: function (value) {
if (value == 3) {
return "L";
}
else if (value == 2) {
return "M";
}
else {
return "H";
}
},
width: 70,
field: {
xtype: 'combobox',
queryMode: 'local',
typeAhead: true,
store: 'Priorities',
displayField: 'name',
valueField: 'id',
listClass: 'x-combo-list-small'
}
},
{
xtype: 'actioncolumn',
width: 16,
items: [{
icon: 'Styles/Images/zoom.png', // Use a URL in the icon config
tooltip: 'Zoom In',
handler: function (grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
alert("Edit " + rec.get('name'));
}
}]
}
]
});
Is there a way in EXTjs to pass a 'ViewModel'/Parameters to my View so that I can re-use it for each of my grids?
app.js
Ext.application({
name: 'AM',
appFolder: 'app',
controllers: ['BacklogCards', 'InprogressCards', 'ReviewCards', 'DoneCards'],
launch: function () {
Ext.create('Ext.container.Viewport', {
layout: 'column',
items: [
{
xtype: 'backlogcardlist'
},
{
xtype: 'inprogresslist'
},
{
xtype: 'reviewlist'
},
{
xtype: 'donelist'
}
]
});
}
});
Ok! I figured it out by reading this post here:
Extjs 4 MVC loading a view from controller
This is how I modified my app.js file:
Ext.application({
name: 'AM',
appFolder: 'app',
controllers: ['BacklogCards', 'InprogressCards', 'ReviewCards', 'DoneCards'],
launch: function () {
Ext.create('Ext.container.Viewport', {
layout: 'column',
defaults: { flex: 1 },
layout: {
type: 'hbox',
align: 'stretch',
padding: 5
},
items: [
Ext.widget('backlogcardlist',
{
title: "Backlog"
}),
Ext.widget('backlogcardlist',
{
title: "In Progress"
}),
{
xtype: 'reviewlist'
},
{
xtype: 'donelist'
}
]
});
}
});
Here I'm just changing the title property, but I imagine changing the other properties shouldn't be anymore difficult.