I am writing a Rally App in which I have a rallychart and a button.
I need to access the chart and modify its setting on a button click. The button is also in the same app container as the rallychart.
I tried Ext. this. etc.
These access specifiers do not work. Could you please help me with this?
Sample code:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
id: 'appid',
launch: function () {
var datepickerfrom = Ext.create('Ext.Container', {
items: [{
xtype: 'rallytextfield',
fieldLabel: 'Enter Start Date for chart (mm/dd/yyyy): ',
labelWidth: 150
}],
renderTo: Ext.getBody().dom,
id: 'd1'
});
this.add(datepickerfrom);
this.add(
{
xtype: 'rallychart',
height: 400,
width: 800,
id: 'chart1',
itemId: 'chart1',
chartConfig: chartConfig,
renderTo: Ext.getBody().dom
}
);
button2 = {
xtype: 'rallybutton',
text: 'Plot Graph',
handler: function () {
console.clear();
console.log("Clicking button");
// I NEED to ACCESS the CHART HERE or EVEN the TEXTFIELD DATA HERE
},
callback: function(){
}
};
this.add(button2);
You may reference them via itemID. After the itemID on the element is set:
this.add(
{
xtype: 'rallychart',
height: 400,
itemId: 'myChart',
chartConfig: {//...}
//...
}
it can be used to reference the element:
this.down('#myChart')
In addition to what Nick said (referencing by id) you can create a variable for each one as you define them like so:
var pickerForm = this.add(datepickerfrom);
var chart = this.add({
xtype: 'rallychart',
height: 400,
width: 800,
id: 'chart1',
itemId: 'chart1',
chartConfig: chartConfig,
renderTo: Ext.getBody().dom
});
And then reference them like this:
chart.method1();
...
Here is an example application. The toggle button shows and hides the cardboard:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
items: [{
xtype: 'button',
text : 'Toggle Cardboard',
handler: function() {
if (App.cardBoard.isHidden()) {
App.cardBoard.show();
} else {
App.cardBoard.hide();
}
}
}],
launch: function() {
App = this;
var addNewConfig = {
xtype: 'rallyaddnew',
recordTypes: ['PortfolioItem/Feature', 'PortfolioItem/Initiative', 'PortfolioItem/Theme'],
ignoredRequiredFields: ['Name', 'Project'],
showAddWithDetails: false
};
App.addNew = this.add(addNewConfig);
var cardBoardConfig = {
xtype: 'rallycardboard',
types: ['PortfolioItem/Feature', 'PortfolioItem/Rollup'],
attribute: 'InvestmentCategory'
};
App.cardBoard = this.add(cardBoardConfig);
}
});
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 added a listener onParentPagePopupCommit for button in popup which was declared in parent view controller and added the popup in view port, now the view model bindings are working as expected, but not sure how to invoke the parent view controller methods without exposing the same methods names in child view controller. Is there any way to extend View Controller during runtime in ExtJs Modern 6.5.
Fiddle
onShowChildPopup: function (sender) {
var popup = sender.up('panel').popups['childPopup'],
pageCtrler = sender.lookupController(),
pageVM = pageCtrler.getViewModel(),
page = pageCtrler.getView(),
popupCtrler = new Ext.app.ViewController({
parent: pageCtrler, //setting parent ctrler
//popup commit event on popup view controller
onPopupCommit: function () {
debugger;
Ext.Msg.alert("Popup Update", "Popup View Controller Invoked")
console.log("popup view controller - commit");
},
// this works but any other way
// same methods name on popup view ctrler...
/*onParentPagePopupCommit: function(){
debugger;
// I don't like this way of invoking a parent method
// this may introduce few more bugs if the parent gets value from its own
// view model - (this will be parent vm and not child/popup.)
// need something similar to extend inorder to reuse certain methods..
this.parent.onParentPagePopupCommit();
var vm = this.getViewModel().get('vm');
vm.set('fullName',this.getFullName());
}*/
}),
popupVM = new Ext.app.ViewModel({
parent: pageVM, //setting parent view model
links: {
//vm is not merging with parent
//vm: {
childvm: {
reference: 'ChildModel',
create: {
address: "child Address",
phone: "child Phone"
}
}
}
});
popup.controller = popupCtrler;
popup.viewModel = popupVM;
popup = Ext.create(popup);
popup.setShowAnimation({
type: 'slideIn',
duration: 325,
direction: 'up'
});
popup.setHideAnimation({
type: 'slideOut',
duration: 325,
direction: 'down'
});
popup.setCentered(true);
/* popup.on('show', function () {
debugger;
});*/
Ext.Viewport.add(popup).show();
//popup.showBy(page, "c-c");
}
For this you need to use extend config in controller.
For example:
Ext.define('Person', {
say: function(text) { alert(text); }
});
Ext.define('Developer', {
extend: 'Person',
say: function(text) { this.callParent(["print "+text]); }
});
In this FIDDLE, I have created a demo using your code and made some modification. I hope this will help or guide your to achieve you requirement.
Code Snippet
Ext.define('ParentModel', {
extend: 'Ext.data.Model',
alias: 'model.parentmodel',
fields: [{
name: 'firstName',
type: 'string'
}, {
name: 'lastName',
type: 'string'
}, {
name: 'address',
type: 'string'
}]
});
Ext.define('ChildModel', {
extend: 'Ext.data.Model',
alias: 'model.childmodel',
fields: [{
name: 'address',
type: 'string'
}, {
name: 'phone',
type: 'number'
}, {
name: 'fullName',
type: 'string'
}]
});
Ext.define('PageViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.pageviewmodel',
links: {
vm: {
reference: 'ParentModel',
create: {
firstName: 'firstName-ParentVM',
lastName: 'lastName-ParentVM'
}
}
}
});
Ext.define('PageViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.pageviewcontroller',
init: function () {
this.callParent(arguments);
},
//i understand fullname can also be done on model using formula/conver
//this is just a sample
getFullName: function () {
var vm = this.getViewModel().get('vm');
return vm.get('firstName') + " " + vm.get('lastName');
},
//popup commit event on parent view controller
onParentPagePopupCommit: function (button) {
var vm = button.up('formpanel').getViewModel().get('vm');
vm.commit();
Ext.Msg.alert("Parent Page Update", "Parent View Controller Invoked");
console.log("Page view controller - commit");
},
onShowChildPopup: function (button) {
var popup = button.up('panel').popups['childPopup'],
pageCtrler = button.lookupController(),
pageVM = pageCtrler.getViewModel(),
page = pageCtrler.getView(),
popupVM = new Ext.app.ViewModel({
parent: pageVM, //setting parent ViewModel
links: {
//vm is not merging with parent
//vm: {
childvm: {
reference: 'ChildModel',
create: {
address: "child Address",
phone: "child Phone"
}
}
}
});
popup.viewModel = popupVM;
popup = Ext.create(popup);
popup.setShowAnimation({
type: 'slideIn',
duration: 325,
direction: 'up'
}).setHideAnimation({
type: 'slideOut',
duration: 325,
direction: 'down'
}).setCentered(true);
Ext.Viewport.add(popup).show();
}
});
//Need to extend popup controller from PageViewController(parent)
Ext.define('PopupViewController', {
extend: 'PageViewController',
alias: 'controller.popupviewcontroller',
//popup commit event on popup view controller
onPopupCommit: function () {
Ext.Msg.alert("Popup Update", "Popup View Controller Invoked")
console.log("popup view controller - commit");
}
});
Ext.define('MainPage', {
extend: 'Ext.Panel',
config: {
title: 'Page',
width: '100%',
height: '100%',
layout: {
type: 'vbox',
align: 'stretch'
}
},
viewModel: {
type: 'pageviewmodel'
},
controller: {
type: 'pageviewcontroller'
},
width: '100%',
height: '100%',
popups: {
childPopup: {
xtype: 'formpanel',
controller: 'popupviewcontroller',
title: 'Cild Popup',
floating: true,
modal: true,
hideonMaskTap: true,
layout: 'float',
minWidth: 300,
maxHeight: 580,
tools: [{
type: 'close',
handler: function () {
var me = this.up('formpanel');
me.hide();
}
}],
items: [{
xtype: 'container',
layout: {
type: 'vbox',
align: 'stretch',
pack: 'center'
},
items: [{
xtype: 'fieldset',
items: [{
xtype: 'label',
bind: {
html: '{vm.firstName} {vm.lastName}'
}
}, {
xtype: 'textfield',
label: 'First Name',
name: 'firstName',
bind: {
value: '{vm.firstName}'
}
}, {
xtype: 'textfield',
label: 'Last Name',
name: 'lastName',
bind: {
value: '{vm.lastName}'
}
}, {
xtype: 'textfield',
label: 'Last Name',
name: 'lastName',
bind: {
//value: '{vm.address}'
value: '{childvm.address}'
}
}]
}, {
xtype: 'container',
docked: 'bottom',
layout: 'hbox',
items: [{
xtype: 'button',
text: 'Popup Update',
handler: 'onPopupCommit'
}, {
xtype: 'button',
text: 'Parent Update',
handler: 'onParentPagePopupCommit'
}]
}]
}]
}
},
bodyPadding: 10,
items: [{
xtype: 'fieldset',
title: 'Enter your name',
items: [{
xtype: 'textfield',
label: 'First Name',
name: 'firstName',
bind: {
value: '{vm.firstName}'
}
}, {
xtype: 'textfield',
label: 'Last Name',
name: 'lastName',
bind: {
value: '{vm.lastName}'
}
}]
}, {
xtype: 'button',
text: 'Show Popup',
handler: 'onShowChildPopup'
}]
});
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.Viewport.add(Ext.create('MainPage'));
}
});
I created a normal window in ExtJS5 which has one grid and one button. I want to get store field items from grid store and want to do another functionality.
When i get store.fields, it shows null. But if i get in ExtJS3, then it works proper.
In below image, I am getting store fields or fields items in ExtJS3.
Here is my code (ExtJS5)
Ext.onReady(function () {
var States = Ext.create('Ext.data.Store',
{
fields: ['value'],
data:
[
{ "value": "HR" },
{ "value": "DL" },
{ "value": "RJ" }
]
});
var window = new Ext.Window({
id: 'grdWindow',
width: 400,
title: 'Grid Samples',
items: [
{
xtype: 'panel',
layout: 'fit',
renderTo: Ext.getBody(),
items: [
{
xtype: 'button',
text: 'Submit',
handler: function () {
var storeFields = Ext.getCmp('grdSample').getStore().fields;
//storeFields get null;
}
},
{
xtype: 'grid',
id: 'grdSample',
store: States,
columns: [
{
header: 'Name',
dataIndex: 'value'
}
]
}
]
}]
}).show();
});
grid.getStore().getModel().getFields() should do what you want.
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!
i have a tab-panel which works fine so far,
but as soon as i apply a grid-panel as one of the tabs i'm getting a js-error somewhere in Observerable.js (a class from ext) that say that 'item.on(...)' is not a function after 'item is undefinded'
Here are the appropriate code lines:
This is what i do in my tab panel:
initComponent: function() {
this.items = [{
xtype: 'profileList',
title: 'Profiles'
}];
this.callParent(arguments);
}
and here is how the code of my grid panel:
Ext.define('BC.view.profile.ProfileList', {
extend: 'Ext.grid.Panel',
alias: 'widget.profileList',
cls: 'profileList',
border: false,
initComponent: function(){
Ext.apply(this, {
store: 'Profiles',
columns: [{
text: 'Name',
dataIndex: 'name',
flex: 1,
}, {
text: 'Others',
dataIndex: 'otherUsers',
width: 200
}, {
text: 'Limit',
dataIndex: 'limit',
width: 200
}]
});
console.log('before');
this.callParent(arguments);
console.log('after');
}
});
Thanks for any help!
Edit: the first console.log works, the error seems to happen in 'callParent()'
You cannot create the items of the tab panel like that:
this.items = [{
xtype: 'profileList',
title: 'Profiles'
}];
You should use Ext.apply(... instead:
Ext.apply(this,{items:[{
xtype: 'profileList',
title: 'Profiles'
}]);