I have some code that is pulling a Release model back and displaying in a grid, this is working fine, but I cannot work out how to inspect what is in the returned model.
What I would like is to get the contents of the model in some kind of object that I can reorganise or drill into as I see fit (in this case the release model).
If I add a component and just dump the model into the html it is not returning the contents as I would expect.
Rally.data.ModelFactory.getModel({
type: 'Release',
success: function(model) {
this.add({
xtype: 'component',
html: model
});
this.grid = this.add({
xtype: 'rallygrid',
model: model,
columnCfgs: [
'FormattedID',
'Name',
'RevisionHistory' ],
storeConfig: {
filters: queryFilters
}
});
},
scope: this
});
If I dig into the ExtJS docs it seems I should be able to do something like getData() on the model to return the contents but this is not working.
Inspection in the debugger tells me I have a "Rally.domain.v2.0.project.10098485624.Release" object but I can't see how to simply access the list of items in the object. Obviously there is a way because passing this model to a grid component will display it quite happily.
The debugger for this object shows me a number of further functions to call but I have no idea which one or how to use it
...
getArtifactMappings: function () {
getCollectionFields: function () {
getCustomFields: function () {
getField: function (fieldName) {
getFields: function () {
getFieldsByName: function (fieldNames) {
getName: function () {
getNonCollectionFields: function () {
getPermissionLevels: function (permission) {
getProxy: function () {
etc...
The Rally docs indicate I should be able to call getData() on a model https://help.rallydev.com/apps/2.0rc2/doc/#!/api/Rally.data.Model but it looks like the ModelFactory.getModel() is not returning a type that has a getData() method
A model is a class, and a record is an instance of that class.
getData() will work on a record.
There are static methods that would work on the actual model, but getData() is not one of them.
Here is a fragment from the code below:
_onDataLoaded: function(store, data){
_.each(data, function(record){
var r = record.getData();
console.log('release', r);
This code builds a grid of Releases filtered by project and ReleaseStartDate. I noticed that in your code you want to display model information, maybe for debug purposes, by actually modifying the dom. I would prefer to use console.log, but in the example below I did both. I used a border layout with a footer, and set html proprety of the container in the footer to JSON.stringify(r)
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
layout:'border',
defaults: {
collapsible: true,
split: true,
bodyStyle: 'padding:15px',
},
items: [{
title: 'data',
region:'south',
itemId: 'd',
margins: '5 0 0 0',
cmargins: '5 5 0 0'
},{
title: 'Releases',
itemId: 'r',
collapsible: false,
region:'center',
margins: '5 0 0 0'
}] ,
launch: function() {
var context = this.getContext();
var projectId = context.getProject().ObjectID;
var millisecondsInDay = 86400000;
var currentDate = new Date();
var startDate = new Date(currentDate - millisecondsInDay*90); //in the last 90 days
var startDateUTC = startDate.toISOString();
Ext.create('Rally.data.WsapiDataStore', {
model: 'Release',
fetch: ['Name','ReleaseStartDate','ReleaseDate', 'State'],
filters: [
{
property: 'ReleaseStartDate',
operator: '>',
value: startDateUTC
},
{
property: 'Project',
operator: '=',
value: '/project/'+ projectId
}
],
autoLoad: true,
listeners: {
load: this._onDataLoaded,
scope: this
}
});
},
_onDataLoaded: function(store, data){
var text = '';
_.each(data, function(record){
var r = record.getData();
console.log('release', r);
text = text + JSON.stringify(r);
});
console.log('text', text);
this.down('#d').add({
xtype:'container',
html: text
});
if (!this.down('#g')) {
this.down('#r').add({
xtype: 'rallygrid',
store: store,
itemId: 'g',
columnCfgs: [
{
text: 'Name', dataIndex: 'Name'
},
{
text: 'State', dataIndex: 'State'
},
{
text: 'Start Date', dataIndex: 'ReleaseStartDate', flex:1
},
{
text: 'Release Date', dataIndex: 'ReleaseDate',flex:1
}
]
});
}
else{
(this.down('#g')).reconfigure(store);
}
}
});
Related
I am using ExtJs for my Application. I made a window in which i have some fields . one field is name which is changing each time when window show.
but since i am not destroying window on button click it not rendering again and showing previous data only. How I make sure for new data.
My code
Code of My Field in form reside in window
items: [
{
xtype: 'combobox',
name: 'Assigned To',
queryMode: 'local',
store: this.getResourceStore(),
displayField: 'svmx_name',
labelAlign: 'top',
fieldLabel: 'Assigned_To',
listeners: {
scope: this,
select: function (combo, record, index) {
var form = display_form.getForm();
var id = record.getId();
form.findField('ResourceId').setValue(id);
},
afterrender: function (combo, record, index) {
console.log(this.getResourceName());
combo.setValue(this.getResourceName());
},
}
},
Setting fields in window.
if (!this.win) {
this.win = Ext.widget({
xtype: 'editorwindow',
resourceStore: Ext.getCmp('scheduler1').getResourceStore(),
eventStore: Ext.getCmp('scheduler1').getEventStore(),
wrapper: Ext.getCmp('scheduler1').getWrapper(),
resourceName: targetResource,
startdate: date,
targetData: dragSource.data,
});
}
this.win.show();
I would define an own window class with a config object to set your required data.
The framework will create setter and getter functions for you.
Ext.define(MyFieldsWindow, {
extend: Ext.window.Window,
xtype: 'myfieldswindow',
config: {
resourceName: '',
startdate: null,
targetData: null
},
}
In the update function set the value to the specific component.
The updateResourceName function will look like.
updateResourceName: function (newResourceName, oldResourceName) {
var resourceNameCmp = this.getComponent('resourceName');
resourceNameCmp.setValue(newResourceName);
},
Now you can set the config when you create an instance.
if (!this.win) {
this.win = Ext.create({
xtype: 'myfieldswindow',
resourceStore: Ext.getCmp('scheduler1').getResourceStore(),
eventStore: Ext.getCmp('scheduler1').getEventStore(),
wrapper: Ext.getCmp('scheduler1').getWrapper(),
resourceName: targetResource,
startdate: date,
targetData: dragSource.data,
});
}
this.win.show();
Or you can set it at runtime with the setter method.
this.win.setResourceName('Roli Agrawal');
The window class looks like.
Ext.define(MyFieldsWindow, {
extend: Ext.window.Window,
config: {
resourceName: '',
startdate: null,
targetData: null
},
updateResourceName: function (newResourceName, oldResourceName) {
var resourceNameCmp = this.getComponent('resourceName');
resourceNameCmp.setValue(newResourceName);
},
updateStartDate: function () {/*similar code like above*/ },
updateTargetDate: function () {/*similar code like above*/ },
items: [
{
itemId: 'resourceName',
xtype: 'textfield'
},
/* additional items*/
]
});
I have window with button enter and few fields i need to get the data out of the form and there is method on button :
enter: function (button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
Here record is undefined. What i do wrong?
////////////////////////////////////////////////////////////////////
Here the form:
Ext.define('ExtMVC.view.portlet.Login', {
extend: 'Ext.window.Window',
alias: 'widget.login',
layout: 'fit',
title: 'LogIn',
width: 300,
height: 150,
autoShow: true,
store: 'LoginModels',
initComponent: function () {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name: 'Name',
fieldLabel: 'Name',
style: { 'margin': '10px' },
},
{
xtype: 'textfield',
name: 'Password',
fieldLabel: 'Password',
style: { 'margin': '10px' },
}
]
}
];
this.buttons = [
{
text: 'Enter',
action: 'enter',
//handler: this.enter
},
{
text: 'Cancel',
scope: this,
handler: this.close
},
{
text: 'Sing in',
scope: this,
handler: this.close
}
];
this.callParent(arguments);
}
});
try to replace with this code
values=form.getForm().getValues();
Please go through the ext doc as it clearly says:
getRecord( ) : Ext.data.Model :
Returns the currently loaded Ext.data.Model instance if one was loaded via loadRecord.
And in case of your example I dont see any code that loads your form panel using loadRecord().
enter: function (button) {
var win = button.up('window'),
form = win.down('form'),
//record = form.getRecord(), /*not required here*/
record = this.getUsersStore().findRecord('id', 1) /*if you know id or some thing which field is know*/
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
You have to load form using form.loadRecord() before fetching it through form.getRecord(), otherwise form.getRecord() returns undefined.
We are trying to build a simple prototype to consume our data service using ExtJs (also to learn ExtJs at the same time).
While developing the prototype (with basic knowledge on ExtJS), I encountered several hickups. Before I post questions, I would like to have you to take a quick look at the following.
The following is the main class which interacts with the service. We wanted to make sure that certain UI components are masked/unmasked during ajax communications.
Ext.define('Sample.provider.SvcClient', {
TestConnectivity: function(prms){
debugger;
Ext.Ajax.on('beforerequest', function(conn,o,result) {
prms.BeforeRequest(conn,o,result);
});
Ext.Ajax.on('requestcomplete',function(conn,o,result) {
prms.RequestComplete(conn,o,result);
});
Ext.Ajax.on('requestexception',function(conn,o,result) {
prms.RequestException(conn,o,result);
});
Ext.Ajax.request({
url: prms.Url,
method: prms.HttpMethod,
headers: {
'Authorization' : 'Basic ' + prms.Credentials
},
success: prms.Success,
failure: prms.Failure,
callback: prms.Callback
});
}
});
We developed an extension to SvcClient especially to help masking of controls during ajax communications:
Ext.define('Sample.util.ClientProxy', {
CtlToMask : null,
DoTestConnection: function(ctlToMask, callback, url, userName, pwd) {
debugger;
var proxy = this;
proxy.CtlToMask = ctlToMask;
var client = new Sample.provider.SvcClient();
var params = {
Url: url,
HttpMethod: "GET",
Credentials: Sample.util.Conversions.Base64.encode(userName + ":" + pwd),
CtlToMask: proxy.CtlToMask,
Scope:proxy,
BeforeRequest: function(conn,o,result,Scope) {
debugger;
if(Scope.CtlToMask !=null) {
if(Scope.CtlToMask.getEl() != undefined)
Scope.CtlToMask.getEl().mask('Testing Connectivity...', 'x-mask-loading');
else
Scope.CtlToMask.mask('Testing Connectivity...', 'x-mask-loading');
}
},
RequestComplete: function(conn,o,result) {
if(this.CtlToMask !=null) {
if(this.CtlToMask.getEl() != undefined)
this.CtlToMask.getEl().unmask(true);
else
this.CtlToMask.unmask(true);
}
},
RequestException: function(conn,o,result) {
if(this.CtlToMask !=null) {
if(this.CtlToMask.getEl() != undefined)
this.CtlToMask.getEl().unmask(true);
else
this.CtlToMask.unmask(true);
}
}
};
client.TestConnectivity(params);
}
});
I have the controller as shown below:
Ext.define('Sample.controller.Locations', {
extend: 'Ext.app.Controller',
models: ['Location', 'Country'],
views: [
'portal.location.Menu',
'portal.location.Edit'
],
init: function() {
this.control({
'locationsMenu':{
OpenAddNewSvcPopup: this.OnOpenAddNewSvcPopup
},
'locationsEdit':{
TestSvcConnectivity: this.OnTestSvcConnectivity,
render: function () { },
afterrender: function () { },
boxready: function () { }
}
});
},
OnOpenAddNewSvcPopup: function(){
var newLoc = Ext.create('Sample.model.Location', {
UserName: 'admin',
Uri: 'http://localhost/DataServicesBase/Data.svc'
});
var v = Ext.create('widget.locationsEdit',{ mode:'add'});
v.down('form').loadRecord(newLoc);
},
OnTestSvcConnectivity: function(ctl){
var proxy = new Sample.util.ClientProxy();
proxy.DoTestConnection(
ctl,
this.OnTestSvcConnectivityCallback,
ctl.down("#Uri").value + '/Countries',
ctl.down("#UserName").value,
ctl.down("#Password").value
);
},
OnTestSvcConnectivityCallback: function(options,success,result){
if(success) {
//show the result
}
else {
//Show error in window
}
}
});
The view would look like the following:
Ext.define('Sample.view.portal.location.Edit', {
extend: 'Ext.window.Window',
alias: 'widget.locationsEdit',
//title: 'Edit Service Location',
layout: 'fit',
autoShow: true,
title: 'Edit Service Location',
bodyStyle: 'border:0px',
closeAction:'destroy',
config:{
mode: 'edit'
},
constructor: function(configs){
this.callParent(arguments);
this.initConfig(configs);
if(this.mode == "add") this.setTitle('Add New Service Location');
},
initComponent: function() {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name: 'Id',
itemId: 'Id',
fieldLabel: 'Unique Name',
labelStyle: 'font-weight:bold',
allowBlank: false,
maxLength: 64,
width: 300
},
{
xtype: 'textfield',
name : 'Uri',
itemId: 'Uri',
fieldLabel: 'URI',
maxLength: 300,
width: 500,
allowBlank: false
},
{
xtype: 'textfield',
name : 'UserName',
itemId: 'UserName',
fieldLabel: 'User Name',
allowBlank: false,
maxLength: 64,
width: 200
},
{
xtype: 'textfield',
name : 'Password',
itemId: 'Password',
fieldLabel: 'Password',
allowBlank: false,
maxLength: 64,
width: 200
}
],
bodyStyle: 'padding:5px;'
}
];
this.buttons = [
{
text: 'Test Connectivity',
action: 'test',
scope: this,
handler: this.OnTestSvcConnectivity
},
{
text: 'Save',
action: 'save'
},
{
text: 'Cancel',
scope: this,
handler: this.close
}
];
this.callParent();
this.addEvents('TestSvcConnectivity') //custom event
},
OnTestSvcConnectivity: function(){
this.fireEvent('TestSvcConnectivity', this); //will be raised to controller
}
});
Q1
The approach works fine during first time when I click on "Test Connection" button (from the popup). If I click the same button for the second time, the (BeforeRequest) handler fires twice. Clicking for the third time, the handler gets fired thrice. What is the mistake in my code.
Q2
If I cancel the popup and again click on "Test Connection" it would never work. The handler still maintains "some" kind of reference (or state) of previous popup instance. As it could not be found, it throws "undefine" on object members. I confirmed this as through the debugger, I could see the id of previous popup instance instead of the current one. The handler always tries to honor the first popup instantiated no matter what.
Q3
Is the pattern we are trying to follow for this sample prototype is having any pitfalls/problems. We are trying to develop using MVC features of ExtJS and ensure that we are using stand and good patterns/practices so that we will not be facing above kind of very basic issues.
I am trying to create a component and access it inside controller. But while accessing the component by id, it is not returning the component. It always returns undefined. Please find below the code.
enter code here
//Component creation in view layer as below
Ext.define('MyApp.view.performance.grid.IFrameGridCmp', {
extend: 'Ext.panel.Panel',
alias: 'widget.crMainPanel',
id:'mainPanelId',
layout: {
align: 'stretch',
type: 'vbox'
},
border:0,
resizable: false,
forceFit: true,
autoWidth: true,
initComponent: function() {
Ext.apply(this, {
items: [
{
xtype:'panel',
flex:.02,
border:0
},
{
xtype:'crHeaderPanel',
flex:.05
},
{
xtype: 'crUpperPanel',
flex: 0.93
},
Ext.create('Ext.Component', {
autoEl: {
tag: 'iframe',
cls: 'x-hidden',
src: Ext.SSL_SECURE_URL
},
id:'FileDownloader',
height:0,
listeners: {
afterrender: function () {
this.getEl().on('load', function () {
console.log('loaded download frame');
});
}
},
load: function(config){
var e = this.getEl();
e.dom.src = config.url + (config.params ? '?' + Ext.urlEncode(config.params) : '');
e.dom.onload = function() {
Ext.getBody().unmask();
if(e.dom.contentDocument.body.childNodes[0].wholeText == '404') {
Ext.Msg.show({
title: 'Attachment missing',
msg: 'The document you are after can not be found on the server.',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
}
};
}
})
]
});
this.callParent(arguments);
}
});
========================================
enter code here
//Accessing the controller as below in controller
views: ['performance.grid.IFrameGridCmp'],
//The below line gives error
var downloader = Ext.getCmp('FileDownloader');
downloader.load({
url: '/APXUI/data/json/xls?exportData='+Ext.JSON.encode(records)
});
Well, the view is not created at the time you are calling Ext.getCmp()
Note that views: ['performance.grid.IFrameGridCmp'], is only a sort of binding that view to the controller, which means the controller will create a getter for you, nothing more. You still need to instantiate the view by calling .create(); or Ext.widget('crMainPanel')
In you controller use control for example to handle it:
me.control({
'crMainPanel #FileDownloader': {
afterrender: me.addDownloader
}
});
Don't use Ext.getCmp() it is really slow and you will have many issues with that.
Don't use id - better use itemId.
Why you need to call this from controller?
I am unable to set the value for the textfield which is inside fieldcontainer. I want to set the value and other config for the "textfield" which is inside the "fieldcontainer". So basically i set the configuration for the textfield which i receive from the server, like for example : allowBank: true , maxlength: 4, value: 'Hello World' i get from the server and want to supply it to the textdfield which is inside my custom control which is fieldcontainer. All other configuration is applied except for the value config using the built in textConfig. Below is my code:
Ext.define('PTextField', { extend: 'Ext.form.FieldContainer',
alias: 'widget.ptextfield',
requires: ['Ext.form.TextField', 'Ext.Img'],
width: 170,
fieldLabel: 'Empty Label',
labelAlign: 'top',
layout: {
type: 'hbox'
},
BLANK_IMAGE_URL: '',
constructor: function (config) {
this.callParent(arguments);
Ext.apply(this.down('textfield'), this.textConfig);
Ext.apply(this.down('image'), this.imgConfig);
}, // eo function constructor
initComponent: function () {
var me = this;
this.textBox = this.createTextField();
this.imageBox = this.createImagefield();
this.items = [this.imageBox, this.textBox];
this.callParent(arguments);
}, //eo initComponent
createTextField: function () { return {xtype: 'textfield'} },
createImagefield: function () { return { xtype: 'image', height: 20, width: 20} }
});
var fname = Ext.create('PTextField', {
fieldLabel: 'First Name',
textConfig: { value: 'Hello World', allowBlank: false, readOnly: true, maxLength: 4, width: 100 },
imgConfig: { src: 'http://www.sencha.com/img/20110215-feat-html5.png' }
});
fname.render(Ext.getBody());
I am using extjs 4.1.
Any help is appreciated.
You should simply create the textfield and image using your configs. Then define your items array using the created objects, like this:
initComponent: function() {
var me = this,
textfield = Ext.widget('textfield', me.textConfig),
image = Ext.widget('image', me.imgConfig);
me.items = [textfield, image];
me.callParent(arguments);
},
I would simplify your code to something like that:
Remove whole constructor() function. you don't need it.
Rewrite initComponent() function for your fieldset as:
initComponent: function() {
var me = this;
Ext.apply(me, items: [{
xtype: 'textfield',
value: me.textConfig.value,
....
}, {
xtype: 'image',
src: me.imageConfig.src,
...
}]);
}