I need to access a PropertyGrid of a created NewPerson window.
NewPerson window is composed of a propertygrid and a toolbar.
When a user fill in the propertygrid and hits 'Save' button, a new
person should be created with the attributes present in the
propertygrid.
the problem is that a user should be able to create as many NewPerson windows as he needs, so how can I access the propertygrid of a window? Thanks.
NewPerson Window View:
Ext.define('MyApp.view.ui.NewPerson', {
extend: 'Ext.window.Window',
height: 180,
width: 524,
resizable: false
,
layout: {
type: 'fit'
},
title: 'New Person',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
dockedItems: [
{
xtype: 'newpersontoolbar',
dock: 'bottom'
}
],
items: [
{
xtype: 'newpersongrid'
}
]
});
me.callParent(arguments);
}
});
NewPersonGrid View:
Ext.define('MyApp.view.ui.NewPersonGrid', {
extend: 'Ext.grid.property.Grid',
border: 0,
id: 'newpersongrid',
forceFit: true,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
source: {
'Property 1': 'String',
'Property 2': true,
'Property 3': '2012-02-20T19:22:06',
'Property 4': 123
},
listeners: {
afterlayout: {
fn: me.onPropertyAfterLayout,
scope: me
}
}
});
me.callParent(arguments);
},
onPropertyAfterLayout: function(abstractcontainer, layout, options) {
}
});
NewPersonToolbar View:
Ext.define('MyApp.view.ui.NewPersonToolbar', {
extend: 'Ext.toolbar.Toolbar',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'savebutton'
}
]
});
me.callParent(arguments);
}
});
SaveButton View:
Ext.define('MyApp.view.ui.SaveButton', {
extend: 'Ext.button.Button',
text: 'Save person',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
listeners: {
click: {
fn: me.onButtonClick,
scope: me
}
}
});
me.callParent(arguments);
},
onButtonClick: function(button, e, options) {
// GRID = code here to access propertygrid
Ext.create('MyApp.model.Person', Ext.encode(GRID.getSource()));
}
});
Since your MyApp.view.ui.NewPerson is a component that contains both the property grid and a save button, it makes sense to put the logic that binds the two there:
Ext.define('MyApp.view.ui.NewPerson', {
extend: 'Ext.window.Window',
...
initComponent: function() {
var me = this;
Ext.applyIf(me, {
dockedItems: [
{
xtype: 'newpersontoolbar',
dock: 'bottom'
}
],
items: [
{
xtype: 'newpersongrid'
}
]
});
me.callParent(arguments);
me.down('#savePersonButton').handler = function(button, e) {
me.down('#newpersongrid').doSomething();
}
}
});
You will need to add itemId = 'savePersonButton' and itemId = 'newpersongrid' property to both your button and grid respectively (since it is not an id it can be used in many instances of component, but will be scoped to one container each time.
Related
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 have some ExtJS forms containing radiogroups.
And each of these radioGroups have 2 radios having inputValues as true and false.
But when I set form values using form.setValues(values), if radioButton value I want to set is false, respective radio is not getting selected. This works in case my value is true.
Here is link for fiddle
This works if you change booleanRadio: true.
My Code:
Ext.define('myView', {
extend: 'Ext.panel.Panel',
xtype: 'myView',
id: 'myViewContainer',
layout: 'vbox',
width: '100%',
initComponent: function() {
var me = this;
var allItems = [];
allItems.push(me.getMyForm());
Ext.applyIf(me, {
items: allItems
});
me.callParent(arguments);
},
getMyForm: function() {
var me = this;
var currentForm = {
xtype: 'form',
cls: 'y-form',
id: 'myForm',
trackResetOnLoad: true,
items: [
{
xtype: 'radiogroup',
fieldLabel: 'is Sponsored',
labelSeparator: '',
layout: 'hbox',
items: [
{
xtype: 'radiofield',
name: 'isSponsored',
boxLabel: 'Yes',
inputValue: true
},
{
xtype: 'radiofield',
name: 'isSponsored',
boxLabel: 'No',
inputValue: false
}
]
}
]
};
return currentForm;
}
});
Ext.define('myController', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'panel#myViewContainer': {
afterrender: this.retrieveFormValues
}
});
},
retrieveFormValues: function() {
var me = this;
var data = {isSponsored: false};
if (data != null && !Ext.Object.isEmpty(data)) {
var myFormContainer = Ext.getCmp('myViewContainer');
myFormContainer.getForm().setValues(data);
}
}
});
if you change the inputValues of radiobuttons to 0 or 1, and adjust values var accordingly, the desired radio button will be set. I have updated the fiddle.
items: [{
boxLabel: 'Item 1',
name: 'booleanRadio',
inputValue: 1,
}, {
boxLabel: 'Item 2',
name: 'booleanRadio',
inputValue: 0,
}],
listeners: {
afterrender: function(radioGroupForm) {
var values = {
booleanRadio: 0
}
Ext.getCmp('radioGroupFormPanel').getForm().setValues(values);
}
}
If you send false to radiobutton, it unchecks the radio. That's why your 'true' is working and 'false' is not.
I have a listContainer and on tap of any item in the list, I open another page known as editContainer with the record from list. In the edit page, I want to disable a dropdown based on the value of another field, is there any way I can get the values in record in the initialize function of editContainer? Here is my code:-
onListItemTap:function(dataview,index,target,record,e,eOpts)
{
if(record)
this.editContainer = Ext.create('myApp.view.EditContainer',{title:'Edit Data'});
this.editContainer.setRecord(record);
this.getMainNav().push(this.editContainer);
}
Above code opens editContainer when a list item is selected. Below is my EditContainer
Ext.define('myApp.view.EditContainer', {
extend: 'Ext.Container',
requires: [
'Ext.form.Panel',
'Ext.form.FieldSet',
'Ext.field.Select'
],
config: {
id: 'editContainer',
autoDestroy: false,
layout: 'fit',
items: [
{
xtype: 'formpanel',
id: 'editFormPanel',
padding: 10,
styleHtmlContent: true,
autoDestroy: false,
layout: 'fit',
items: [
{
xtype: 'fieldset',
id: 'nameFieldSet',
autoDestroy: false,
items: [
{
xtype: 'textfield',
id: 'siteName',
itemId: 'mytextfield',
label: 'Name',
labelWidth: '35%',
name: 'name'
},
{
xtype: 'selectfield',
id: 'role',
itemId: 'myselectfield4',
label: 'Role',
labelWidth: '35%',
name: 'role',
options: [
{
text: 'Unassigned',
value: 'Unassigned'
},
{
text: 'Role1',
value: 'role1'
}
]
},
{
xtype: 'selectfield',
id: 'type',
label: 'Type',
labelWidth: '35%',
name: 'type',
options: [
{
text: 'Default',
value: 'Default'
},
{
text: 'Custom',
value: 'custom'
}
]
},
{
xtype: 'selectfield',
id: 'roleValue',
label: 'Role Value',
labelWidth: '35%',
name: 'rolevalue',
options: [
{
text: 'value1',
value: 'value1'
},
{
text: 'value2',
value: 'value2'
},
{
text: 'value3',
value: 'value3'
}
]
}
]
}
]
}
],
listeners: [
{
fn: 'onTextfieldKeyup',
event: 'keyup',
delegate: 'textfield'
},
{
fn: 'onSelectfieldChange',
event: 'change',
delegate: 'selectfield'
}
]
},
onTextfieldKeyup: function(textfield, e, eOpts) {
this.fireEvent('change', this);
},
onSelectfieldChange: function(selectfield, newValue, oldValue, eOpts) {
this.fireEvent('change', this);
},
initialize: function() {
this.callParent();
var record;
//Code to disable roleValue selectfield if Role is unassigned.
},
updateRecord: function(newRecord) {
var me = this,
myPanel = me.down('#editFormPanel');
if(myPanel)
myPanel.setRecord(newRecord);
},
saveRecord: function() {
var me =this,
myStore = Ext.data.StoreManager.lookup('MyStore');
var formPanel = me.down('#editFormPanel'),
record = formPanel.getRecord();
formPanel.updateRecord(record);
return record;
}
});
Since creating your editContainer and setting its data are two different steps in your code you can't use the initialize method of the editContainer.
But you can override the setRecord method of the editContainer, so it additionally disables the dropdown.
Since you push the editContainer onto a navigation view you could also use the activate event of the editContainer to disable the dropdown.
Maybe you can create a quick store on the fly, as a place to have a reference to that data...
//in your controller where you set the record
var mod = Ext.define('app.model.PanelDataModel', {
extend: 'Ext.data.Model',
config: {
fields: [
'roleValue'
]
}
});
var sto = Ext.create('Ext.data.Store', {
model: mod,
id:'PanelDataStore'
});
sto.add({
roleValue: record.roleValue
});
sto.sync();
//Now in your panel's initialize method:
var pstore = Ext.getStore('PanelDataStore');
pstore.load();
if(pstore.data.all[0].data.roleValue == 'unassigned'){
Ext.getCmp('roleValue').setDisabled(true);
}
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 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);
}
});