For what do I use the appProperty property? - extjs

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.

Related

Call translation service from a callback registered in an app.config section

I'm relatively new to AngularJS and the problem I'm facing is one of those "I want to inject a Service into an app.config" type of scenarios, which I realise cannot be done. (I'm comfortable with the different between Service and Provider, and why a Service cannot be injected into a .config.)
What I am trying to accomplish is to use angular-schema-form together with angular-translate such that field titles in generated forms are translated.
There is an issue where someone asks how to do this, and the advice given is to take advantage of angular-schema-form's postProcess, which is a property of the Provider. This callback gives you the form object before it is rendered, giving you the opportunity to manipulate it with user code. Therefore translation could be done within here.
The postProcess method is called on the Provider, so it is done within an app.config:
app.config(function(schemaFormProvider, $translateProvider) {
schemaFormProvider.postProcess(function(form){
// within here I can inspect the form object, find all
// properties whose key is "title", and then perform
// language translation on their values.
So, that is apparently the place where I have an opportunity to manipulate control titles and so on.
Over to the angular-translate library, for me to 'manually' translate strings, I can use the $translate service. This provides both synchronous and asynchronous methods to translate a given key string. The synchronous one is $translate.instant(key).
To glue these two together, what I have tried so far (which does work) is to create a 'bridge' method like this:
var app = angular.module('myApplicationName', ['schemaForm', 'pascalprecht.translate']);
....
app.config(function(schemaFormProvider, $translateProvider) {
schemaFormProvider.postProcess(function(form){
// ... code here which iterates over properties
// and finds all control titles ...
key = app.myTranslate(key);
// ....
}
....
});
app.myTranslate = function (key) {
var service = angular.injector(['ng', 'myApplicationName']).get("$translate");
return service.instant(key);
}
This does work, but it seems ugly and unsafe (as presumably there's no guarantee $translate is ready when the callback is first invoked) and the calls to angular.injector(['ng', 'myApplicationName']).get... are presumably expensive.
Is there a better way, or is this the only way I'm going to get it done, considering the constraints of the libraries I'm working with?
I have also considered an alternative approach altogether, which would be to instead perform the translations on the schema or form objects before they are processed by angular-schema-form. This could be done from within Controllers, eliminating the problem of accessing the $translate service. I may end up going down that route, but it would still be nice to understand the best solution for the above scenario.

Change data between controllers with service

When I use this it works:`
angular.module('app').service('DataService', function() {
return {theme: "amelia"}
});
But when I use this, there is no update? Can you tell me the difference?
angular.module('app').service('DataService', function() {
return {
theme: function() {
return {theme: "amelia"}
}
};
});
Controller
$scope.settings = DataService.theme();
Jade
select.form-control(ng-model="settings.theme", ng-options="theme for theme in themes")
Is it possible to get the second way working? Because I will share more data then one Object!
Thank you!
The first version of the code calls the function once to instantiate the service. After that, because services are singletons in angular the function isn't called again, but rather the return value (a "static" object) is accessed in every controller that uses the service after that.
The second version, each controller you inject the service into calls the theme function, which instantiates a brand new object each time. You have now effectively mitigated the fact that the service is a singleton. This is why data will not be shared with the second set of code.
If you put a break point on the function call in each case and run your code you should see the first version called once while the second version will be called many times.
"Get It Working"...
You can't really make it work with a function call but if you need to share multiple data objects there isn't any reason not to nest them. You could very easily do something like:
angular.module('app').service('DataService', function() {
return {
dataObjects: [
{"type":"theme", "theme":"amelia"},
{"type":"user", "id":123, "name":"ABC"}
]};
});
In the example I added a second object which is a user object to make shared "dataObjects" array. To find a specific object in the "dataObjects" array, you could loop till you find the correct type ("theme", for example). If necessary, you could even nest one level deeper if you needed the objects to be pristine (without the added type attribute).
Hope that helps!
It should be theme: function().... inside your service. Replace "=" with ":".

Singletons Ext JS (4.2.1) and Stores

How do you implement a Store to be a singleton?
In Architect my store has a property checkbox that adds the property
singleton: true,
If I add that then reload the application it fails to load (I can give more details if required about error)
Uncaught TypeError: object is not a function VM5238:3
(anonymous function) VM5238:3
Ext.ClassManager.instantiate ext-all-debug.js:5485
(anonymous function) ext-all-debug.js:2109
Ext.define.getStore
If I then remove that property it loads fine, but where I use Ext.getStore("MyStore") then the stores that are returned contain different data depending on where I'm using the store. I have a single controller where I use the class name inside the getStore method and this is used in a couple of functions inside that one controller.
Also there does not appear to be any documentation about the singleton property in the docs. If I look at Ext.data.Store there is no singleton.
I recommend you to do it the ExtJS way for handling stores and store instances...
Use the storeId along with the Ext.StoreManager. Note that each storeId need to be unique and as soon as you create a instance of a store it will register itself into the Ext.StoreManager with its storeId. You can get a store by calling the lookup('storeId') on the Ext.StoreManager. And yes you can do that from anywhere in your code.
For example all Ext.Components that mixin Ext.util.Binable (which are most (all) native components that bind a store) will be fine with the storeId string assigned to the store cfg property. The Binable mixin will internally lookup it from the StoreManager. If you need to do it yourself
//...
store: Ext.StoreMgr.lookup('storeId') || Ext.create('YourStoreClassname')
//...

Best practice for overriding classes / properties in ExtJS?

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...
}
});

Ext JS: what is xtype good for?

I see there are lot's of examples in Ext JS where instead of actually creating Ext JS objects, an object literal with an xtype property is passed in.
What is this good for? Where is the performance gain (if that's the reason) if the object is going to be created anyway?
xtype is a shorthand way to identify particular components: panel = Ext.Panel, textfield = Ext.form.TextField, etc. When you create a page or a form, you may use these xtypes rather than instantiate objects. For example,
items: [{
xtype: 'textfield',
autoWidth: true,
fieldLabel: 'something'
}]
Moreover, creating pages in this manner allows Ext JS to render lazily the page. This is where you see a "performance gain." Instead of creating a large number of components when the app loads, Ext JS renders components when the user needs to see them. Not a big deal if you have one page, but if you exploit tabs or an accordion, many pages are initially hidden and therefore the app will load more quickly.
Furthermore, you may create and register new components creating xtypes of your choosing. Ext JS will similarly render your components lazily.
You may also retrieve components by ID. Since your component (as well as the Ext JS components) may provide a bunch of nice behavior, it is sometimes convenient to search for and retrieve a component rather than a simple DOM element or node.
In short, xtypes identify components and components are a key aspect of Ext JS.
I'm new to Sencha/Ext JS but I think at this point the odd notion of having a shorthand definition identifier string for only UI components must be to satisfy legacy users.
Look at the "List of xtypes" here: http://docs.sencha.com/touch/2-0/#!/guide/components
Is there any good reason to use a similar-but-not-quite-the-same string identifier as the "class" name as the shorthand definition identifier? I don't think so.
Check the following sample of some xtype to class name mappings for Sencha touch:
video - Ext.Video Ok this sort of makes sense - lowercase version of 'class' name
carousel - Ext.carousel.Carousel Same pattern here
carouselindicator - Ext.carousel.Indicator Um, ok - we'll include a package too
navigationview - Ext.navigation.View And again here
datepicker - Ext.picker.Date Ok, wtf?
Some of the arguments above for xtype were that it allowed deferred instantiation of components. I think that is completely irrelevant - what allows deferred instantiation is the fact that Sencha/Ext JS supports the specification of a string identifier in place of an instantiated component in a view hierarchy.
The mapping of a particular string to a particular component that might be instantiated later is completely arbitrary - and in the case of Sencha/Ext JS, unfortunately silly (see examples above).
At least just follow a sensible pattern - for example why couldn't a Ext.Label have an "xtype" of Label? Too simple?
In reality I know why - it's because they made xtype names that read well - there are many repeated class names that wouldn't work (Ext.Panel and Ext.tab.Panel), and pickerDate would just sound stupid.
But I still don't like it - it's an odd little inconsistent shortcut that obfuscates more than it helps.
I asked the same question as Joe, but I found the answer. If you use xtype, one approach is to also specify an itemId in the same object:
{
itemId: 'myObject',
xtype: 'myClass'
...
}
Then you can find it with getComponent() as in
this.getComponent('myObject');
If you declare a class and give it an xtype, you can query it later with Ext.ComponentQuery.query()
For example:
Ext.create('MyApp.view.MyButton', {
xtype: 'mybutton',
.....
});
Later in your code, if you do:
var buttonArray = Ext.ComponentQuery.query('mybutton');
then buttonArray will contain an array of components of that class type. If you create components inline, your component query will be more complex.
Another advantage of xtypes is that if you move your classes around (let's say, you add another subdirectory under "view": MyApp.view.button.MyButton), then your component queries can still remain the same, since your xtype doesn't change. Once your project gets large, you will start creating subdirectories and moving classes around.
An xtype is simply a name given to represent a class. It is a
definition object which don't need to be instantiated when used in
any part of application.
While registering a xtype, we simply use this syntax: Ext.reg(<xtype name>,<classname>). But, we don't use the new keyword with the class name because the Component Mgr will automatically create instance of this class only if needed eg. in response to an event like click.
We don't need to get an instance manually because after registering an xtype, the 'Component Mgr' will automatically create an instance for the class represtented by that xtype only if it is used anywhere in the application or it simply don't instantiate that class if not used elsewhere. Component Mgr runs this code:
create : function(config, defaultType){
return new types[config.xtype || defaultType](config);
}
xtype don't instantiate the class when Ext.Ready runs. But, new Ext.Container() will create all instances when Ext.Ready runs. So, using xtype is intelligent for large applications to get rid of garbage objects.

Resources