M, V, C arrays vs require array inside Controller - extjs

What is the Sencha's way of preloading the dependencies?
Inside controller, is it better to put views, stores in arrays like this:
views: ['Full.Path.To.View', 'Full.Path.To.View'],
stores: ['Full.Path.To.Store', 'Full.Path.To.Store']
or just inside requires:
requires: ['Full.Path.To.View', 'Full.Path.To.View', 'Full.Path.To.Store', 'Full.Path.To.Store']
In some cases (when I want Ext.syncRequire()) works only the second option so I wanted your opinion. So, this is being called inside Controller, not inside app.js in Ext.application.
Thank you!
EDIT:
This is my solution and vision of how it should be:
var views = ['MyApp.view.Login.LoginForm', 'MyApp.view.Main.Index'];
var models = ['MyApp.model.Company'];
var stores = ['MyApp.store.Tables'];
var senchaData = ['Ext.field.Text', 'Ext.Button'];
var dependencies = [].concat(views, models, stores, senchaData);
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
requires: dependencies,
config: {
refs: {
loginForm: '#loginForm',
loginButton: '#loginForm #loginButton'
},
control: {
loginButton: {
tap: 'onLogin'
}
}
}...

You have to understand how controller dependencies get resolved by the classmanager because that makes the difference.
Note: Last time I dig into the controller classes was with version ExtJS4.2 so something might have change slightly.
These arrays (models,views,controllers) have some benefits.
One benefit is cleaner code due to the different arrays a second is that the controller can predict the namespace of each class base on the app namespace and the array. You have to know that these arrays get resolved a definition time!
Now these three arrays are nice but the classmanager didn't know them that is why the Ext.app.Controller inject a appropriate hooks for doing so. The hook get triggered when the class get extended and will require all classes found in one of the four array (models,stores,views,controllers). This force the classmanager to load these classes immediately.
Note that the Ext.app.Application is the only one that initializes the controllers, but since ExtJS4.2 it is possible to do it your own with only little effort.
That is all I can say based on your info. If this doesn't help please be more precise in which case loading fails.
Edit
Why not define it this way? It is better to read, isn't it?
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
views: ['Login.LoginForm', 'Main.Index'],
models: ['Company'],
stores: ['Tables'],
requires: ['Ext.field.Text', 'Ext.Button'];
//...
}

Related

EXTJS how to access global variables in store

I'm quite new to Extjs, I'm needing to pass some data to my stores, I mean, I need to fetch some URL from a singleton configuration file, but reading in the Official documentation I am not able to find a require method in the store. So, I wonder how to tell my store to fetch that URL from a configuration file?
I am not sure which version of Extjs you are using. The answer is based on Extjs6 which I am using. We add the singleton (mostly common configs) files in the application(Application.js) level so that the file will be available across the entire app.
For example,
singleton file is 'Some.Globals.configs'
//Application.js
Ext.define('Some.Application', {
extend: 'Ext.app.Application',
requires: [
'Some.Globals.configs'
]
});
Then anywhere in the application, you can access directly as mentioned below.
Some.Globals.configs.respectiveConfig
If you are extending Ext.data.Store you should be able to use requires property
eg.
Ext.define('My.awesome.Store', {
extend: 'Ext.data.Store',
requires: [
'My.global.Config'
]
...
});

How can I run the same setup function on every view?

Many of the views in my application need to be "collapsible". To the user this means that you can click an arrow to collapse or expand the view's contents.
When creating a view I need to be able to easily say, "This view should be collapsible," and then run the appropriate setup code (which essentially means adding the .collapsible class to the view's wrapper and inserting a dom element that looks like this: <div class="toggle"></div>
Suggestions on ways to pull this off seamlessly? I'm currently using Backbone, Backbone.Marionette, and Underscore.
I do this with another application that doesn't use Backbone. In that application every action results in a page refresh, so I just use jQuery to look for all elements with the .collapsible class and do my setup that way.
EDIT:
I'm using Backbone.Marionette.CompositeView for these particular views, if that helps.
I've done similar thing in my project by extracting such functionality into mixins. There're different approaches to implementing mixins in Backbone. Take a look here or here
You can create parent view that extends from Marionettes compositeView and add your common functionallity there, and have your project views extend from this parent view.
var CollapsibleView = Backbone.Marionette.CompositeView.extends({
variable1: 1,
var2: true,
initialize : function() {
// your code here
},
helperfunction : function () {
// other helpful function
}
});
var MySpecificView = CollapsibleView.extends({
mySpecificFunction : function () {
// some specificView functionality
}
});
var myProjectView= new MySpecifcView();
myProjectView.helperfunction(); /// function from the parent
myProjectView.mySpecificFunction(); /// function from the specificView
/// you also have the functionality added on the initialization of the collpasibleView

ExtJS Application Event Woes

EXTJS 4.1
I have run into a bit of a conundrum and would love to hear some other developers input on this scenario regarding ExtJS events and controller methods. I understand this topic has been covered and debated on numerous occasions but I feel that it could use a bit more delving into.
As is standard practice, I define event listeners in my Controller's init() method declaration as follows:
Ext.define("My.controller.Awesome", {
init: function(application){
/** Observe some Views */
this.control({
'my-awesome-view #saveButton':{
click: this.saveMyData
}
});
/** Listen for Events, too! */
this.on({
showAwesomeView: this.showMyAwesomeView
});
/** Application events, what fun! */
this.application.on({
showThatAwesomeView: this.showMyAwesomeView
});
}
Now, as I merrily go about coding some functionality in some other controller, I find myself needing to call showMyAwesomeView in My.controller.Awesome. I can do this in a few different ways...
Ext.define("My.controller.Other", {
/* ... class definition */
someImportant: function(){
// I can do this (Approach #1)
this.application.getController("Awesome").showMyAwesomeView();
// Or I can do this (Approach #2)
this.application.getController("Awesome").fireEvent("showAwesomeView");
// Last but not least, I can do this (Approach #3)
this.application.fireEvent("showThatAwesomeView");
}
});
To me, Approach #3 feels the most 'right'. My problem is that if I haven't instantiated the My.controller.Awesome before, the init() method has not been run yet and therefore there are no listeners established, so the fired event goes off into mystery land never to be heard of again.
I have overloaded Ext.application.getController() to call controller.init() before returning controller, therefore a controller has its init method called as soon as it is loaded (typically as a dependency in another controller). Is this bad?
In order to save on load time (my application is quite large) my controllers and their dependencies are loaded on an as-needed basis. Therefore, the majority of my controllers (and views, and data stores) are not instantiated when my application first boots therefore not init()'ed which makes firing application-wide events quite cumbersome.
I feel like I may be missing something big here, or maybe I just need to bite the bullet and ensure my controllers have been init'd before firing events. I suppose I could also put an absolutely horrific number of event listeners in the main application file and handle init'ing controllers before calling their methods accordingly, but this seems very sloppy and difficult to maintain.
Any input would be greatly appreciated, thank you for your time!
Approach #3 (this.application.fireEvent('showThatAwesomeView')) is a great solution. The use of application events results in controllers that have no assumptions about what other logic may be added or removed from the application related to this event.
Regarding your concern about controllers having been instantiated in time to be correctly bound to events, use of the Ext.app.Application controller will eliminate this. The App controller initializes all specified controllers when the App initializes. You noted a concern about start-up time related to the number of controllers. I have worked on many single page apps that have dozens and even hundreds of controllers in some cases. Keeping any init logic to a minimum should reduce any noticeable slowdown. Minified and combined scripts in place of on-demand loading has worked well to keep app start-up very fast.
Avoiding the getController method is good practice. Application logic tends to be better organized when using application events in place of logic that tightly couples controllers with each other.
Ext.define('UD.controller.c1', {
extend: 'Ext.app.Controller',
refs: [
{
selector: 'viewport',
ref: 'userview'
}
],
init: function() {
console.log("initincontroller!!");
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered:function(){
alert("rendered");
UD.getApplication().fireEvent('myevent');
}
});
Ext.define('UD.controller.c2', {
extend: 'Ext.app.Controller',
refs: [
{
selector: 'viewport',
ref: 'userview'
}
],
init: function() {
console.log("initincontroller!!");
UD.getApplication().on({
myevent : this.doSomething
});
},
doSomething:function(){
alert("controller2");
}
});

MVC paths in Extjs

I have got a ExtJs application (MVC).
So, I define many controllers, models, views and stores.
At now, the structure of my project is not easy.
For example my model:
Ext.define('KP.model.account.AccountList', {
extend: 'Ext.data.Model',
fields: ['parameter', 'string_value']
});
I define my store with model like this:
Ext.define('KP.store.account.AccountList', {
extend: 'Ext.data.Store',
alias: 'store.s_AccountList',
model: 'KP.model.account.AccountList',
......................................
});
If I want to move some .js files, I must rewrite many paths in classes definitions.
So, how can I declare my classes (by alias maybe) and use them more effectively?
It's need, If I move files on files tree.
Thanks!
I believe stores are the only classes that refer to Model classes by their full name. Controllers refer to model classes by their name minus the 'AppName.model' prefix. So a model MyApp.model.User is referred in the controller class as simply User.
If you have a finer grain separation of code than MyApp.model.specific.User is referred by controller as specific.User .
Aliases are used to register xtypes and are also used by the Ext.widget method.

Using a single store on multiple grids and dropdowns with extjs 4.1

I have a store "Contacts". In my application i'm using this in 2 grids and 1 combo box. In Each of these components have varying screen space so i need to define pageSize. What is the best practise for this scenario. Is it better do create 3 different stores. ( I'm using MVC ) . If so, are there naming conventions.
Edit
Currently i load the stores in the onLaunch method in my controller
var partsStore = this.getPartsStore();
partsStore.pageSize = 15;
partsStore.load({
scope: this
});
and reference this store in my view
Ext.define('Mis.view.JobPartList', {
extend: 'Ext.grid.Panel',
alias: 'widget.jobpartlist',
store: 'Parts',
Yes, you should create multiple store instances. Not sure what you mean about naming conventions, the store name should stay the same whether you have 1 or multiple instances.
Based on the code you've posted above, it's not going to work, because by adding it to the class definition you're telling it to explicitly share the store.
Ext.define('Foo', {
// ...
initComponent: function(){
this.store = new MyStoreType();
// ...
this.callParent();
}
});

Resources