Grid loadMask malfunction.Set loadMask target config - javascript

The grid loadMask has some problems.
LoadMask:true does not work.
If I choose to do as follows:
viewConfig: {
loadMask: {msg: 'Loading records ...'}
}
It works but the mask only covers the grid body, excluding toolbares.
I tried maskElement: 'el' but did not work.
I do not intend to use setLoading ().
One solution might be target to my grid:
viewConfig: {
loadMask: {msg: 'Loading records ...', target: this}
}
But target: this does not work.
Any idea how to get and set grid reference in the config target?

You would have to override the createMask function of AbstractView.
Ext.define('Test',{
override:'Ext.view.AbstractView',
privates:{
createMask:function(mask) {
if(this.ownerCt) {
if(!Ext.isObject(mask)) mask = {target:this.ownerCt};
else if(!mask.target) mask.target = this.ownerCt;
}
this.callParent(arguments);
}
}
});
Fiddle

Related

Dragging windows

I did some research on this and still can't find a good solution for it. I wrote my app in ExtJS 4.1 and when I run it on an iPod the dragging functionality is disabled by default (which is what I want), but if I write the same app in ExtJS 6.2 all windows can be draggable which causes issues of visibility of the app. With that being said, Does anyone know how to disable window dragging when using Tablets (iPod, iPad, etc.)? I'm using ExtJS 6.2
Here's my working code that works great for a single window, but I want a general solution that will stop ALL windows from being dragged.
var win = Ext.create('Ext.Window', {
title: "My Window",
width: 500,
modal: true,
layout: 'fit',
items: form,
buttons: [{
text: 'Close',
handler: function() {
win.hide();
}
}]
});
win.show();
if(Ext.os.deviceType === 'Tablet') {
win.dd.disable();
}
A "global solution" sounds like you want to use an override to apply one of the other answers globally to your application:
Ext.define('MyAppName.override.Window', {
override: 'Ext.window.Window',
initComponent: function() {
this.callParent(arguments);
if(Ext.os.deviceType === 'Tablet') {
this.dd.disable();
}
}
})
or
Ext.define('MyAppName.override.Window', {
override: 'Ext.window.Window',
initComponent: function() {
if(Ext.os.deviceType === 'Tablet') {
this.draggable = false;
}
this.callParent(arguments);
}
})
To make the override work, put it into the file app/override/Window.js and add a reference to your requires array in Application.js:
requires: [
'MyAppName.override.Window'
],
You are looking for Ext.os class.
More precisely Ext.os.is method, according to the docs it has all the values you would need.
I am not sure why you want to block only iPads and not tables in general. If you wan tablets than you can use if(Ext.os.deviceType === 'Tablet') {...}
Otherwise if(Ext.os.is.iPad) {...}.
UPDATE Solution:
If you want to force anything across all classes in the ExtJS you would use Ext.override.
So the solution would be to put at the beginning of the app this code:
if (Ext.os.deviceType === 'Tablet') {
Ext.override('Ext.Window', {
privates: {
initDraggable: function(){}
}
})
}
FYI You can check the Ext.Window source code. I had to override this method, the default value draggable: false doesn't work.
https://fiddle.sencha.com/#view/editor&fiddle/2iqi
To test it, just press F12 switch to table mode.
But this solution has 1 drawback:
If the target is a class declared using Ext.define, the override
method of that class is called
Which means this solution don't work when you use Ext.create('Ext.Window',{})
Solution for that would be to define our own Ext.Window class and than inside the app when you are using Ext.create('Ext.Window' you would use Ext.create('Fiddle.view.MyWindow', and when we have our own function already we don't need to use override but can put if directly into the class definition like this:
Ext.define('Fiddle.view.MyWindow', {
extend: 'Ext.Window',
alias: 'widget.mywindow',
draggable: (function(){
if (Ext.os.deviceType === 'Tablet') {
return false;
} else {
return true;
}
})()
});
https://fiddle.sencha.com/#view/editor&fiddle/2iqj
I don't know how to override it for Ext.create('Ext.Window' if you still insists on using it. One solution would be to re-write Ext.create or simply edit the framework source itself but I highly discourage from that.
Why you are not using draggable: false in window config
Here is some code in FIDDLE
var win = Ext.create('Fiddle.view.MyWindow', {
title: "My Window",
width: 500,
draggable: false,
modal: true,
layout: 'fit',
buttons: [{
text: 'Close',
handler: function() {
win.hide();
}
}]
});
win.show();

Ext.Defer gives getAsynchronousLoad Error

I've just defined a combobox. Firstly it loads a countrylist and when select a value it's fire a change event which doing a ajax query to DB within searching service;
The thing; this configuration works pretty well when I click and open combobox items. But when I'm typing to combobox's field it's fires listener's store.load and because of none of country selected yet, the search query url gives not found errors of course.
{
xtype: 'countrycombo',
itemId: 'countryName',
name:'country',
afterLabelTextTpl: MyApp.Globals.required,
allowBlank: false,
flex: 1,
// forceSelection: false,
// typeAhead: true,
// typeAheadDelay: 50,
store: {
proxy: {
type: 'ajax',
// isSynchronous: true,
url: MyApp.Globals.getUrl() + '/country/list?limit=250',
// timeout: 300000,
reader: {
type: 'json',
rootProperty: 'data'
}
},
pageSize: 0,
sorters: 'description',
autoLoad: true
}
,
listeners: {
change: function (combo, countryId) {
var cityStore = Ext.getStore('cityCombo');
cityStore.getProxy()
.setUrl(MyAppp.Globals.getUrl() + '/city/view/search?query=countryid:'+ countryId);
// Ext.defer(cityStore.load, 100);
cityStore.load();
}
}
},
I've tried several things as you see in code above to set a delay/timeout for load during typing to combobox text field; Ext.defer, timeoutconfig on proxy, typeAhead config on combo but none of them worked!
I thought that Ext.defer is the best solution but it gives this error:
Uncaught TypeError: me.getAsynchronousLoad is not a function at load (ProxyStore.js?_dc=15169)
How can I set a delay/timeout to combobox to fires load function?
Instead of Ext.defer(cityStore.load, 100);
try using this :
Ext.defer(function(){
cityStore.load
}, 300);
If this doest work, try increasing your delay
or you can put a logic before loading
like this :
if(countryId.length == 5){
cityStore.load
}
This will ensure that you Entered the right values before loading
Hope this helps, and Goodluck on your project
well.. I've tried to implement #Leroy's advice but somehow Ext.defer did not fire cityStore.load. So I keep examine similar situations on google and found Ext.util.DelayedTask
So configured the listerens's change to this and it's works pretty well;
listeners: {
change: function (combo, countryId) {
var alert = new Ext.util.DelayedTask(function () {
Ext.Msg.alert('Info!', 'Please select a country');
});
var cityStore = Ext.getStore('cityCombo');
cityStore.getProxy().setUrl(MyApp.Globals.getUrl() + '/city/view/search?query=countryid:'+ countryId);
if (typeof countryId === 'number') {
cityStore.load();
} else {
alert.delay(8000);
}
}
}

Grid with json store sometimes don't show data

I have a extjs 4 grid panel with remote stores.
On the renderer of column there is function, which change ID to NAME.
Mostly times it works fine, but sometimes (~40%) the grid shows with empty columns.
I've tried to debug - the store is defined, but its items are empty.
To my mind store not loaded yet, or already destroyed (if it is possible).
How to correctly show grid, with full data?
There is my simplified code:
Loading needed components
Ext.Loader.setConfig({
enabled:true
});
Ext.Loader.setPath('Ext.ux', '/js/ux');
Ext.require([
'Ext.grid.*',
'Ext.data.*'
]);
Ext.onReady(function () {
Create models
Ext.define('Expense', {
extend:'Ext.data.Model',
fields:[
{name:'id', type:'number'},
{name:'cost_id', type:'string'},
{name:'comment', type:'string'}
]
});
Ext.define('Cost', {
extend:'Ext.data.Model',
fields:[
{name:'id', type:'string'},
{name:'name', type:'string'},
{name:'displayname', type:'string'}
]
});
Create stores
store = Ext.create('Ext.data.Store', {
autoDestroy:true,
model:'Expense',
autoLoad:true,
autoSync:true,
pageSize:30,
proxy:{
type:'ajax',
url:'/expenses/gettable',
reader:{
type:'json',
root:'data',
record:'Expense'
}, writer:{
type:'json'
},
api:{
create:'/expenses/create',
update:'/expenses/update',
destroy:'/expenses/delete'
}
}
});
costsStore = Ext.create('Ext.data.Store', {
autoDestroy:true,
model:'Cost',
autoLoad:true,
autoSync:true,
proxy:{
type:'ajax',
url:'/costs/gettable',
reader:{
type:'json',
record:'Cost'
}, writer:{
type:'json',
allowSingle:false
},
api:{
create:'/costs/create',
update:'/costs/update'
}
}
});
Configure grid panel
grid = Ext.create('Ext.grid.Panel', {
store:store,
autoSync:true,
columns:[
{
id:'comment',
header:'Задача',
dataIndex:'comment',
flex:5
},
{
id:'cost',
header:'Cost',
dataIndex:'cost_id',
flex:5,
editor:{
xtype:'combobox',
store:costsStore,
valueField:'id',
displayField:'name',
name:'cost_id'
},
renderer:function (value, meta, record) {
if (value != '') {
ind = costsStore.find('id', value);
elem = costsStore.getAt(ind);
if (elem) {
return elem.data['name'];
}
}
}
}
],
renderTo:'editor-grid'
});
});
I've tried to manually load stores on grid render event:
grid = Ext.create('Ext.grid.Panel', {
listeners:{
beforerender:function(){
store.load();
costsStore.load();
}
}
...
});
It is decrease empty table to ~10% cases, but not 0%...
The only way I've found is to set delay after loading all stores, and then show grid, something like this:
listeners:{
'load':function(){
window.setTimeout("getGrid()", 1000);
}
}
Where getGrid() is the function with creating grid.panel.
What I have to do, to show grid only after all stores loaded, or show error if data can't load?
As sra suggested - your problem seems to stem from using a store within a renderer, while you cannot be sure that store is loaded.
I have described what I think is the most elegant solution to this problem in this answer, with some code examples.

ExtJS renderTo element not found

I have an MVC architecture, but when I try to make another TabPanel insite an existing one, I get this in the browser:
el is null
el = el.dom || Ext.getDom(el); ext-all-debug.js (line 12807)
From what I understand, it seems that the new TabPanel can't find the needed div for it to render. Anyway, here is the controller:
Ext.define('FI.controller.MainController', {
extend: 'Ext.app.Controller',
id: 'mainController',
views: ['MainTabPanel', 'UnitsTabPanel', 'SummariesTabPanel'],
mainTabPanel : {},
unitsTabPanel : {},
summariesTabPanel : {},
init: function(){
console.log("main controller is init");
console.log(this);
this.control({
'mainTabPanel':{
afterrender: this.onCreate
}
});
this.mainTabPanel = Ext.widget('mainTabPanel');
},
onCreate: function(){
console.log("main tab panel is created");
console.log(this);
this.unitsTabPanel = Ext.widget('unitsTabPanel');
this.summariesTabPanel = Ext.widget('summariesTabPanel');
}
});
This is the MainTabPanel:
Ext.define("FI.view.MainTabPanel", {
extend: 'Ext.tab.Panel',
renderTo:'container',
alias: 'widget.mainTabPanel',
enableTabScroll: true,
items:[{
title:'Units',
html: "<div id='units'></div>",
closable: false
},
{title: 'Summaries',
html: "<div id='summaries'></div>",
closable:false
}
]
});
And this is the SummariesTabPanel(the one with problems):
Ext.define("FI.view.SummariesTabPanel", {
extend: 'Ext.tab.Panel',
renderTo: 'summaries',
alias: 'widget.summariesTabPanel',
enableTabScroll: true
});
The problem is with the SummariesTabPanel. If I don't create it, the UnitsTabPanel gets rendered. For some reason, it can't find the summaries div.
Can you please tell me what is wrong?
The SummariesTabPanel renders to the "units" div according to your last snippet of code, is that correct? If not, replace renderTo: 'units' with renderTo: 'summaries'.
Edit
Since it was not the case, you may take a look ath this piece of Ext 4 Panel documentation (here: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.panel.Panel-cfg-html ) that says that the html content isn't added until the component is completely rendered. So, you have to wait for the afterrender event of the tab (not the tabpanel, as you do now) before you can actually get the DOM element.
If you instantiate this Panel
{title: 'Summaries',
html: "<div id='summaries'></div>",
closable:false
}
and store the pointer to it into a separate variable, you could listen to its afterrender event and try again.
A workaround to this could be using an existing element of the page (that is, a static html fragment) instead of adding it via the Panel's html config option.
Why are you doing this that way? If you want to have a nested panels - just define them inside one another. Don't use renderTo
Ext.define("FI.view.SummariesTabPanel", {
extend: 'Ext.tab.Panel',
alias: 'widget.summariesTabPanel'
});
Ext.define("FI.view.MainTabPanel", {
extend: 'Ext.tab.Panel',
alias: 'widget.mainTabPanel',
enableTabScroll: true,
items:[{
xtype: 'summariesTabPanel'
title:'Units',
closable: false
}
]
});

ExtJS mask a TreePanel without toolbar

Im trying to mask a tree panel without the toolbar so that the user can keep typing as the panel is masked. This seems to be harder than I thought so some suggestions would be great!
Although its prob not necessary, Here is my (stripped down) base tree panel:
Ext.tree.TreePanel({
id:'quicksearch_panel',
root:{
nodeType:'async',
preloadChildren:false
},
loader: new Ext.tree.TreeLoader({
dataUrl:'...',
baseParams:{}
}),
tbar:['Quicksearch:', {
xtype:'textfield',
id:'quicksearch_combo',
emptyText: 'search...',
listeners:{
keyup:{buffer:400, fn:function(field, e) {
// Mask Panel and not Combo HERE
}}
}
}]
});
I think you can try to mask the body of the TreePanel? The Element body is an element in all components that inherits Panel, and the Toolbar is in fact out of this body element so you probably could just mask the body, your toolbar will be out of the masking overlay.
Try this:
var tree = Ext.tree.TreePanel({
//......
tbar: ['Quicksearch:', {
xtype:'textfield',
emptyText: 'search...',
enableKeyEvents: true, //you need this for key events
listeners:{
keyup:{
buffer:400,
fn:function(field, e) {
tree.body.mask();
//When the searching done, unmask it
//tree.body.unmask();
}
}
}
}]
});
Do update us if it works :)

Categories