ExtJS Panel Inheritance/Base class - extjs

I am trying to create my own Date/Time field. I know there are a few that others have made, I'm making my own .
My question is as follows. I want to create a new object, DateTime, which extends Ext.Panel. I specify some properties for width, height, etc but I also specify the values for the items property which will contain a date field and a time field. When I try to actually instantiate the created object, I get an error saying "Object or property not supported". When I go into the error, it seems that the items collection throws an error The code is as follows:
var dateField = new AppealDate({
id: 'dateField',
tabIndex: 0,
fieldLabel: '',
msgTarget: 'under'
});
var timeField = new Ext.form.TimeField({
id: 'timeField',
tabIndex: 0,
fieldLabel: '',
msgTarget: 'under'
});
var DateTime = Ext.extend(Ext.Panel, {
id: '',
xtype: 'panel',
fieldLabel: '',
layout: 'table',
layoutConfig: {
columns: 2
},
items: [dateField, timeField]
});
var dateTimeField = new DateTime(); //this throws an error

Your class is missing initComponent. You also need to render the panel somewhere.
DateTime = Ext.extend(Ext.Panel, {
initComponent: function() {
// define dateField, timeField here.
this.dateField = new AppealDate({
id: 'dateField',
msgTarget: 'under'
});
this.timeField = new Ext.form.TimeField({
id: 'timeField',
msgTarget: 'under'
});
Ext.apply(this, {
items: [this.dateField, this.timeField]
});
DateTime.superclass.initComponent.call(this);
}
});
var dateTimeField = new DateTime();
dateTimeField.render(Ext.get('someDiv'));

As a comment outside of your direct question, "DateTime" is a terrible name for a Panel subclass. You want someone coming along later to know what kind of class they are dealing with -- "DateTimeField" would be much better, based on how you're using it (although that implies a Field subclass as explained below...).
However, note that another potential issue since you are intending to use this Panel as a Field is that a FormPanel is going to expect its form fields to support the Ext.form.Field interface, which your "field" will not (i.e., you won't be able to add your DateTime object into a form's items config). So if your goal is to create a truly reusable component that can be treated as a Field, you're going to want to add methods like getValue, setValue, markInvalid, etc. that internally interact with your constituent fields. It's not a trivial task to get it all working smoothly.
(Not sure if this is your goal, but thought I would mention it since I've gone down this road myself).

Related

ExtJs - custom class resolution

Let's say I have a concrete view named "view." I would like, at runtime, be able to call Ext.create("view_1") or Ext.create({ xtype: "view_5" }) and they will create instances of "view".
So any xtype matching the regex: /view_[0-9]+/ should create a "view" instead.
Is this possible, if so how?
More details,
We added the ability for our users to create custom reports. They define the menu name, the title, the set of columns, and the data constraint to be used. Each custom report is constructed using the same xtype view.
The problem arise when we save the state for these custom reports. Normally, we use the xtype as key for storage. So if all custom reports are the same xtype they override each other's state.
The direct workaround is to have different xtype for each custom report. So "view_1", "view_5", "view_1008"...view_[0-9]+ are the xtypes associated with custom report #1, custom report #5, custom report #1008...custom report [0-9]+. But they all should be constructed using xtype view.
If we create aliases, we would need to add all reasonable/possible form of view_[0-9]+. I am not sure this approach scales very well when we have more types of dynamic views.
Isn't possible to create a view from regex.
In my opinion, the best way you can do is to set alias as list of strings.
Example:
Ext.define('SomeView', {
alias: ['widget.view_1', 'widget.view_2', 'widget.view_3', 'widget.view_4' ...],
});
Update ( according to the comment ) :
Maybe you want to create multiple views (same definition) with id like:
Ext.create("SomeView", {
id: "view_1",
});
Ext.create("SomeView", {
id: "view_2",
});
Update :
The other way is to override Ext.create function.
Example on https://fiddle.sencha.com/#view/editor&fiddle/32lj
Ext.apply(Ext, {
_create: Ext.create
});
Ext.override(Ext, {
create: function () {
var name = arguments[0],
nameType = typeof name;
if(nameType == 'string'){
let regex = /widget\.viewx_[0-9]+/;
let found = name.match(regex);
if (found) {
name = "widget.viewx";
}
}
return Ext._create(name, arguments[1], arguments[2], arguments[3]);
}
});
And usage:
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create("Ext.panel.Panel", {
width: 300,
height: 300,
renderTo: Ext.getBody(),
items: [{
xtype: 'viewx',
fieldLabel: "AA"
}, {
xtype: 'viewx_1',
fieldLabel: "AA"
}, {
xtype: 'viewx_2',
fieldLabel: "AA"
}]
});
}
});

Trying to get a basic combo to work in ExtJS

I want to use a very simple combo box in ExtJS, but I was surprised to learn that it seems as though I have to complexify things by using a store.
I have a single array of data :
var states = [
{"name":"Alabama"},
{"name":"Alaska"}
]
I create my model 'State' linking to the 'name' field, and then I create my store linking to the model, and the array of data.
Ext.regModel('State', {
fields: [
{type: 'string', name: 'name'}
]
});
var store1 = Ext.create('Ext.data.Store', {
model: 'State',
data: states
});
Now I create my combo, as a field in my panel :
var f = Ext.create('Ext.form.Panel', {
items: [
{
fieldLabel: 'hi there',
xtype: 'combobox',
name: 'XXXX',
store:store1,
maxLength: 64,
allowBlank: false
}
]
})
Nothing tells me that I am doing anything wrong, but I get an 'Uncaught TypeError: Cannot read property 'indexOf' of undefined ' whenever I try and open the combo.
My fiddle is here :
http://jsfiddle.net/sr61tpmd/1/
Another aside to my question is, what is the simplest way I can present a combobox in ExtjS?
As long as you only want a combo box with same value as displayed, it is entirely possible to define the store as an array.
xtype:'combo',
store:['Alabama','Arkansas',...]
A real extjs store is necessary where your displayed text differs from the value. You can see a working example for this (also using the us states, actually) in the ext docs: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.form.field.ComboBox

How to get all xtype values from a window

Let's say I have a window which are several combobox's and texfield's. What I want to do, getting all selected and filled values from this window to be able to post server side.
I used to ComponentQuery but only getting specified type of field. Is there any solution to get any kind of xtype values, like combobox, checkbox, textfield etc?
The solution is to use an Ext.form.Panel, it contains functionality to manage groups of fields:
var win = new Ext.window.Window({
layout: 'fit',
items: {
border: false,
xtype: 'form',
items: [] // your fields here
}
});
// Later
console.log(win.down('form').getForm().getValues());

How to get ExtJs 4 panel to update itself on data refresh

I'm using ExtJs 4.
I have a panel that looks something like this:
var panel = Ext.create('Ext.panel.Panel',{
title: 'Current Transaction Data',
width: 500,
items:[
{
id: 'field1',
xtype: 'textfield',
label:'Field 1',
},
{
id: 'field 2',
xtype: 'textfield',
label:'Field 1',
}
],
})
I have a function to issue an ajax request that looks something like this:
var myDataObject;
var getData= function(callback){
Ext.Ajax.request({
url: 'MY-URL-TO-GET-DATA',
success: function(response){
myDataObject= Ext.JSON.decode(response.responseText)}})}
What I want to do is that after I retrieve my data object, I want to tell the panel to update with the new data. I'm looking for a call like panel.update(data).
I have seen the update() method on panel, but don't understand how to use it. Do I override it? It says something about using templates, but I haven't found any good examples. I'm not even sure if that's the preferred approach for doing this.
I have done similar type things using grid panel and using a data store. In that case I can call refresh() on the data store, but I don't want to use a grid for this particular problem.
You could use panel.update(data) but that just injects the text as innerHTML effectively, using the configured tpl if necessary. What are the two text fields in your panel for? You could set the text of one of those fields to the data, or add a Ext.form.field.DisplayView to the panel, and set the value of that to the data.
EDIT: As suggested in the comments below, the answer is to subclass and add a method to do the data refresh.

Replacing store contents in Ext JS

I need to pick up Ext JS for a project I working on, and here's a simple issue that got surfaced in it which I can't figure out:
Here's my code:
var arrayData = [
['Jay Gar','MD'],
['Aaron Baker','CA'],
['Susan Smith','NY'],
['Mary Stein','KT'],
['John Zalupic','WA'],
];
var store = Ext.create('Ext.data.ArrayStore',{
data: arrayData,
fields: ['personName', 'state']
});
var grid = Ext.create('Ext.grid.Panel', {
title: 'first grid',
renderTo: Ext.getBody(),
authoHeight:true,
width: 250,
store: store,
autoScroll: true,
columns: [
{ header: 'name', dataIndex: 'personName' },
{ header: 'st', dataIndex: 'state', sortable: false }
]
});
grid.getSelectionModel().on('selectionchange', function(sm, selectedRecord){
var newData = [
['Poka Boka', 'VK'],
['Choko Mok', 'CA']
];
store.removeAll();
store.add(newData);
});
So basically I populate the grid with default values and whenever one of them is clicked, data in the store is getting replaced with new data, which should in turn prompt re-render of the Grid Panel. It does work, but with one consistent issue:
When I click on any element, the newData values flash below the data it's about to replace and for some reason it shows 3 rows: first one, second one and then first one again. Also, I get an error saying "Uncaught TypeError: Cannot read property 'internalId' of undefined" happening on this line: store.add(newData).
Any idea what might be causing it? I'm using Ext JS 4.
Thank you!
Luka
The add method is expecting records and you are passing an Array.
You should create an instance of your store record type and iterate to create as many records as you need and then add them to the store.
here is an example:
var store=this.getStore();
var rt = store.recordType;
var p = new rt({
InvoiceLineNum: '',
LineNumber:'',
ItemDescription: '',
Quantity: '',
UnitPrice: '',
UnitMeasure:'',
TotalAmount:'',
OrderDate:new Date()
});
this.stopEditing();
store.insert(count, p);
this.startEditing(count, 0);
this.markEditableCells(count);
I use the insert here but you can use the add just as well.

Resources