Global config in titanium mobile mobile app - mobile

I am new to titanium mobile and I am a bit stuck. I have an app.js file and services.js file which sends some HTTP requests to an URI my issue is I want to create a global variable within the app.js which the services.js can use and other files as and when they get included.
What is the best way to do this ?
In PHP you would have a config file but how do you do in titanium mobile ?

If you are using services.js from a Ti.include, it will have access to everything declared in app.js. You usually create your own namespace and put 'global' variables in that:
var myapp = {};
myapp.myGlobalVariable = 'something';
Here is a more complete example from Aaron Saunders.

You could do it 3 ways, depending on how long you'll need the variable. If it is needed outside of the session scope (so later on) you could store it either in an Property or SQLite Database
The last option, which is a session-only option is a regular JavaScript variable. Like Jeff has pointed out (copying his code here)
var myapp = {};
myapp.myGlobalVariable = 'something';
Declaring this myapp should be done before any function opens. So in the global scope.

Related

How to Insert dynamic script in Angular based on environment variable in Nodejs

I have a script at the bottom of the index.html file within an Angular app that I want to change based on an environment variable in Node. I want to use one public api key with staging and another with production.
I use the same grunt build for both staging and production, so I don't know if dynamically changing the constants on build as suggested here is the best solution.
Any thoughts on how to handle this?
When environment variable is NODE_ENV=production, insert this:
<script>
Stripe.setPublishableKey('pk_live_NN4j94VX3mtz2wJtIO3bmH');
</script>
When environment variable is NODE_ENV=staging, insert this:
<script>
Stripe.setPublishableKey('pk_test_LgtEvbZwjC2GaKQYE3I6NnzuA');
</script>
I would use grunt-ng-constant to manage your angular environment variables and then initialize Stripe inside of your angular app.config() function rather than your document.
My preference is to manage Stripe inside the angular boot process using angular-stripe. This also may make your life easier if you configure your application with both keys. Here's some example code from one of my applications.
var $app = angular.module('app', ['angular-stripe']);
$app.constant('devDomains', ['localhost', 'staging.mydomain.com']);
$app.constant('stripePubKeyStaging', 'STRIPE_PUB_KEY_HERE');
$app.constant('stripePubKey', 'STRIPE_PUB_KEY_HERE');
$app.config(function(devDomains, stripePubKey, stripePubKeyStaging, stripeProvider) {
if (devDomains.indexOf(document.location.hostname) !== -1 || document.location.search.indexOf('stripe-test-key') !== -1) {
// if you're running your angular app on local or staging, use the test key. Additionally
// if you load your page with ?stripe-test-key you can force your production app
// to use the test key in order to debug something on live if you'd like.
stripeProvider.setPublishableKey(stripePubKeyStaging);
} else {
stripeProvider.setPublishableKey(stripePubKey);
}
});

Is it possible to define an angularjs constant inside a controller or config block?

I am trying to set up some app wide constants from a http endpoint. I don't want (or need ) to do it via the manual bootstrap way (ala this ). Ideally I want to load the constants in after the user has signed in. So I assume I need to define the constants somewhere I can run some code (and use $http). But whenever I define a constant inside a controller or a config block, the constant gives an unknown provider error when I pass it into another module. As soon as I move the definition outside of the controller it works. So for example, if I have ...
var app = angular.module('testApp',[]);
app.constant('test', 'test value');
then I can pass that into another module's controller like this:
var app2 = angular.module('anotherModule',[testApp]);
app2.controller('TestCtrl', ['test',
function(test) {
console.log(test)`
}..
and this will output 'test value' as you would expect. But if the constant is defined inside a code block then it seems it doesn't register as a provider. So, for example:
var app = angular.module('testApp',[]);
app.controller('firstCtrl',function(){
app.constant('test', 'test value');
}
If I run a page with that controller, the constant seems to register (in the sense that it is listed inside the _invokeQueue array on the testApp module) but the injector service doesn't have a provider for it and I get an unknown provider method for it on anotherModule.
I initially felt that a factory or service was overkill for what I was trying to do but maybe that is the way I should go. But I would also love to understand why a constant defined like this isn't injectable.
Easiest way to load constants for HTML5 app:
add the following line into head section:
< script src="service/constants.js">
create web api / wcf / java REST service method with signature "service/constants.js"
in that method return "window.constants = {...}".
replace "..." with actual key:value pairs read from database.

How to dynamically add a decorator after angularjs bootstrap

Is there a way in angularjs to dynamically (after angular bootstrap) to enhance a service by proxying it using the decorator pattern.
In the following plunker example I can overload my default search service (google based) but this relies on the declaration/addition of the overloading module (the yahoo one) using the app.requires dependencies of the application before the angular app is bootstrapped. This does not work once the angular application is already bootstrapped, as demoed when clicking on duckduckgo button.
I must do the decoration dynamically by injecting javascript code into the application in a migration scenario where the webapp has to be embed into a java client (using JavaFX webview) and where some actions (the ones introduced dynamically) have to replace standard behavior of the webapp.
I have tried to use some technics described by Ifeanyi Isitor in his blog without success.
One possible method might be to get a hold of the injector of the currently running application (as described at the bottom of the documentation for angular.injector). This is done by using angular.element on an element of the currently running app to get its injector().
To easily get a hold of this element, if you were to give the tag on which you've declared your app the id of mcfoggy-application-search:
<div ng-app="mcfoggy.application.search" id="mcfoggy-application-search">...</div>
... you could .getElementById() and clobber the originally defined service a bit like this (as per your plunkr):
console.info('interpreting duckduckGoService.js');
var appElement = document.getElementById('mcfoggy-application-search');
var injector = angular.element(appElement).injector();
injector.invoke(['SearchService', '$log', function(SearchService, $log) {
// replace search in SearchService
SearchService.search = function(terms) {
var duckduckGoSearch = 'https://duckduckgo.com/?q=' + encodeURI(terms);
$log.info("search called: " + duckduckGoSearch);
// $window.location.href = duckduckGoSearch;
};
}]);
Maybe not as pretty as decoration, but it seems to work!
Updated plnkr

Angular translate extend existing translations

I am trying to have external modules change my $translateProvider.translation on the main module. see this as a "tranlation plugin" for my app.
it seems like changing translations from the $translate service is not possible.
mymodule.service('MyService', function ($translateProvider) {
var lib = function () {
//EDITED FOR BREVITY
this._registerTranslations = function (ctrl) {
if (!ctrl.i18n) return;
for (var name in ctrl.i18n) {
/////////////////////////////
// THIS IS THE PLACE, OBVIOUSLY PROVIDER IS NOT AVAILABLE!!!!
$translateProvider.translations(name, ctrl.i18n[name]);
//////////////////////////////
}
};
//EDITED FOR BREVITY
};
return new lib();
});
anyone with a bright idea?
So, to answer your question: there's no way to extend existing translations during runtime with $translate service without using asynchronous loading. I wonder why you want to do that anyway, because adding translations in such a way means that they are already there (otherwise you would obviously use asynchronous loading).
Have a look at the Asynchronous loading page. You can create a factory that will load a translation from wherever you want.
I created an Angular constant to hold new translations. If I want to add a new translation, I add it to the constant. Then in my custom loader, I first check the constant to see if the translation exists (either a new one, or an updated one). If so, I load it from the constant. If not, I load it from a .json file (or wherever you load your initial translations from). Use $translate.refresh() to force translations to be reloaded and reevaluated.
Demo here
The demo is pretty simple. You would need to do a little more work if you wanted to just change a subset of the translations, but you get the general idea.
From the AngularJS docs (https://docs.angularjs.org/guide/providers):
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.
Providers are to be used with the application's .config function. $translateProvider for configuration, $translate for other services and controllers.

angular.bootstrap to run multiple angular apps

This is NOT a Twitter Bootstrap question...
I have a use case that requires the loading of separate angular applications.
Based on several stack overflow questions and this google thread, it's doable. However, I can't get it to work.
Looking at the documentation:
http://docs.angularjs.org/api/angular.bootstrap
It looks like you need to provide the element (how to get a handle on the element?), and then how to tie it back to config, controllers, etc. And how would this work with routes? Seems if one app uses otherwise and the other uses otherwise, the second would just override the first?
Thanks!
to grab references to your app(s), you can do something along the lines of:
var first = document.getElementById('firstapp-id');
var second = document.getElementById('secondapp-id');
angular.bootstrap(angular.element(first), ['firstapp']);
angular.bootstrap(angular.element(second), ['secondapp']);
where 'firstapp' and 'secondapp' are module/app names, and 'firstapp-id' and 'secondapp-id' are the id's of the container div's for each app (or your favorite DOM element). just define your apps in the usual manner:
var firstapp = angular.module('firstapp', []);
var secondapp = angular.module('secondapp', []);

Resources