Dojo/Dijit TitlePane - dojo

How do you make a titlePane's height dynamic so that if content is added to the pane after the page has loaded the TitlePane will expand?

It looks like the rich content editor being an iframe that is loaded asynchronously confuses the initial layout.
As #missingno mentioned, the resize function is what you want to look at.
If you execute the following function on your page, you can see that it does correctly resize everything:
//iterate through all widgets
dijit.registry.forEach(function(widget){
//if widget has a resize function, call it
if(widget.resize){
widget.resize()
}
});
The above function iterates through all widgets and resizes all of them. This is probably unneccessary. I think you would only need to call it on each of your layout-related widgets, after the dijit.Editor is initialized.
The easiest way to do this on the actual page would probably to add it to your addOnLoad function. For exampe:
dojo.addOnLoad(function() {
dijit.byId("ContentLetterTemplate").set("href","index2.html");
//perform resize on widgets after they are created and parsed.
dijit.registry.forEach(function(widget){
//if widget has a resize function, call it
if(widget.resize){
widget.resize()
}
});
});
EDIT: Another possible fix to the problem is setting the doLayout property on your Content Panes to false. By default all ContentPane's (including subclasses such as TitlePane and dojox.layout.ContentPane) have this property set to true. This means that the size of the ContentPane is predetermined and static. By setting the doLayout property to false, the size of the ContentPanes will grow organically as the content becomes larger or smaller.

Layout widgets have a .resize() method that you can call to trigger a recalculation. Most of the time you don't need to call it yourself (as shown in the examples in the comments) but in some situations you have no choice.

I've made an example how to load data after the pane is open and build content of pane.
What bothers me is after creating grid, I have to first put it into DOM, and after that into title pane, otherwise title pane won't get proper height. There should be cleaner way to do this.
Check it out: http://jsfiddle.net/keemor/T46tt/2/
dojo.require("dijit.TitlePane");
dojo.require("dojo.store.Memory");
dojo.require("dojo.data.ObjectStore");
dojo.require("dojox.grid.DataGrid");
dojo.ready(function() {
var pane = new dijit.TitlePane({
title: 'Dynamic title pane',
open: false,
toggle: function() {
var self = this;
self.inherited('toggle', arguments);
self._setContent(self.onDownloadStart(), true);
if (!self.open) {
return;
}
var xhr = dojo.xhrGet({
url: '/echo/json/',
load: function(r) {
var someData = [{
id: 1,
name: "One"},
{
id: 2,
name: "Two"}];
var store = dojo.data.ObjectStore({
objectStore: new dojo.store.Memory({
data: someData
})
});
var grid = new dojox.grid.DataGrid({
store: store,
structure: [{
name: "Name",
field: "name",
width: "200px"}],
autoHeight: true
});
//After inserting grid anywhere on page it gets height
//Without this line title pane doesn't resize after inserting grid
dojo.place(grid.domNode, dojo.body());
grid.startup();
self.set('content', grid.domNode);
}
});
}
});
dojo.place(pane.domNode, dojo.body());
pane.toggle();
});​

My solution is to move innerWidget.startup() into the after advice to "toggle".
titlePane.aspect = aspect.after(titlePane, 'toggle', function () {
if (titlePane.open) {
titlePane.grid.startup();
titlePane.aspect.remove();
}
});
See the dojo/aspect reference documentation for more information.

Related

AnyColumn option added as new column in Dojo enhanced grid view

I am working on dojo enhanced grid view. I am able to display the grid in UI. But AnyColumn option is added as new column.
Example:
Any help will be appreciated...
Here is the Code
var mygrid = new EnhancedGrid({
id: "grid",
store: gridStore, //Data store passed as input
structure: gridStructure, //Column structure passed as input
autoHeight: true,
autoWidth: true,
initialWidth: width,
canSort : true,
plugins: {
filter: {
//Filter operation
isServerSide: true,
disabledConditions : {"anycolumn" : ["equal","less","lessEqual","larger","largerEqual","contains","startsWith","endsWith","equalTo","notContains","notEqualTo","notStartsWith","notEndsWith"]},
setupFilterQuery: function(commands, request){
if(commands.filter && commands.enable){
//filter operation
}
}
}
}, dojo.byId("mydatagrid"));
mygrid.startup();
Thanks,
Lishanth
First, do not use EnhancedGrid, instead use either dgrid or gridx.
I think by default anycolumn is added to the dropdown. If you want to remove then, I would suggest to
Register for click event on the filter definition
Iterate through the drop-down and remove the first entry which is anyColumn
or you can also try something like
dojo.forEach(this.yourgrid.pluginMgr.getPlugin('filter').filterDefDialog._cboxes, function(dropdownbox) {
dropdownbox._colSelect.removeOption(dropdownbox.options[0]);
});
Updated answer is. I know this is not the elegant way of doing it but it works.
//reason why I'm showing the dialog is that _cboxes of the filter are empty initially.
dijit.byId('grid').plugin('filter').filterDefDialog.showDialog();
dojo.forEach(dijit.byId('grid').pluginMgr.getPlugin('filter').filterDefDialog._cboxes, function(dropdownbox) {
var theSelect = dropdownbox._colSelect;
theSelect.removeOption(theSelect.options[0]);
});
//Closing the dialog after removing Any Column
dijit.byId('grid').plugin('filter').filterDefDialog.closeDialog();

dgrid inside ContentPane - Scroll error

I have a problem with dgrid.... I have an AccordionContainer, and in each ContentPane of it,
I place a dgrid. The problems with the dgrid are:
1- Error with scroll: when scrolling down, in certain moment the scroll "skips" and jumps into the end and there's no way to scroll up and show the first records.
(I have seen in Firebug the error TypeError: grid._rows is null when the scroll fails).
2- Trying to change a value: sounds like no dgrid-datachange event is emitted,
no way to capture the event after editing a value.
I think these errors has to do with having dgrid inside layouts (dgrid inside ContentPane, inside AccordionContainer). I also included the DijitRegistry extension but even with this extensions I can't get
rid of this errors.
I have prepared this fiddle which reproduces the errors:
https://jsfiddle.net/9ax3q9jw/5/
Code:
var grid = new (declare([OnDemandGrid, DijitRegistry,Selection, Selector, Editor]))({
collection: tsStore,
selectionMode: 'none',
columns:
[
{id: 'timestamp', label:'Timestamp', formatter: function (value,rowIndex) {
return value[0];
}},
{id: 'value', label: 'Value',
get: function(value){
return value[1];
},
editor: "dijit/form/TextBox"
}
],
showHeader: true
});
grid.startup();
grid.on('dgrid-datachange',function(event){
alert('Change!');
console.log('Change: ' + JSON.stringify(event));
});
//Add Grid and TextArea to AccordionContainer.
var cp = new ContentPane({
title: tsStore.name,
content: grid
},"accordionContainer");
Any help will be appreciated,
Thanks,
Angel.
There are a couple of issues with this example that may be causing you problems.
Data
The store used in the fiddle is being created with an array of arrays, but stores are intended to work with arrays of objects. This is the root of the scrolling issue you're seeing. One property in each object should uniquely identify that object (the 'id' field). Without entry IDs, the grid can't properly keep track of the entries in your data set. The data array can easily be converted to an object array with each entry having timestamp and value properties, and the store can use timestamp as its ID property (the property it uses to uniquely identify each record).
var records = [];
var data = _globalData[0].data;
var item;
for (var i = 0; i < data.length; i++) {
item = data[i];
records.push({
timestamp: item[0],
value: item[1]
});
}
var tsStore = new declare([Memory, Trackable])({
data: records,
idProperty: 'timestamp',
name: 'Temperature'
});
_t._createTimeSeriesGrids(tsStore);
Setting up the store this way also allows the grid column definitions to be simplified. Using field names instead of IDs will allow the grid to call formatter functions with the corresponding field value for each row object.
columns: [{
field: 'timestamp',
label: 'Timestamp',
formatter: function (value) {
return value;
}
}, {
field: 'value',
label: 'Value',
formatter: function (value) {
return value;
},
editor: "dijit/form/TextBox"
}],
Loading
The fiddle is using declarative widgets and Dojo's automatic parsing functionality to build the page. In this situation the loader callback does not wait for the parser to complete before executing, so the widgets may not have been instantiated when the callback runs.
There are two ways to handle this: dojo/ready or explicit use of the parser.
parseOnLoad: true,
deps: [
...
dojo/ready,
dojo/domReady!
],
callback: function (..., ready) {
ready(function () {
var _t = this;
var _globalData = [];
...
});
}
or
parseOnLoad: false,
deps: [
...
dojo/parser,
dojo/domReady!
],
callback: function (..., parser) {
parser.parse().then(function () {
var _t = this;
var _globalData = [];
...
});
}
Layout
When adding widgets to containers, use Dijit's methods, like addChild and set('content', ...). These typically perform actions other than just adding a widget to the DOM, like starting up child widgets.
var cp = new ContentPane({
title: tsStore.name,
content: grid
});
registry.byId('accordionContainer').addChild(cp);
instead of
var cp = new ContentPane({
title: tsStore.name,
content: grid
}, "accordionContainer");
In the example code a ContentPane isn't even needed since the dgrid inherits from DijitRegistry -- it can be added directly as a child of the AccordionContainer.
This will also call the grid's startup method, so the explicit call in the code isn't needed.
registry.byId('accordionContainer').addChild(grid);
It also often necessary to re-layout the grid's container once the grid has been initially rendered to ensure it's properly sized.
var handle = grid.on('dgrid-refresh-complete', function () {
registry.byId('accordionContainer').resize();
// only need to do this the first time
handle.remove();
});

In Extjs4 how to set scrollbar position to bottom of form panel

i am working in extjs4. i have form panel with autoscroll true. I have 20-25 fields with fileUpload field at bottom. When i am uploading file, form's scroll is going to top by default. i want to keep scroll of form as it is on where it was while uploading file. So how to set this scrollBar at bottom of or at upload field section in extjs4
You can try by adding the following method to your form declaration:
scrollToField: function(fieldId) {
var field = Ext.get(fieldId);
field.el.scrollIntoView(this.body.el);
}
Here you have a working sample
IMHO,it will be better, however, to group fields using tabs or something similar to avoid having a long a and hard to read / fill form
I have solve this problem into Ext js 4.2 for Ext.form.panel
See the following code. It will helpful to you.
onRender function call on render event
onRender: function () {
this.callParent(arguments);
if (!this.restoreScrollAfterLayout) {
this.mon(Ext.get(this.getEl().dom.lastElementChild), 'scroll', this.onScroll, this);
this.restoreScrollAfterLayout = true;
}
},
onScroll: function (e ,t, eOpts) {
this.scroll = Ext.get(this.getEl().dom.lastElementChild).getScroll();
},
afterLayout: function () {
this.callParent(arguments);
if (this.restoreScrollAfterLayout && this.scroll) {
var el = Ext.get(this.getEl().dom.lastElementChild),
scroll = this.scroll;
el.scrollTo('left', scroll.left);
el.scrollTo('top', scroll.top);
}
}

extjs How to get a grid

In Designer I set my grid name to equal MyGrid
On clicking the button addRecord is called, it fails where rows is attemting to get an undefined grid.
How do I define this MyGrid so that it references the grid within the panel?
Ext.define('MyApp.view.MyPanel', {
extend: 'MyApp.view.ui.MyPanel',
initComponent: function() {
var me = this;
me.callParent(arguments);
var button = me.down('button[text=Submit]');
button.on('click', me.onSubmitBtnClick, me);
},
addRecord: function(myRecordArray) {
var rows = grid.getStore().getRange(); // ERROR happens here
console.log(rows);
},
onSubmitBtnClick: function() {
this.addRecord(["ll", "kk", "mm"]);
}
});
Chrome Javascript Debugger Console ->
Uncaught ReferenceError: grid is not defined
Before you call grid.getStore() you need to define "grid". You can just do var grid = this; right before the call because you are defining the addRecord function from inside of the grid.
EDIT:
I just noticed that this wasn't being called from inside the grid panel with the store but some other panel. What you will have to do to is set an id config on your grid panel. E.g. id: MyGridPanel There may already be an id config set on it and you just have to find out what it is. If you are using the ExtJS designer it may actually already be set to "MyGridPanel". Then you would call it like so:
var grid = Ext.getCmp("MyGridPanel");
then you would do:
grid.getStore().getRange()
try changing button.on('click', me.onSubmitBtnClick, me) to button.on('click', Ext.bind(me.onSubmitBtnClick, me), me)
This looks like a scope issue, in your onSubmitBtn() method, this probably refering to the wrong object (e.g. window, or the button), and not the grid object, which is what you want.

Load html data with AJAX in Sencha touch when panel is shown

I have a TabPanel with a Tabbar and four panels inside. I want to load the HTML content for the fourth panel with an AJAX call when the panel becomes visible.
The AJAX function fetches the data from the server and places it inside the panel, which uses the panel update function. The problem is how to call this function when the panel becomes visible. A simplified version is:
Pages.Contact = new Ext.Panel({
title: 'Contact',
html: 'test data',
iconCls: 'user',
cls: 'cHome',
activate: function () {
Pages.Contact.update("my ajax data");
}
});
When I go to my panel the body content is not affected. Does anyone know what goes wrong here? I've already tried to replace activate with render and show.
To add event's listeners you need to do
listeners: {
activate: function(){
console.log('activate fired');
}
},
But that's not the event you want to listen. It's better to listen for beforecardswitch on the TapPanel object, example:
listeners: {
beforecardswitch:function(newCard, oldCard, index, anim){
if(index == 3){
//loadJson and update card.
// you may want to use this also
newCard.setLoading(true);
//and after the json request has finished set it to false.
}
}
},
The solution was to use:
beforecardswitch:function(object, newCard, oldCard, index, anim) {
As shown by Ilya139 by with the object parameter as first parameter.
Then the index variable returns the correct cardnumber.