I have been learning SenCha Touch for awhile and still feel confused when trying to create a store.
In the SenCha Documentation, it says to use Ext.create() Example
I tried and it simply doesn't work.
For the rest of others, I always see people use Ext.define() to create a store and it works.
Now, my question is:
what are the differences between them and when/how to use either one of them in a right way?
Some demo code is highly appreciated
Thanks a lot my friends.
define is for declaring a class.
Ext.define('Foo', {
extend: 'Bar'
});
// Similar to:
public class Foo : Bar {
}
create is for creating an instance:
var o = Ext.create('Foo'); // Can also have var o = new Foo();
// Similar to:
Foo o = new Foo();
Ext.create
- to create an instance of a pre-defined class.
- the class was defined using Ext.define
- used to define the data and behavior of a component. which will be used later.
Ext.define
- to define your own class definition
- reusable component.
- instances can be created using Ext.create API.
Related
In a single-page ExtJS 6 application I need to scan through all classes ever declared with Ext.define method and find those implementing specific mixin. For simplicity let's assume that all classes I am interested in are already loaded, and on-demand loading mechanisms are out of the game.
There seems to be no other way to iterate than via private Ext.ClassManager.classes property. Is there a cleaner alternative?
Anyway, the above gives the list of class names. How to figure out whether corresponding classes implement specific mixin?
function getClassesByMixin(mixin){
var classes=[];
Ext.iterate(Ext.ClassManager.classes,function(className,c){
if(c.prototype &&c.prototype.mixins && c.prototype.mixins[mixin]){
classes.push(className);
}
});
return classes;
}
Sencha fiddle
I have an Ext.form.field.Text and I want to override the setValue function.
What is the recommended way to override this class functionality in ExtJS? Ext.override?
For clarification:
By real class modification I mean a intended permanent
modification/extension of a class, which should always be done by extending a class.
But it is not a temporary solution for just a specific problem (bug-fix, etc.).
You have at least four options how to override members of (Ext) Classes
prototype I guess is well known and allows you to override a member for all instances of a class. You can use it like
Ext.view.View.prototype.emptyText = "";
While you can't use it like
// callParent is NOT allowed for prototype
Ext.form.field.Text.prototype.setValue = function(val) {
var me = this,
inputEl = me.inputEl;
if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
inputEl.removeCls(me.emptyCls);
me.valueContainsPlaceholder = false;
}
me.callParent(arguments);
me.applyEmptyText();
return me;
};
Here's a JSFiddle
This variant should not be used for real class modifications.
Ext.override does nearly the same then prototype but it fully applies to the ExtJS Class-system which allows you to use callParent()
You can use it like
// callParent is allowed for override
Ext.override('Ext.form.field.Text', {
setValue: function(val) {
this.callParent(['In override']);
return this;
}
});
Here's a JSFiddle (c-p error fixed! Thanks to #nogridbag)
Use case: I faced a (I think still existing) bad behavior of a
radiogroup where ExtJS expect a object (key-value-pair) for correct
setting of the value. But I have just one integer on my backend. I
first applied a fix using Ext.override for the setValue()
method and afterwards extend from radiogroup. There I just make a
Key-Value-Pair from the given value and call the parent method with
that.
As #rixo mentioned this can be used for overriding a instance member. And may therefore be qualified for overriding even mixins (I never tested it myself)
var panel = new Ext.Panel({ ... });
Ext.override(panel, {
initComponent: function () {
// extra processing...
this.callParent();
}
});
This variant should not be used for real class modifications.
Extending a existent class to apply additional behavior & rendering. Use this variant to create a subtype that behaves different without loosing the original type.
In the following example we extend the textfield with a method to change the labelcolor when setting a new value called setColored and override the setValue method to take care of removing a label color when setValue is called directly
Ext.define('Ext.ux.field.Text',{
extend: 'Ext.form.field.Text',
widget: 'uxtextfield',
setColored: function(val,color) {
var me = this;
if (me.settedCls) {
me.removeCls(me.settedCls);
}
me.addCls(color);
me.settedCls = color;
me.setValue(val,true);
},
setValue: function(val,take) {
var me = this;
if (!take && me.settedCls) {
me.removeCls(me.settedCls);
}
me.callParent(arguments);
return me;
}
});
Here's a JSFiddle
Overriding per instance will happen in really rare cases and might not be applicable to all properties. In such a case (where I don't have a example at hand) you have a single need for a different behavior and you might consider overriding a setting just per instance. Basically you do such things all times when you apply a config on class creation but most time you just override default values of config properties but you are also able to override properties that references functions. This completely override the implementation and you might allows don't have access to the basetype (if any exist) meaning you cannot use callParent. You might try it with setValue to see that it cannot be applied to a existing chain. But again, you might face some rare cases where this is useful, even when it is just while development and get reimplemented for productive. For such a case you should apply the override after you created the specific by using Ext.override as mentioned above.
Important: You don't have access to the class-instance by calling this if you don't use Ext.override!
If I missed something or something is (no longer) correct, please comment or feel free to edit.
As commented by #Eric
None of these methods allow you to override mixins (such as Ext.form.field.Field). Since mixin functions are copied into classes at the time you define the class, you have to apply your overrides to the target classes directly
The answer by #sra is great and was very helpful to me in gaining a deeper understanding of the override functionality available in Ext, but it does not include the way that I most commonly implement overrides which looks something like this:
Ext.define('my.application.form.field.Text' {
override: 'Ext.form.field.Text'
getValue: function () {
// your custom functionality here
arguments[1] = false;
// callParent can be used if desired, or the method can be
// re-written without reference to the original
this.callParent(arguments)
}
});
I'm still using Ext 5 so I would then load this file in my Application.js and add it to the requires array there which applies the override to the app globally. I think Ext 6 projects include an override folder and simply adding this file to that folder ensures the override is applied.
This is the only way that works for me in ExtJS 7.
Example:
app/desktop/overrides/Toast.js
Ext.define(null, {
override: 'Ext.window.Toast',
show : function () {
this.callParent();
// Your custom code here...
}
});
I recently stumpled over the appProperty within the the Ext.app.Application class and wondered why would I use it. I would require access to App instance anyway to then access a variable that again contains the instance? Maybe I am stupied but for what is this property?
I guess you have a misunderstanding here; The name property just defines a namespace of the Application along with a getter Method for it (getApplication()) but it will not provide you with the current instance of that application unless you call the getter or use the new appProperty.
Lets say you have the following application
Ext.application({
name: 'App',
appProperty: 'instance',
launch: function() {
// some more code
}
});
the you can access this application from any Component by calling either
App.getApplicatio();
or
App.instance
Where the second will be bit faster cause it is no method call and for sure you can define the name of this property. So I guess you see this property is quite useful!
Note that a namespace is always a object in javascript. That is the
reason why you are able to place properties into it.
I need to execute some code both on initialize and render methods, but as I understand, I canot just modfy them directly when using Chaplin - when I define my own initialize method, my routes stop working.
I also tried afterInitialize() but it seems its not meant to be overrided: https://github.com/chaplinjs/chaplin/issues/168#issuecomment-8015915
[...] but as I understand, I canot just modfy them directly when using
Chaplin
You can modify them directly as long you appropriately delegate to the extended prototype.
As you haven't tagged your question javascript or coffeescript, the following are two solutions for each one. First up is javascript. Notice how we must explicitly invoke the extended function.
var View = Chaplin.View.extend({
initialize: function(options) {
// Add code here ..
// The below invokes the initialize function of the
// base Chaplin.View class in the context of
// this class
Chaplin.View.prototype.initialize.call(this, arguments);
// .. or here
}
});
Next is coffeescript, which makes this kind of thing significantly easier.
class View extends Chaplin.View
initialize: ->
// Add code here ..
// The below auto-magically invokes the
// initialize method of the base class
super
// .. or here
I'm using experimenting with .extend() to set up my views and initialise them with. I've found it's convenient to assign config variables to view objects nested deep within a hierarchy.
My problem is that my Views lose their this context. This becomes the ctor object which I asume is the constructor. How can I fix this?
My coffeescript is below. The first class would be nested deep within a tree, the second is at the top level where the application boots up:
# This is a child somewhere deep within a tree of views.
class View extends Backbone.View
initialize: ->
console.log # # returns object ctor
MyView = View.extend({
initialize: ->
# do config stuff then init prototype
App.Views.MyView.prototype.initialize()
})
view = new MyView
Two things:
First, and not as importantly, you can use
class MyView extends View
instead of View.extend. CoffeeScript classes and Backbone classes are interoperable.
Second—and this is the important part—instead of
App.Views.MyView.prototype.initialize()
you should simply use the CoffeeScript keyword
super
That effectively does the same thing, but also ensures that the function is called in the correct context. Bonus: It also passes in all of your function arguments for you.
If you're curious, super here compiles into
initialize.__super__.constructor.apply(this, arguments)
(where __super__ is a reference to the superclass that's set by both CoffeeScript's extends). Read about apply at MDN.
My coffe script isnt so hot but can you call the function sending the view you want to be the value for this in as the first parameter
I suppose in standardish js
var view = null;
MyView = View.extend({
initialize: function() {
// do config stuff then init prototype
App.Views.MyView.prototype.initialize.call(view)
}
})
view = new MyView;
Im not sure what you have access to at that point or the generated js either.
The point being if you have access to what should be the value for this when you call the function you should be able to pass it in.
I would check myself but i don't comprehend coffeescript :)