I have a main app:
var mainApp = angular.module('mainApp', ['secondApp'])
.constant('config', {
key: "mainKey"
});
And the second app looks like this:
var secondApp = angular.module('secondApp', [])
.constant('config', {
key: "secondKey"
});
When I am injecting config into a directive in the second app:
secondApp.directive("ngTest", function (config) {
});
config is being initialized from the main app config. What I am doing wrong here? When I name a constant differently and injecting with the different name it works fine.
var secondApp = angular.module('secondApp', [])
.constant('secondConfig', {
key: "secondKey"
});
secondApp.directive("ngTest", function (secondConfig) {
});
Version is: AngularJS v1.5.7
AngularJs 1 not does not handle namespace collisions.
So if you are using two module in one APP having same named
Services
Factory
Constants
So according to me best to overcome this problem is:
Just give some prefix to your variable
Like::
var mainApp = angular.module('mainApp', ['secondApp'])
.constant('mainApp_config', {
key: "mainKey"
});
var secondApp = angular.module('secondApp', [])
.constant('secondApp_config', {
key: "secondKey"
});
I know this is not a solution which may you are looking...
this is only way I know i can suggest to you.
Related
I have an AngularJS application, which is supposed to call several Spring-based REST API's, url of which would be dynamic based on the environment.
Like if I am running on dev environment, REST URL would be localhost:7777/..
If on production, it would be productionserver:7777/....
Now I have to provide these API URLs to Angular.
What is the best way to configure these REST URLs at run time in my AngularJS application?
You could place all of your api configuration into a single json file named for example config.json, and then before application is bootstrapped you can fetch that data and make a constant out of it and after inject it anywhere you need, something like the following:
Lets say config.json contains these values:
{
"ApiUrls": {
"ApiUrl1": "value1",
"ApiUrl2": "value2",
"ApiUrl3": "value3"
}
}
Injecting configuration api urls before bootstrapping:
(function () {
fetchData().then(bootstrapApp);
function fetchData() {
var initInjector = angular.injector(["ng"]);
var $http = initInjector.get("$http");
return $http.get("config.json").then(function (response) {
app.constant("ApiConfiguration", response.data.ApiUrls);
}, function (errorResponse) {
alert(errorResponse);
// Handle error case
});
}
function bootstrapApp() {
angular.element(document).ready(function () {
angular.bootstrap(document, ["app"]);
});
}
}());
and for example your service:
app.factory('factory', factory);
factory.$inject = ['ApiConfiguration'];
function factory(ApiConfiguration){
var serviceFactory = {
ApiUrl1: ApiConfiguration.ApiUrl1
}
return serviceFactory;
}
This way you can set your values inside the config.json file as per enviroment. Locally it will be localhost:7777/.., in production it will be productionserver:7777/... etc..
Create Service for rest urls or REST Data:-
(function () {
var injectParams = ['$location'];
var service = function ($location) {
var vm = this;
vm.baseUrl = 'http://' + $location.host() +':'+$location.port() + '/api/v1/';
return vm;
};
//bootstrapping
service.$inject = injectParams;
angular.module('showdown').service('restURL', service);
}());
Depending on your setup, you may want to inject your URLs via ng-init. Just make sure to JS and HTML escape the string, if necessary.
So your HTML would look something like this:
<div ng-app="myApp" ng-init="
myUrl='${myUrl?html?js_string}';
myUrl2='${myUrl2?html?js_string}';">
And your Javascript would look something like this:
angular.controller("myApp", () => ($scope) => {
$scope.myUrl; //url is here
});
Create a const in ur app like SERVER-ENV and write a build task to change the value of this constant based on the server environment.
Now you can create URL using this const e.g. SERVER-ENV + "";
This task can be automated with gulp or grunt.
currently i provide my application with a constant called "config" to inject some specific application-wide configuration like the API endpoint URL and so on.
This works like expected for my main module "app" in the configuration section.
app.config(['config', function(config) {
console.log(config.api); // http://api.endpoint.com
}];
The problem is, that i have a separate module like "app.auth" where i wish you configure it with some values from this global constant, but there i get an error, that the config is unknown.
How i can solve this? Inject a service in the configuration area isn't a solution because AngularJS don't provide the services on the configuration block.
Thank you in advance.
First off you answer your question about why 'config' is not available to your app.
Is your app set as a dependency of 'app.auth'?
var app = angular.module('myApp', ['ngResource']);
var authApp = angular.module('myApp.auth', ['myApp']);
Secondly using a constant to set multiple values is a poor use of constant, that would be a great job for a provider. Here is an example:
module.provider('GlobalConfig', function ($resourceProvider) {
var valOne = 'Some Default';
this.setOne = function(value) {
valOne = value;
};
var valTwo = 'Another Default';
this.setTwo = function(value) {
valTwo = value;
};
this.$get = function($resource) {
return {
getOne: function() {
return valOne;
},
getTwo: function() {
return valTwo;
}
};
};
});
From a .config the provider above can be injected by using 'GlobalConfigProvider' and only the setters would be available. Then for directives and services 'GlobalConfig' can be injected and only the getters would be available.
I need to load a config file (JSON format) upon my AngularJS app startup in order to load few parameters which will be used in all api calls. So I was wondering if it is possible to do so in AngularJS and if yes where / when I shall be loading the config file?
Note:
- I will need to save the config file parameters in a service, so I will need to load the json file content before any controller is loaded but with service units available
- Using an external json file is a must in my case here as the app client need to be able to update the app configuration easily from external file without the need to go through the app sources.
EDITED
It sounds like what you are trying to do is configure a service with parameters. In order to load the external config file asynchronously, you will have to bootstrap the angular application yourself inside of a data load complete callback instead of using the automatic boostrapping.
Consider this example for a service definition that does not actually have the service URL defined (this would be something like contact-service.js):
angular.module('myApp').provider('contactsService', function () {
var options = {
svcUrl: null,
apiKey: null,
};
this.config = function (opt) {
angular.extend(options, opt);
};
this.$get = ['$http', function ($http) {
if(!options.svcUrl || !options.apiKey) {
throw new Error('Service URL and API Key must be configured.');
}
function onContactsLoadComplete(data) {
svc.contacts = data.contacts;
svc.isAdmin = data.isAdmin || false;
}
var svc = {
isAdmin: false,
contacts: null,
loadData: function () {
return $http.get(options.svcUrl).success(onContactsLoadComplete);
}
};
return svc;
}];
});
Then, on document ready, you would make a call to load your config file (in this case, using jQuery). In the callback, you would then do your angular app .config using the loaded json data. After running the .config, you would then manually bootstrap the application. Very Important: do not use the ng-app directive if you are using this method or angular will bootstrap itself See this url for more details:
http://docs.angularjs.org/guide/bootstrap
Like so:
angular.element(document).ready(function () {
$.get('/js/config/myconfig.json', function (data) {
angular.module('myApp').config(['contactsServiceProvider', function (contactsServiceProvider) {
contactsServiceProvider.config({
svcUrl: data.svcUrl,
apiKey: data.apiKey
});
}]);
angular.bootstrap(document, ['myApp']);
});
});
UPDATE: Here is a JSFiddle example: http://jsfiddle.net/e8tEX/
I couldn't get the approach suggested my Keith Morris to work.
So I created a config.js file and included it in index.html before all the angular files
config.js
var configData = {
url:"http://api.mydomain-staging.com",
foo:"bar"
}
index.html
...
<script type="text/javascript" src="config.js"></script>
<!-- compiled JavaScript --><% scripts.forEach( function ( file ) { %>
<script type="text/javascript" src="<%= file %>"></script><% }); %>
then in my run function I set the config variables to $rootScope
.run( function run($rootScope) {
$rootScope.url = configData.url;
$rootScope.foo = configData.foo;
...
})
You can use constants for things like this:
angular.module('myApp', [])
// constants work
//.constant('API_BASE', 'http://localhost:3000/')
.constant('API_BASE', 'http://myapp.production.com/')
//or you can use services
.service('urls',function(productName){ this.apiUrl = API_BASE;})
//Controller calling
.controller('MainController',function($scope,urls, API_BASE) {
$scope.api_base = urls.apiUrl; // or API_BASE
});
//in html page call it
{{api_base}}
There are also several other options including .value and .config but they all have their limitations. .config is great if you need to reach the provider of a service to do some initial configuration. .value is like constant except you can use different types of values.
https://stackoverflow.com/a/13015756/580487
Solved by using constant.
Like providers you can configure it in .config phase.
Everything else like Keith Morris wrote before.
So the actual code would be look like this:
(function () {
var appConfig = {
};
angular.module('myApp').constant('appConfig', appConfig);
})();
then in app.bootstrap.js
(function () {
angular.element(document).ready(function () {
function handleBootstrapError(errMsg, e) {
console.error("bootstrapping error: " + errMsg, e);
}
$.getJSON('./config.json', function (dataApp) {
angular.module('myApp').config(function (appConfig) {
$.extend(true, appConfig, dataApp);
console.log(appConfig);
});
angular.bootstrap(document, ['myApp']);
}).fail(function (e) {
handleBootstrapError("fail to load config.json", e);
});
});
})();
To json config file, there is a practice example on Jaco Pretorius blog's. Basically:
angular.module('plunker', []);
angular.module('plunker').provider('configuration', function() {
let configurationData;
this.initialize = (data) => {
configurationData = data;
};
this.$get = () => {
return configurationData;
};
});
angular.module('plunker').controller('MainCtrl', ($scope, configuration) => {
$scope.externalServiceEnabled = configuration.external_service_enabled;
$scope.externalServiceApiKey = configuration.external_service_api_key;
});
angular.element(document).ready(() => {
$.get('server_configuration.json', (response) => {
angular.module('plunker').config((configurationProvider) => {
configurationProvider.initialize(response);
});
angular.bootstrap(document, ['plunker']);
});
});
Plunker: http://plnkr.co/edit/9QB6BqPkxprznIS1OMdd?p=preview
Ref: https://jacopretorius.net/2016/09/loading-configuration-data-on-startup-with-angular.html, last access on 13/03/2018
I have one question about using of services. I'm creating services in this way
and everything working properly. Here is my code.
var appName = angular.module('appName', ['configuration', 'angularSpinner']);
// this is whay that I creating services.
(function (module) {
var moduleName = function () {
return function(inputVar) {
// some work with
// inputVal variable
return result;
}
};
module.factory("moduleName", [moduleName]);
}(angular.module("appName")));
// in this way I'm using service into controller.
appName.controller('controllerName', function($scope, moduleName) {
});
My question is do I need to set 'moduleName' in 'appName'. Ie like this:
var appName = angular.module('appName', ['configuration', 'angularSpinner', 'moduleName']);
In both cases everything works properly. I would appreciate any comments and recommendations.
Best regards.
My question is do I need to set 'moduleName' in 'appName'. Ie like this:
No you do not, unless you actually create another module. In this case your moduleName is actually your factory name. If you wanted to create another module you would do this.
var myModule = angular.module('myModule', []);
myModule.factory('myFactory', [function(){ /* factory definition */ }]);
var app = angular.module('app', ['myModule']);
// this will now make myFactory available to my app
Your using the factory method which returns a function. If you need a service (a singleton object) then use the service method.
I create my services like this
var app = angular.module('app', []);
app.service('myService', [function(){
var serviceMember = { name: 'something' };
var serviceMethod = function() { };
// revealing module pattern
return {
serviceMember: serviceMember,
serviceMethod: serviceMethod
};
}]);
Yes, You needed
var appName = angular.module('appName', ['configuration', 'angularSpinner', 'moduleName'])
The 'appName' is Main Module name, and the 'moduleName' is sub module name. If you put the 'moduleName' with 'appName', then you can call 'modulname' functions wherever you use the 'appName'.
Main Module :
angular.module('appName',
Sub Module :
, ['configuration', 'angularSpinner', 'moduleName']
The concepts works by Dependency Injection Concept
I have a config that I'd like to be able to inject into Angular services, directives, etc. What is the best way to go about doing this?
I was playing with the idea of making config module:
'use strict';
angular.module('config', [])
But I wasn't sure how to construct the object literal that would be the actual config object that gets injected:
angular.module('myModule', ['ngResource', 'config'])
.factory('myservice', function ($resource) {
return $resource(config.myservice,{}, {
// whatever
})
});
Would it be okay to just expose config as a service and inject that?
I would say, the strategy varies, depending on what sort of config you have, but you have several options:
Module wide constants
If you only need several constants, you can use .value(), like this:
var app;
app = angular.module("my.angular.module", []);
app.value("baseUrl", "http://myrestservice.com/api/v1");
//injecting the value
app.controller("MyCtrl", ['baseUrl', function (baseUrl) {
console.log(baseUrl); // => "http://myrestservice.com/api/v1"
}]);
See a more detailed answer here.
Fetching the config/config service
What i personally like to do is fetch my configuration from somewhere else via a service just as normal. It doesn't matter, if this is a remote location or just static information.
var app;
app = angular.module("my.angular.config", []);
app.service('Configuration', [function() {
return {
getbaseUrl: function() { return "http://myrestservice.com/api/v1" },
getConfig: function() {
return {
answer: 42,
question: "??"
}
}
}
}]):
EDIT: example with an external fetch:
var app;
app = angular.module('my.module.config', []);
app.factory('ConfigurationData', ['$http', '$q', function(http, q) {
var deferredConfig = q.defer();
//error handling ommited
http.get('http://remote.local/config.json').success(function(data) {
return deferredConfig.resolve(data);
});
return {
getConfig: function() {
return deferredConfig.promise;
}
};
}]);
With this service, you can inject your config into other services, however, you can run into timing issues, as you have to inject and resolve the promise given by the service before anything you want to do with the config:
var app;
app = angular.module("my.other.module", ['my.module.config']);
app.factory('MyAwesomeService', ['ConfigurationData', function(config) {
config.getConfig().then(function(config) {
//do something with your config.
});
}]);
You get a bit more fine control here, as you can react to different inputs. Again, it depends on your use case. You can use a factory here if you need additional logic for structuring the configuration.
Lastly, if you want even more control over configuration, you can make a
Custom Provider
Providers can be pretty useful, but i think they are a bit harder to design. Considering a baseUrl from the configuration needed for your app to work, you could write a provider for the service needing the value of the baseUrl like this:
var app;
app = angular.module('my.angular.module', []);
app.provider("RestServiceProvider", function(){
this.baseUrl = 'http://restservice.com';
this.$get = function() {
var baseUrl = this.baseUrl;
return {
getBaseUrl: function() { return this.baseUrl; }
}
};
this.setBaseUrl = function(url) {
this.baseUrl = url;
};
});
This lets you do cool stuff in the config phase of your application:
app.config(['RestserviceProvider', function(restServiceProvider) {
restServiceProvider.setBaseUrl('http://wwww.myotherrestservice.com');
}]);
Every instance you fetch in a service/controller/etc. of RestService will now have the baseUrl set from the config phase from the moment you inject it.
For a more detailed overview, i suggest this gist.
Creating a stand-alone module that only has a service or a directive (or both) is a great way to make application-independent angular code. If you do this you can easily just take that .js file and plop it into any project, and all you need to do is inject it into your applications and it just works.
So doing something like:
angular.module('config', [])
.factory('config', function() {
return {
theme : 'nighttime',
cursor : 'sword',
...
};
});
Then you can just inject it into any application like so:
angular.module('myModule', ['config'])
.factory('myservice', function (config) {
var theme = config.theme;
var cursor = config.cursor;
// do stuff with night-time swords!
});
This is actually how the angular-ui team package all their directives, each directive is contained within its own module, which makes it easy for others to just take that code and reuse it in all their apps.