How to pass a globally configured CDN url to templates in AngularJS? - javascript

this should be simple but after extensive googling I havent found an answer.
I use cloudfront as a CDN for my web app. I would like to configure the cloudfront url to a single file, as it might change in the future. I am trying currently to pass the value to the the templates as they use some images via css style background. I have found out that one solution would be to put in the scope in every controller, but there so many of them, and including this to all would make the code more possible for errors if it is forgotten.
So, this is a code example I have tried:
app.js:
.constant('CDNurl', 'https://xxxxxxxxxxx.cloudfront.net/')
main.js:
$rootScope.CDN = CDNurl;
navbar.html:
<div class="avatar__image"
ng-style="{'background-image':'url(' +
$root.CDNurl + currentUser.profileImage+')'}">;
does not work. If I include it in the navbar controller it of course works, but I need to pass it globally.
So what is the correct way of doing this? Configure something and reach it from templates?

If you have a parent controller at the top of the DOM and in that you set $rootScope.CDN = CDNurl;, then you can access CDNurl is available in all the child views.
Or another option might be to use run (I haven't tried this):
var app = angular.module('module', []);
// run blocks
app.run(function($rootScope, CDNurl) {
$rootScope.CDN = CDNurl;
});

Related

Change React Webpack application file and api path

I'm working on an app that is going to be deploy on-prem (no cloud) and there are requirement to deploy the application to different server path. For example in one company it might be company1.com and on another it might be company2.com/app because they already have a server and want to deploy it on the same server under a different context path.
The problem is in Webpack we compile the app and create HTML+JS+CSS files. The HTML and JS files have the server context path (part after the domain name) hardcoded into the code. For example loading the JS files will be done with <script src="/hello.js" /> so if the app will be deploy to company2.com/app I need the script tag to be <script src="/app/hello.js" />
I'm looking for way to change the server context path dynamically preferably using environment variable.
For compare we use Spring on the server side and there we can define env-var server.contextPath which will change the context path in which the app works.
If it changes anything the app is deployed as docker image.
Any ideas how to implement such thing?
That's an interesting question, and there are some ways you can resolve that. I'll list some options below.
I'm looking for way to change the server context path dynamically preferribly using environment variable.
I will list some other options, but the first one is using env vars.
Using Environment Variables When Building
webpack has a plugin (DefinePlugin) that allows us to set environment variables to the javascript code.
Then, you will be able to get those environment variables using process.env. For exemple, if you have the following configuration:
plugins: [
new webpack.DefinePlugin({
fruit: JSON.stringify('orange'),
MY_VAR: JSON.stringify('value'),
API_URL: JSON.stringify('http://some-api')
})
]
Then, in your code you can get them using:
console.log(process.env.fruit); // "orange"
console.log(process.env.MY_VAR); // "value"
console.log(process.env.API_URL); // "http://some-api"
This said, you can do something like this:
Passing environment-dependent variables in webpack
Then, for example, you can just use process.env.API_URL in your code, instead of using it hardcoded.
IMPORTANT: this method will only work if you have can build your code before releasing it to production. (I think it's not a problem for you).
I think this is the best option, because your code will be "clean", it is more "customizable" and it will "simply work", regardless your environment.
Using a Map
You can have some application logic to decide your variables. For example, you may "look" to the URL (i.e. location.href) and decide the values to use based on this address.
let api;
if (domain === 'domain1.com') api = 'api1';
if (domain === 'domain2.com') api = 'api2';
Using an Extra HTTP Server
You can always point to a hardcoded path in your server, lets say /api. Then, in your code, you will point to /api. So, all your requests will go to /api.
You will need to have an HTTP Server (it can be a Nginx, a NodeJS, whatever you want) listening to /api and then have this "routing" logic there.
It will work fine, but you will need to control the deployment of this HTTP server. This may not be a good option for you, but it may suit your needs.
One advantage is that you'll be able to only change the code of this HTTP server when changing some routes, without need to deploy your front-end code again.
I think that sums it.
Hope it helps!

Using external js libraries in sapui5

So I'm trying to inlcude an external .js file in my SAPUI5 Controller.
jQuery.sap.includeScript("externalLibrary.min.js",
function() {
//initalizing objects from library
});
However, the callback which should be called once the script is loaded, never gets called. The error message it gives me is:
"externalLibrary.min.js:16 Uncaught TypeError: Cannot read property
'Constructor' of undefined"
Whats another way I could do this? I was looking into jQuery.sap.registerModulePath() and jQuery.sap.registerResourcePath() but couldn't find a good example of the use of these nor an explaination of the difference between the two online.
Thanks a lot!
You can try jQuery.sap.includeScript(vUrl, sId?, fnLoadCallback?, fnErrorCallback?)
https://sapui5.hana.ondemand.com/docs/api/symbols/jQuery.sap.html#.includeScript
in fiori launchpad based app , we use component.js as root , so we don't have index.html to include scripts (if you use XML view instand of HTML view).
try
jQuery.sap.includeScript({
url: "https://maps.googleapis.com...",
id: "IncludeGoogleMapsScript"
}).then(function() { ... })
Not working in portal service , fallback is provided :
UsingjQuery.sap.includeScript().then() in HCP Firori Launchpad
You can use jQuery.sap.registerResourcePath('lib', URL) and then jquery.SAP.require('lib.file'). You can do both one after another or register in the init and later require. Does not matter. I don't have an example at hand as I am on a phone but it works. What you need to keep in mind is that this example would load something like URL/file.js so you need to adjust accordingly. The name you give to the lib does not matter.
You can also inject a script tag into the current page ,however, the require will load the external lib synchronously while if you inject a script tag you need to wait until it is loaded with a callback.
PS: the capitalization on those methods is not right
Got it! For future reference, it works to load the files from the index html like so:
<script src="library.js"></script>
The main problem was that I was trying to include external dependencies which also contained jQuery. So, I had to remove that from the file and now it's working.

How do I make JS know about the application root?

I have some javascript that's referencing /jobs/GetIndex in an MVC project. This works great when I run it locally because I have a Controller called JobsController. When I deploy it, I deploy the application to a 'Jobs' subfolder, which means the URL should become http://site/jobs/jobs/GetIndex but it's going to http://site/jobs/GetIndex, I presume because the javascript doesn't know what the 'root URL' is, and uses the site as the root. How can I get it to work in both environments?
If you simply care about getting the root/base url of the site so you can append that to get the other url you are after, you may simply use / as the first character of your url.
var urlToJobIndex2= "/jobs/GetIndex";
Here is an alternate approach if you want more than just the app root (Ex : Specific urls( built using mvc helper methods such as Url.RouteUrl etc)
You may use the Url.Content helper method in your razor view to generate the url to the app base, assign it to a javascript variable and use that in your other js code to build your other urls.
Always make sure to use javascript namespacing when doing so to avoid possible issues with global javascript variables.
If you want to get url to a specific action method, you may use the Url.Action or Url.RouteUrl helper methods.
So in your razor view (Layout file or specific view), you may do this.
<script>
var myApp = myApp || {};
myApp.Urls = myApp.Urls || {};
myApp.Urls.baseUrl = '#Url.Content("~")';
myApp.Urls.jobIndexUrl= '#Url.Action("GetIndex","jobs")';
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>
And in your PageSpecificExternalJsFile.js file, you can read it like
var urlToJobIndex= myApp.Urls.jobIndexUrl;
// Or With the base url, you may safely add the remaining url route.
var urlToJobIndex2= myApp.Urls.baseUrl+"jobs/GetIndex";
Here is a detailed answer about the same , but using this in a specific page/view
Angular Js
You might need the correct relative url(s) in your angular controller / services / directives.The same approach will work for your angular code as well. Simply build the js namespace object and use the angular value provider to pass the data to your angular controllers/services/directives as explained in this post in detail with example code.
Add <base href="/jobs"> to your head tag. It will specify the root.
This is further explained here https://docs.angularjs.org/guide/$location

How to inject a module dynamically inside another module?

My angular app is like below
App.js
angular.module('myapp', [
'ngSanitize',
'ngMessages',
authModule,
loginModule
]);
//prodductModule
In my login module I have a ajax call using $http. After receiving proper response from server I want to initialize another module suppose "productModule".
How to do it? Is it possible in angular?
You can do like this:
var myApp = angular.module('myapp', [
'ngSanitize',
'ngMessages'
]);
Now, later in your AJAX call code, you can write like this:
myApp.requires.push('productModule');
Take a look at Inject modules conditionally in AngularJS app
Short answer - NO, it is not supported by default.
Long answer - SLIGHTLY - using 3rd party libraries like: https://oclazyload.readme.io/
But my opinion is that you shouldn't do that, Angular is designed for apps, so just let whole app load before start. Even big app will start fast. Loading modules dynamically can cause unwanted lagging and modules are not unloaded when not needed.
But final decision is yours as ussual :)
EDIT:
If you are trying to load other modules when user is logged in. We ussually do it like redirect to production app with authentication token in querystring, so server let us download javascript with app. But this is not necessary everytime, ussually we load whole app.
You can't load Module dynamically. Angular needs to know all module names during its bootstrap process.
To solve this problem you can create empty module and pass its name to your app.
then load module JS file via RequireJS and register each services or controller one by one.
Load module dynamically, I would suggest to go with require js.

Setting up a common route for javascript calls in ASP.NET MVC project

I have a bizarre routing issue with my ASP.NET MVC project that I hope you guys can help me with.
Overall everything works fine when I run the project off my localhost or run it on the server while it's deployed directly at http://myServerName. The problems start when I deploy the application to various enviornments on the server located under different virtual directories. For example: http://myServerName/QaEnviornment or http://myServerName/TestEnviornment
The problem is that all Javascript calls to application URLs ignore my environment virtual directories and fail.
For example on my QA server whenever I have to make an Ajax call I take a standard approach such as:
var myUrl = '/ControllerName/ActionMethodName/'
$.ajax({url:myUrl,success:function(){Do stuff} })
Because my application is deployed on http://myServerName/QaEnviornment, when rendered I expect myUrl to be http://myServerName/QaEnviornment/ControllerName/ActionMethodName. Instead it comes back as http://myServerName/ControllerName/ActionMethodName and ofcourse fails.
To get around this for now I declared a global Javascript variable that contains the environment folder name and when I build URLs for javascript calls I have to remember to ALWAYS construct them as var myUrl = myGlobalFolderVar + '/ControllerName/ActionMethodName/'
Using a global JavaScript variable to get around this issue seems as a bad solution to me. Is there anything I can do to get routing to work properly so whenever JavaScript calls are made whatever subfolder the application is running under is always included in the URL ?
Instead of always having to remember to construct them correctly, make a helper function that you call to create your URLs
function CreateUrl(string path){
return myGlobalFolderVar + path;
}
To answer your second question, not really. Routing is not aware of what made the request and you cannot always rely on the X-Http-RequestedWith header to base that decision on. In addition, your site application root is not at the domain root, therefore routing would only kick in when it visits your application. The only other way I am aware of is to have MVC actually generate the Url for you (var url = '#Url.RouteUrl(params)';) but this does not help at all when you have your JavaScript in a single or a few .js files.
EDIT
The above function is a JavaScript function that can sit anywhere you would like in your application, including external JS files. As for setting your myGlobalFolderVar, there are a few ways you could set this.
1.Actually hard code the variable in your external JS file.
var myGlobalFolderVar = 'TestEnviornment';
This is hard however if you are deploying to several different testing servers.
2.If you are using web.config transformations, you could add an AppSettings key/value pair in your web.config transformations depending on build type. Then, using that value, set your global Javascript variable in your master page layout/views.
<appSettings xdt:Transform="Replace">
<add key="folderLocation" value="TestEnvironment" />
</appSettings>
In your external JS file
//this makes it a site wide/global variable in any place you
//include your external JS file
var myGlobalFolderVar = '';
And in your master view
<script type="text/javascript">
myGlobalFolderVar = '#ConfigurationManager.AppSettings["folderLocation"]'
</script>
3.Same as number two, but use the URL helpers to figure out what the path to your application is in your master view instead of using the web.config transformations
<script type="text/javascript">
myGlobalFolderVar = '#Url.Content("~/")'
</script>
The basic idea is using .NET to figure out where it lives and set a global JavaScript variable with that path information. Then, in conjunction with the helper JavaScript function provided at the top of this answer, you can correctly generate paths as needed throughout your application - regardless of path depth, deployment location or any other deployment type concerns.
var myUrl = CreateUrl('/ControllerName/ActionMethodName/');
$.ajax({url:myUrl,success:function(){Do stuff} });

Categories

Resources