Ext JS create custom component(class) - javascript

I want to create a custom component(container) that would contain other components (labels, buttons,...).
I would like to create some kind of a class so I would be able to create multiple instances of this component but with different params. Somekind of constructor. These params would set the labels and button options.
I am using Sencha Architect, so I am wondering is this possible and how it could be done?

Via ExtJS code you just can use the Ext Class System:
Ext.define('MyOwnView', {
extend: 'Ext.container.Container',
constructor: function () {
// ... your code
}
});
To achieve this via Architect GUI, follow this guide (with screenshots):
http://docs.sencha.com/architect/3/creating_an_application/working_with_classes.html

You can use Ext.define (http://docs.sencha.com/extjs/4.2.2/#!/api/Ext-method-define) to define your new class prototype as follows:
Ext.define('My.app.Panel', {
extend: 'Ext.panel.Panel',
requires: [
'My.app.PanelPart2',
'My.app.PanelPart3'
]
constructor: function (config) {
this.callParent(arguments); // calls Ext.panel.Panel's constructor
//...
}
});

Related

Accessing Ext Component Config

I have a very simple extension in Ext JS from Ext.form.Panel:
Ext.define('path.to.SomeClass', {
extend : 'Ext.form.panel',
xtype : 'some-class'
config : {
hasDog : true
},
constructor : function (config) {
if (this.config.hasDog) {
// do something dog related
} else {
// do something not dog related
}
}
});
I then have a "container" for this custom componet:
Ext.define('path.to.OtherClass', {
extend : 'Ext.window.Window',
// ....
items : [{
xtype : 'some-class',
hasDog : false
}]
});
However, for some reason unknown to me, the if...else evaluation in SomeClass is always picking up the default configuration for hasDog. Am I not correctly configuring some-class in OtherClass's items config?
To add a bit more context, OtherClass is called via some using code:
var window = Ext.create('path.to.OtherClass');
window.show();
From what I can see, the above is pretty standard stuff - at least in thought.
The reason why you always get the default configuration is because you're accessing this.config, which is the declaration of your configuration, instead of the actual configuration from the constructor argument. So either use config or - once you've called the parent class constructor - this.
constructor : function (config) {
// before parent class constructor or this.initConfig was called:
console.log(config.hasDog);
// call parent class constructor
this.callParent(arguments);
// after parent class constructor or this.initConfig was called:
console.log(this.hasDog);
}
Also have a look at the documentation:
Note: You need to make sure Ext.Base.initConfig is called from your constructor if you are defining your own class or singleton, unless you are extending a Component. Otherwise the generated getter and setter methods will not be initialized.
In your case, since your extending a component, calling the parent constructor should suffice (as shown in the example above).

ExtJS4 - Extending different components from a single base class

I have a web app for which I am using ExtJS 4.2. This application has a bunch of different components - a panel that displays some data, another panel that displays some other data, a grid, a chart, etc, etc.
It's required that each component has at minimum a specific set of functions and properties. So I'd like to define a 'component' class that I can extend everything else from. For example:
Ext.define('MyApp.BaseComponent', {
extend: 'Ext.panel.Panel',
alias: 'widget.myapp-basecomponent',
prop1: true,
prop2: 17,
func1: function (a, b) {
return a + b;
}
});
Then I would extend every individual component in my app from that base component class. The problem is that if I define the base component as extending 'Ext.panel.Panel', I can only extend other panels from it. I can't extend a grid, tree, etc, etc from it.
Is there a way I can accomplish this? Or am I approaching this the wrong way? Maybe I should just nest everything that's not a panel (grid, chart, etc) in a panel so they can all extend from BaseComponent? Advice greatly appreciated.
If you just want to augment the base component class, you could always just provide an override that adds them:
Ext.define('MyApp.AugmentComponent', {
override: 'Ext.Component',
a: 1,
b: 2,
fn1: function() {
}
});

How to give local variables as properties to cell editor in editable GridX?

I'm using Dojo 1.9 with GridX 1.2. I'm just configuring the ComboBox as editor to the cells in the grid.
I have found the following configuration syntax in the examples:
editor: "dijit/form/ComboBox",
editorArgs: {
props: 'store: myStore, searchAttr: "label"'
}},
The problem is, that props must be a text that would be parsed. It doesn't accept the object. It means, that I must make myStore as global variable, which is something I'd like to avoid.
Is there an alternative way to configure editors in GridX?
QUICK FIX:
instead of creating it as global variable, add it to a namespace, which is widely used for these cases. So, while creating the store, add it to particular namespace and use it in props.
var ns = {};
//use this namespace for all objects subject to grid/a particular section/anything
ns.myStore = new Memory({
data: [
{name:"Option 1", id:"OP1"},
{name:"Option 2", id:"OP2"},
{name:"Option 3Samoa", id:"OP3"}
]
});
props: 'store: ns.myStore, searchAttr: "label"'
So, therefore we can avoid adding up global objects directly to window object.
RECOMMENDED FIX:
In the template string that you pass for that column, instead of using default combo box, use a custom widget.
And in this widget, override the postCreate method and set the desired store.
define([
"dojo/_base/lang",
"dijit/form/ComboBox",
"dojo/store/Memory"
], function(lang, comboBox, Memory) {
return dojo.declare("myapp.widget.MyComboBox", [ dijit.form.ComboBox], {
// summary:
//Custom sub-class of ComboBox with following functionality:
//This will set the desired store
postCreate: function(){
// summary:
// This will call default postCreate and additionally create/set store:
this.inherited(arguments);
var wid = this;
//if store is static get storeObj from a json file
//if store comes from backend, make the call here and get storeObj
dojo.xhrGet({
url: "filenameOrUrl",
handleAs: "json"
}).then(function(result){
var storeObj = new Memory(result);
wid.set("store",storeObj);
});
}
});
});
Now you this in the template for that column. Note that we need not mention the store here neither as string or object, since the widget itself will load the store, once created.
<div data-dojo-type="myapp/widget/MyComboBox"
style="width: 100%"
data-dojo-attach-point="gridCellEditField"
></div>

Backbone component reusability

I'm trying to find best option to make Backbone views reusable. I goggled and found many different solutions but not sure which one suits my requirements. Basically I'm going to have many widgets filled with real time data and I need a base component that will handle service subscriptions
Is following best solution for this problem:
App.View.Base = Backbone.View.extend({
baseMethod: function( params ) {};
});
App.ExtendedView.Base = App.View.Base.extend({
// new stuff here
// overriding App.View.Base.baseMethod
baseMethod: function( params ) {
// overriding stuff here
App.View.Base.prototype.baseMethod.call(this, params); // calling super.baseMethod()
}
});
Is there any better approach? or should I use mixins?
I might be inclined to favour composition over inheritance here, and create a spinner view, and use instances of it in other views that require spinner functionality.
More info: Prefer composition over inheritance?
The typical rule-of-thumb I use for stuff like this is if there are any immutable methods in the base class that provide a common context for all your sub-classes, then inheritance makes sense. For instance, I've created a BaseView class for my Backbone application that looks something like this:
define(function() {
return Backbone.View.extend({
/**
* show() and hide() are immutable
*/
show : function() {
this.beforeShow();
this.doShow();
this.afterShow();
},
hide : function() {
this.beforeHide();
this.doHide();
this.afterHide();
},
doShow : function() {
this.$el.show();
this.trigger('displayComplete', {action : 'show'});
},
doHide : function() {
this.$el.hide();
},
//Override the following to extend behavior of the view
//before and/or after the view is shown/hidden.
beforeShow : function() {},
beforeHide : function() {},
afterShow : function() {},
afterHide : function() {}
});
});
This is a pretty simple example, but it has proven to make things much easier for development of my application, as my central controller object is given a common interface for showing and hiding views. I suppose you could use composition here as well, but that requires doing an explicit extend() at runtime. You get the same result in either case, but I just prefer to have the functionality available when I instantiate my views.
Another thought is that it really depends upon what you want to accomplish. Inheritance is much more rigid than composition, but again, it depends upon what you ultimately want to accomplish, and sometimes enforcing rigidity to maintain a context is a good thing.

ExtJS convering an Ext.app.Controller to an Ext.app.Application

I am trying to convert a class that extends Ext.app.Controller to extending Ext.app.Application. Since Ext.app.Application is a child class of Ext.app.Controller I assumed that simply changing the class being extended would work, instead however, it causes an error in the console that says Uncaught TypeError: Cannot call method 'substring' of undefined. The error occurs at the this.callParent(arguments) inside the constructor: function, Does anyone have any suggestions as to what might be causing this?
You cannot use a constructor within a Ext.app.Application class changes will come with 4.2 but till that use the launch method for example to apply stuff. And do NOT extend.
Application is sort of a singleton instance an get just intialized by calling
Ext.application({
name: 'MyApp',
launch: function() {
Ext.create('Ext.container.Viewport', {
items: {
html: 'My App'
}
});
}
});
Trying to run more instances result in problems but you will be able to do this with 4.2 like so
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
name: 'MyApp'
...
});
Ext.application('MyApp.Application');

Categories

Resources