Where to store settings in Sencha Touch? - extjs

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.

Related

Loading relative templateUrl

I've been trying to find the best way to create a modular, scalable angular application. I really like the structure of projects like angular-boilerplate, angular-app, where all the related files are grouped together by feature for partials and directives.
project
|-- partial
| |-- partial.js
| |-- partial.html
| |-- partial.css
| |-- partial.spec.js
However, in all these examples, the template URL is loaded relative to the base url, not relative to the current file:
angular.module('account', [])
.config(function($stateProvider) {
$stateProvider.state('account', {
url: '/account',
templateUrl: 'main/account/account.tpl.html', // this is not very modular
controller: 'AccountCtrl',
});
})
This is not very modular, and could become difficult to maintain in large projects. I would need to remember to change the templateUrl path every time I moved any of these modules. It would be nice if there was some way to load the template relative to the current file like:
templateUrl: './account.tpl.html'
Is there any way to do something like this in angular?
The best way to do this now is using a module loader like browserify, webpack, or typescript. There are plenty of others as well. Since requires can be made from the relative location of the file, and the added bonus of being able to import templates via transforms or loaders like partialify, you don't even have to use template urls anymore. Just simply inline the Template via a require.
My old answered is still available below:
I wrote a post on exactly this subject and spoke on it at our local Angular Meetup. Most of us are now using it in production.
It is quite simple as long as your file structure is represented effectively in your modules. Here is a quick preview of the solution. Full article link follows.
var module = angular.module('myApp.things', []);
var all = angular.module('myApp.things.all', [
'myApp.things',
'things.someThing',
'things.someOtherThing',
'things.someOtherOtherThing',
]);
module.paths = {
root: '/path/to/this/thing/',
partials: '/path/to/this/thing/partials/',
sub: '/path/to/this/thing/sub/',
};
module.constant('THINGS_ROOT', module.paths.root);
module.constant('THINGS_PARTIALS', module.paths.partials);
module.constant('THINGS_SUB', module.paths.sub);
module.config(function(stateHelperProvider, THINGS_PARTIALS) {
stateHelperProvider.setNestedState({
name: 'things',
url: '/things',
templateUrl: THINGS_PARTIALS + 'things.html',
});
});
And then any sub modules or "relative" modules look like this:
var module = angular.module('things.someThing', ['myApp.things']);
var parent = angular.module('myApp.things');
module.paths = {
root: parent.paths.sub + '/someThing/',
sub: parent.paths.sub + '/someThing/sub/',
partials: parent.paths.sub + '/someThing/module/partials/',
};
module.constant('SOMETHING_ROOT', module.paths.root);
module.constant('SOMETHING_PARTIALS', module.paths.partials);
module.constant('SOMETHING_SUB', module.paths.sub);
module.config(function(stateHelperProvider, SOMETHING_PARTIALS) {
stateHelperProvider.setNestedState({
name: 'things.someThing',
url: "/someThing",
templateUrl: SOMETHING_PARTIALS + 'someThing.html',
});
});
Hope this helps!
Full Article: Relative AngularJS Modules
Cheers!
I think you'll eventually find that maintaining the paths relative to the js file will be harder, if even possible. When it comes time to ship, you are most likely going to want to concatenate all of your javascript files to one file, in which case you are going to want the templates to be relative to the baseUrl. Also, if you are fetching the templates via ajax, which Angular does by default unless you pre-package them in the $templateCache, you are definitely going to want them relative to the baseUrl, so the server knows where to find them once your js file has already been sent to the browser.
Perhaps the reason that you don't like having them relative to the baseUrl in development is because you aren't running a server locally? If that's the case, I would change that. It will make your life much easier, especially if you are going to work with routes. I would check out Grunt, it has a very simple server that you can run locally to mimic a production setup called Grunt Connect. You could also checkout a project like Yeoman, which provides a pre-packaged front end development environment using Grunt, so you don't have to spend a lot of time getting setup. The Angular Seed project is a good example of a Grunt setup for local development as well.
I've been chewing on this issue for a while now. I use gulp to package up my templates for production, but I was struggling to find a solution that I was happy with for development.
This is where I ended up. The snippet below allows any url to be rewired as you see fit.
angular.module('rm').config(function($httpProvider) {
//this map can be defined however you like
//one option is to loop through script tags and create it automatically
var templateMap = {
"relative.tpl.html":"/full/path/to/relative.tpl.html",
etc...
};
//register an http interceptor to transform your template urls
$httpProvider.interceptors.push(function () {
return {
'request': function (config) {
var url = config.url;
config.url = templateMap[url] || url;
return config;
}
};
});
});
Currenly it is possible to do what you want using systemJs modules loader.
import usersTemplate from './users.tpl';
var directive = {
templateUrl: usersTemplate.name
}
You can check good example here https://github.com/swimlane-contrib/angular1-systemjs-seed
I had been using templateUrl: './templateFile.tpl.html but updated something and it broke. So I threw this in there.
I've been using this in my Gruntfile.js html2js object:
html2js: {
/**
* These are the templates from `src/app`.
*/
app: {
options: {
base: '<%= conf.app %>',
rename: function( templateName ) {
return templateName.substr( templateName.lastIndexOf('/') );
}
},
src: [ '<%= conf.app %>/**/{,*/}<%= conf.templatePattern %>' ],
dest: '.tmp/templates/templates-app.js'
}
}
I know this can lead to conflicts, but that is a smaller problem to me than having to edit /path/to/modules/widgets/wigdetName/widgetTemplate.tpl.html in every file, every time, I include it in another project.

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.

Backbone collection/model best practice

In my application we are using RequireJs and Backbone
So a typical model might look like the following in a separate file so we can attempt to modularize this application better:
define([
'Require statements here if needed'
],
function() {
var toDo = Backbone.Model.extend({
// Model Service Url
url: function () {
var base = 'apps/dashboard/todo';
return (this.isNew()) ? base : base + "/" + this.id;
},
// Other functions here
});
return toDo;
});
Right now we keep each model and collection in its own file and return the Model/Collection as above. The bigger the application gets the harder it is to keep the files and naming convention straight. I would like to combine similar collections/models together into 1 file and maintain the modularity.
What is a good way to achieve this? Or should I stick with them in separate files and get a better naming convention? If so, what do you use for your naming convention between similar Collections/Models?
This is the way I structure my application :
I have a javascript path, which I'm minifying on demand by the server when client access "/javascript", so I have only one script line in my index.html :
<script src='/javascript'></script>
My directory structure of /javascript is the following :
application.js
router.js
lib/
lib/jquery.js
lib/underscore.js
lib/backbone.js
lib/require.js
lib/other_libraries.js
views/
views/navigation.js
views/overlay.js
views/content.js
views/page
views/page/constructor.js
views/page/elements
views/page/elements/constructor.js
views/page/elements/table.js
views/page/elements/form.js
views/page/elements/actions.js
collections/
collections/paginated.js
All those files are minified and loaded from client in the first request. By doing this I have a lot of my code already loaded in my browser before the application makes any requests with RequireJS.
On my server I have a directory, which is also public, but is for dynamic javascript loading and templates ( it is accessed by demand from the application at any given time ). The directory looks like this :
dynamic/
dynamic/javascript
dynamic/javascript/pages
dynamic/javascript/pages/articles.js
dynamic/templates
dynamic/templates/pages
dynamic/templates/pages/articles.hb
dynamic/templates/pages/items.hb
When my server requests "/templates/pages/articles.hb" the server returns JSON object which looks like this :
{ html : "<div class='page' id='articles'>blah blah blah</div>", javascript : "javascript/pages/articles.js" }
And when my client app receives "javascript" property in the returned JSON object it triggers a RequireJS request
if ( typeof json.javascript === string ) {
require([ json.javascript ], function(constructor) {
window.app.page = new constructor();
});
}
In the dynamic/javascript/pages/articles.js I have something like :
define(function() {
var Model = Backbone.Model.extend({});
// Collections.Paginated is in fact the Collection defined by /javascript/collection/paginated.js
// it is already loaded via the initial javascript loading
var Collection = Collections.Paginated.extend({
url : '/api/articles'
});
// Views.Page is in fact the View defined by /javascript/views/page/constructor.js
// it is also already loaded via the initial javascript loading
var articles = Views.Page.extend({
collection : Collection,
initialize: function(options) {
this.collection = new Collection();
});
});
return articles;
});
Pretty much that's it. I have minimum requests with RequireJS, because every time you hit require('something.js') it makes a request to the server, which is not good for your application speed.
So the exact answer of your question ( in my opinion ) is : You should make your initial loaded files separated as much as possible, but later loaded files with requireJS should be as small as possible to save traffic.

How to use JSON without json file?

I need to use dynamically JSON with data.TreeStore.
With this component, there is proxy "config", it need a path to JSON file.
My problem is, i can't write Json file in my application.
I would know, if i can generated JSON dynamically and pass it to url config into proxy?
For example :
Var trStore = Ext.create('Ext.Data.TreeStore',{
... // config
proxy {
type : 'ajax',
url : { id : 'id0', task :'task0', value : 'val0', ..... }
}
});
My URL is not a file url but is JSON generated with my own method !
How to build JSON for use it with TreeStore and without make file !?
I hope you understand my problem :)
Thanks a lot to help !
Your example looks like you want to pass static "inline data" to the TreeStore.
As far as I can see this is not possible with a bare TreeStore, since it does not have a data config option as the "normal" Store has. However, it is possible with a Treepanel.
You can pass your inline data to the TreeStore using the root config option of the Treepanel (not the TreeStore). It works in a very similar manner as the data config option of a "normal" Store:
Ext.create('Ext.tree.Panel', {
root: { id : 'id0', task :'task0', value : 'val0', children: [...], ... }
// ...
});
There are two caveats related to this:
The beta3 docs say root is boolean, that's wrong.
Because of a bug in beta3 you cannot use this together with rootVisible: false.
Remember that a "json file" is really just a text string, so you can generate that with PHP or your preferred server software.
For the url in the proxy, simply put in the url you use to run that function. Eg in my web app I have http://example.org/controller/getTree?output=json
This runs the getTree() function on my controller, and the function knows to return json.

Resources