apps.jsb3 doesn't include controller definitions - when building - extjs

I used the command sencha create jsb -a http://myserver/myapp/app.html -p apps.jsb3 -v
This created the file apps.jsb3, and when i opened this file, it contained all the definitions for Models and Stores (but, no controllers).
Then i followed with the command ;
sencha build -p apps.jsb3 -v -d . and this created 2 files. app.all.js which is a compressed form of the model, store and the app.js (and it also includes the definition of the controllers of the application as found in the app.js)
ex : ....controllers:["Person","Pers... likewise
and then all-classes.js has all the models, and stores (and again no controllers)
Then i included the following to my app.html file
<script type="text/javascript" src="extjs/ext.js"></script>
<script type="text/javascript" src="app-all.js"></script>
Finally, i copied the app-all.js, all-classes.js, app.html to another folder in the server. and this folder is called SERVERFOLDER2.
Now, when i type http://myserver/SERVERFOLDER2/app.html it says that "NetworkError: 404 Not Found - http://myserver/SERVERFOLDER2/app/controller/Person.js?_dc=1347636548640".
Why is this, and how can i resolve this ?
UPDATE APP.JS
Ext.Loader.setConfig({
enabled: true
});
Ext.require('Ext.container.Viewport' );
Ext.application({
requires: [
'MyApp.Names',
'Ext.window.MessageBox'
],
models: [
'PersonModel',
'SchoolModel'
],
stores: [
'PersonStore',
'SchoolStore' ,
'GenderStore
],
views: [
'UserPanel',
'SchoolViewPanel',
'UpdateSchoolWindow'
],
controllers: [
'SchoolController',
'PersonController',
'UserActionController',
],
name: 'MyApp',
refs:
[{
ref: 'viewport',
selector: 'viewport'
}],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'card',
items: [
{
xtype: 'panel',
items: {
xtype: 'UserPanel'
}
}
]
});
},
userSuccess: function() {
var st = Ext.getStore('PersonStore');
st.on('load', this.onSuccess, this, {
single: true,
delay: 100
});
st.load();
},
onSuccess: function() {
this.getViewport().getLayout().setActiveItem(1);
}
});

The process you describe looks good to me.
The problem you should focus on is why the generated jsb3 file does't include the controller classes. All the steps that follow seem to work correctly, but the application does not fire up in the end because the packaging process does not include your controller class files.
Ext.Loader kicks in and tries to dynamically ('on demand') load the controller class file - the goal here is not to fix the path configuration for Ext.Loader to find the controller class, but rather to make sure the controller classes are included in the jsb3 file from step 1 in the first place.
I assume that your application starts up fine when launching it via http://myserver/myapp/app.html in the non-packaged state (with only ext-dev.js and no ext-all.js, app.all.js or whatsoever).
I further assume that you can observe messages on the console that say something along the lines of:
Synchronously loading 'app.controller.Person'. Consider adding Ext.require() above Ext.onReady
This means that your class dependencies are not configured correctly. The controller class is not picked up as dependency and therefore not pre-loaded before your application starts.
The packaging process (your first step) relies on the dependencies to generate the jsb3 file. It will not pick up dependencies loaded synchronously on demand.
Solution
The goal is to remove any synchronous on-demand loading when you start your application. If you are successful, the packaging process should be fixed as well.
As a quick workaround you could simply Ext.require your controller classes above your Ext.onReady or Ext.application call.
However, controller classes should be automatically added as dependency by the framework. If they are not, then either your configuration is faulty or there it is a bug in ExtJs.

Related

EXTJS: Uncaught ReferenceError: Dexie is not defined at myJavascriptFile.js:18

I am swapping out one IndexedDb wrapper(localForage) for another(Dexie) and I am unable to run the application because the recommended way to integrate it within the ExtJs framework is not working for me. What have I done wrong?
My current version/s of ExtJs:
framework: 6.6.0.258
Cmd: v6.6.0.13
Dexie version is latest
The Dexie documentation recommends that you set up your database like this
var db = new Dexie("MyDatabase");
db.version(1).stores({
myStoreName, "++id, indexOne, indexTwo",
myOtherStoreName, "++id, indexOne, indexTwo",
});
myExtJsFile.js
Ext.define('DataLayer.Inferface', {
extend: 'Ext.Component',
xtype: 'DLInterface',
config: {
stuff...
db: new Dexie("mydatabaseName"),
}
The way that the ExtJs documentation recommends using an external library is to reference it in the app.json file in the js array
app.json
"js": [
{
"path": "${framework.dir}/build/ext-all-rtl-debug.js"
},
{
"path": "dexie.js" //Dexie is located in the same folder as app.json
},
I get a successful build yet when I go to deploy it(run locally) I get the run-time error listed in the title of this question. I am aware that the intellisense in VSCode isn't working all that good, so I didn't really think much of it when I was not appearing to have access to the global Dexie object.
I have tried several different ways, and places to load this library with m=no luck. I would use a CDN, but it is an offline capable app so I really want the library locally. How should I be getting, referencing, and using 3rd party libraries in Ext?
Thanks.
If You use external library in Ext.define, try to include external libraries before extjs libraries (ext-all-rtl-debug.js, app.js etc.).
Another solution - don`t attach remote libraries on class defines - use initialize/initComponent instead. Example:
Ext.define('DataLayer.Inferface', {
extend: 'Ext.Component',
xtype: 'DLInterface',
config: {
stuff...
},
initComponent: function () {
this.db=new Dexie("mydatabaseName");
this.callParent(arguments);
}

Where to store settings in Sencha Touch?

i would like to consolidate the url base for my RESTFul API in a single place in my app built with Sencha Touch. Where is the best place i can put it?
There is a obvious option to store it in localStorage, but is this a good practice ?
When I want to support MVC structure I create file Config.js and put it in application tree in the following place:
in Config.js:
Ext.define('MyApp.config.Config', {
singleton: true,
config: { /** here you can put any objects of your choice that will be accessible globally**/
baseURL : Ext.os.is.Android ? 'http://live_url_here.com' : 'http://localhost/testing_locally',
topBannerUrl : 'http://some_url/banner.png',
anotherGlobalParam : true
},
constructor: function(config) {
this.initConfig(config);
return this;
}
});
Those config parameters will be visible in the whole application.
You may get them:
MyApp.config.Config.getBaseImgURL(); /* returns 'http://some_url/banner.png' */
MyApp.config.Config.getAnotherGlobalParam(); /* returns true */
or set:
MyApp.config.Config.setBaseImgURL('new_url');
MyApp.config.Config.setAnotherGlobalParam(false);
This solution may be especially handy when your project requires many configuration parameters.
I hope it will work for you as well.
Always keep your url base in a seperate file like util.js(utility.js). Your file path should be app > util > Util.js. You can keep your common functions like animateItem, showLoading/hideLoading, custom functions, etc over here so that you can use the same function throughout the app. To load this file in your app do this:
app.js
Ext.application({
name: 'HelloWorld',
requires: [
'HelloWorld.util.Util'
],
view: []
})
For best practices in sencha touch you can see this: Sencha Touch Blog
+1 for Anubis recommendation.
Something like this:
Ext.define('MyApp.Const', {
statics:{
url1:'....',
url2:'....'
}
})
Then you can access your urls with:
MyApp.Const.url1
Of course you must require Const class but you don't need to instantiate it.

Jasmine testing backbone views that use precompiled handlebars templates

I am at a loss here.
I am looking to start adding tests for a site I am working on, using jasmine. I am unable to test any of my views though, because the templates being defined in the initialize functions for my views are pre-compiled handlebars templates that are being saved in an object.
My setup is so:
index.jade gets precompiled on my node server. This jade file had a bunch of
<script id="[name]" type="text/x-handlebars-template">
in it, with the snippets for each view. At the bottom of the index page is a jQuery $.each call:
var templates = {};
$("[type='text/x-handlebars-template']").each(function(index, div){
templates[div.id] = Handlebars.compile(div.innerHTML);
});
That loops through all these script tags, compiles them, and loads them into the templates object. I then save this object as an attribute of my main app model, to pass out to views as needed.
This works well for the site itself, but has proven a blocker for testing. When I try to load my views, they will not initialize as doing so requires the 'templates' object on the main model, with is populated from script tags pulled from the index. But index.html does not exist in my specRunner, short of me copy/pasting all the script tags into the spec runner each time I make a change.
I have no idea what the work-around here is. I'm sure it's something simple and I am too dense to see it, but I have been trying things out and looking up solutions for the better part of five hours, and have nothing to show for it.
I know I can compile the .jade file to .html with grunt, but past that I am unsure how to get the information from the html file to my SpecRunner.
So this was pretty complicated, but I got it working thanks to the magic that is grunt.
I set up grunt to use the grunt-contrib-jade and grunt-contrib-handlebars, which would auto compile my jade include pages to HBS, then compile those HBS files to JS.
jade: {
compile: {
options: {
pretty: true
},
files: [ {
cwd: "views/templates",
src: "**/*.jade",
dest: "spec/hbs",
expand: true,
ext: ".hbs"
} ]
}
},
handlebars: {
compile: {
options: {
namespace: "compTemplates",
},
files: [ {
expand: true,
cwd: 'spec/hbs',
src: '**/*.hbs',
dest: 'spec/helpers',
ext: '.js'
} ]
}
},
Each of these JS files would add their contents to the compTemplates object. These JS files were all pre-loaded into the Jasmine specRunner via Grunt, and the last helper (which I called 'z.js' to make sure it loaded last) included:
var templates = {};
for (var prop in window['compTemplates']) {
var name = prop.split('/')[3];
name = name.split('.')[0];
templates[name] = window['compTemplates'][prop];
}
And voila! I had a templates object available to Jasmine that included all the handlebars templates ready to load into my views!

Launch code before Application creation and requirement

I have question about the best way to implement correctly my code.
I have this in app.js
/*** EXT LOADER ENABLE & PATH ***/
Ext.Loader.setConfig(
{
enabled : true,
application : 'MyApp'
});
Ext.log('--- APPLICATION --- Loading Elasticsearch configuration');
Ext.define('MyApp.configuration.elastic',
{
singleton : true,
...
loadElasticConfiguration: function()
{
// ExtDirect or ajax call in order to set configuration
}
});
MyApp.configuration.elastic.loadElasticConfiguration();
Ext.onReady(function()
{});
Ext.create('MyApp.Application');
This is working well but I do not like to have lots of code is app.js.
Is there a way to "export" the "MyApp.configuration.elastic" code to a specific file and call it. I have tried via Ext.require but others files which needs this config are loaded before ...
If anyone has a clue.
Have a good day !
If you want to use Ext.require you will need to create your application within the Ext.onReady listener:
Ext.require('MyApp.configuration.elastic');
Ext.onReady(function(){
Ext.create('MyApp.Application');
});
Alternatively, this should also work as it will make your application's main class require the config class:
Ext.define('MyApp.Application', {
requires: ['MyApp.configuration.elastic'],
// ...
});

Unable to access NameSpace.app variables with ST2?

I'm using the Sencha Command Line 3 tools with a newly generated Sencha Touch 2 application.
Assuming my app.js file looks like this:
Ext.application({
name: "CA",
event_code: "test123",
launch: function() {
console.log("application launched!");
}
});
My views and object stores depend on generating a URL based on CA.app.event_code equaling "test123";
During development in the browser, everything works fine, CA.app returns the variables I need.
When I compile my application with sencha app build and try to run the minified version in the browser, I get an error like this:
Error evaluating http://localhost:8888/app.js with message: TypeError: Cannot read property 'event_code' of undefined localhost:11
I'm not entirely sure why this is happening or how I can fix it. I am open to any and all ideas or suggestions, any pointers in the right direction will be greatly appreciated.
Ran into the exact same issue. You have no access to the namespaced app within the views... really sucks that they let you in development and not when built. Anyway, I got around it by adding a static helper class and using that all over my app:
In /app/util/Helper.js:
Ext.define('MyApp.util.Helper', {
singleton: true,
alternateClassName: 'Helper',
config: {
foo: "bar",
bat: "baz"
},
staticFunction: function() {
// whatever you need to do...
}
});
Then in your view or controller:
Ext.define('MyApp.view.SomeView', {
...
requires: ['Events.util.Helper'],
...
someViewFunction: function() {
var someValue = Helper.staticFunction();
// and you can use Helper.foo or Helper.bat in here
}
});
For reference, here's some documentation on Sencha Singletons. And one important note: make sure that your Helper singleton is in it's own file! If it's small, you may be inclined to put it at the bottom of your app.js, and things will work at first, and the build process will work, but the code will not. Don't worry, the build process puts all of your JS code in one big, compressed file anyway.

Resources