Angular Translate - Multi Language - Static Files - Race Condition? - javascript

I'm currently using angular translate with the static files loader. I'm implementing at least 3 languages currently, however, I've noticed that typically when it's attempting to load the language file sometimes it takes longer to load the language file than it does for the view itself - which results in a partially translated UI. Most of the items on the screen will stay untranslated, but certain ones will be.
I've tried the following, with no changes:
setting forceAsyncRefresh(true) when configuring the $translateProvider.
set a $rootScope watch in the login controller (first view user will see), and on translateLoadedSuccess, call $translate.refresh().
Upgraded to the latest angular translate
99.9% of all translations are currently being done in the view, e.g.: {{ ::'My Translation Key' | translate }}
What am I missing in trying to resolve this issue? Should I be trying to manually load these language files and set them at an early load time? If so, how do I setup the use of them in the config?
I'm using Angular 1.5.0 and Angular Translate 2.11.1.
TIA!

So this actually was a race condition where the time it was taking to load up the language file initially, was sometimes (not always) longer than it would take angular-translate to static file load the language file.
As far as I could tell, there were two (2) options available - either manually load and setup the language file, or move the language file into separate smaller files themselves. However, I wanted to always be guaranteed moving forward that this wasn't going to be an issue, so I opted to manually load and setup the language file. This actually was fairly simple and required the following:
1) The language file(s) would be loaded at the top of the items in the index.html file.
2) The language file(s) would be assigned a variable in themselves - ie var enUS = { 'LOGIN': 'Login', 'USER': 'User' }
3) The language would be manually setup in the app.config:
app.config(['$translateProvider', function($translateProvider){
$translateProvider.translations('en_US', enUS); // this is the variable we assigned to the language json in step 2
$translateProvider.preferredLanguage('en_US');
$translateProvider.useSanitizeValueStrategy('sanitize');
}]);
That completely fixed all problems across all clients.

Related

How to structure app with Angular JS

I am trying to learn Angular JS and use it in my web app project and am looking for some guidance as well as answers to specific angular js questions. Tech stack I am using is MySQL db, Java w/ Spring Framework, HTML/CSS/Bootstrap/JS, etc..
The purpose of the app is basically a "social media craigslist" where it will have:
1. User accounts
2. Ability to create a "newsfeed-esque" post (one "view")
3. Ability to create a sale post (separate "view")
4. A view for an "inventory"
5. A view for a "wishlist"
etc..
(note: Items 2-5 are accessed via a nav bar of sorts that sits on the left side of my page and the idea was to have the main section of the page switch the content based on what nav item you clicked.. more later..)
What I was doing was writing a bunch of Javscript code to make calls to my web services (grabbing static content to populate drop downs, sending user login info for logging in, etc..) and the < script > tags were growing and all of this was living in my index.html page and I thought it might make more sense to use something like Angular JS and structure it a bit differently and "modularize" the code so it wasn't a giant mess in index page. I was also doing some manual .hide() and .show() JS stuff so I thought that it also might make more sense to switch out the content using something like AngularJS instead of having maximum ONE .show() active at once and then having to do as many .hide()'s as I would need to, to manually switch out the content. This is sounding like a SPA (single page app) right?
I have researched AngularJS StackOverflow posts and looked at w3schools and other helpful websites but am having trouble with how to structure this and use best practices not only with code efforts but organizational as well.
1) Am I correct in thinking Angular would make the hide and show of content easier?
2) I would like to make each "feature" of my website have its own controller and have Controller1.js, Controller2.js, etc.. but do I need to have a
var app = angular.module('myApp', []); ...
line at the top of each controller or do I need something like a main controller with that in there only once and then a call to each controller from a main controller? Or is this not even how I should go about it? Thought process was again to modularize and avoid having one giant beastly file with all my JS logic in it.
3) I assume that I need to use the ng-route stuff (is this correct?) in order to do that hide and show of html content? (items 2-5 listed above) But in what file should that live? a javascript controller file? index.html? other?
4) I read you can only have one ng-view per application. Does that mean that you can only switch/change the content for ONE < div > / section of your web app, OR can you have multiple different divs being changed?
5) fyi - my current file structure is pretty much this.. is this how it should be?
-Java Resources (java code)
...
-WebContent
-img
-META-INF
-resources
-css (folder)
-js (folder with js files - controllers)
-WEB-INF
-lib (folder)
-views (folder)
-xx-servlet.xml
-web.xml
-index.html
-pom.xml
A lot of my questions are just because I am new to AngularJS and not seasoned in JS itself so am trying to better understand. Thanks for any and all help in advance.
First of all, if you want to use multiple views per app then you should use angular-ui-router module instead of angular-route module.
Now, we come to the file handling. So, for that you can make as much file as you can to define controllers, config, services and factories for the app. There are three ways of doing this.
The first one is putting var app = angular.module("MyApp",[]); in first file and defining controllers and services like app.controller('ctrl', ControllerFunction) in each of the other files below the first one. But, personally i don't prefer to use this way as you are exposing your app as a global variable here.
The second way is to create a main module in first file using angular.module('MyApp',[]) and in other files you can get it and define controllers using angular.module('MyApp').controller('ctrl', ControllerFunction). This is the safer way than the previous one.
The third way is to create a different module in each of the files and using all the modules in a single main module as dependencies. Like below
in one file
angular.module('Module1',[]).controller('ctrl1',CtrlFun1);
in another file
angular.module('Module2',[]).controller('ctrl2',CtrlFun2);
and in the main file, the main module, which is to be bootstraped
angular.module('MyApp',['Module1','Module2'])
This is the safest way to define services in different files. I personally advise this way of using multiple js files in single app. Because here you care not exposing a global variable or a single module, so anyone cannot inject some code using console easily.

Dynamic loading of modules and components at runtime in Angular 4

I've been looking to develop a method for loading modules and/or components into an AOT-compiled Angular 4 application and been stymied by a variety of solutions that never quite seem to get me where I want to be.
My requirements are as such:
My main application is AOT compiled, and has no knowledge of what it is loading until runtime, so I cannot specifically identify my dynamic module as an entry component at compile time (which is explicitly necessary for the 'dynamic' component loading example presented on Angular.io)
I'd ideally love to be able to pull the code from a back end database via a GET request, but I can survive it simply living in a folder alongside the compiled site.
I'm using Webpack to compile my main application, breaking it into chunks - and so a lot of the SystemJS based solutions seem like dead ends - based on my current research, I could be wrong about this.
I don't need to know or have access to any components of my main application directly - in essence, I'd be loading one angular app into another, with the dynamically loaded module only perhaps having a few tightly controlled explicit interface points with the parent application.
I've explored using tools like SystemJsNgModuleLoader - which seems to require that I have the Angular compiler present, which I'm happy to do if AOT somehow allowed me to include it even if I'm not using it elsewhere. I've also looked into directly compiling my dynamic module using ngc and loading the resulting ngfactory and compiled component/module, but I'm not clear if this is at all possible or if so - what tools Angular makes available to do so. I have also seen references to ANALYZE_FOR_ENTRY_COMPONENTS - but can't clearly dig up what the limitations of this are, as first analysis indicates its not quite what I'm looking for either.
I had assumed I might be able to define a common interface and then simply make a get request to bring my dynamic component into my application - but Angular seems painfully allergic to anything I try to do short of stepping outside of it alltogether and trying to attach non-angular code to the DOM directly.
Is what I'm trying to do even possible? Does Angular 2+ simply despise this kind of on the fly modification of its internal application architecture?
I think I found an article that describes exactly what you are trying to do. In short you need to take over the bootstrap lifecycle.
The magic is in this snippet here.
import {AComponentNgFactory, BComponentNgFactory} from './components.ngfactory.ts';
#NgModule({
imports: [BrowserModule],
declarations: [AComponent, BComponent]
})
export class AppModule {
ngDoBootstrap(app) {
fetch('url/to/fetch/component/name')
.then((name)=>{ this.bootstrapRootComponent(app, name)});
}
bootstrapRootComponent(app, name) {
const options = {
'a-comp': AComponentNgFactory,
'b-comp': BComponentNgFactory
};
https://blog.angularindepth.com/how-to-manually-bootstrap-an-angular-application-9a36ccf86429

AngularJS module architecture

I am planning to create several modules in my company's application and I'm having trouble designing the architecture for the modules. I have done research and it seems like either you are supposed to use one module per page, or create a 'master' module that depends on all of your other modules. I don't like this approach because it means I have to load all of the javascript for every aspect of my application for every single page. That seems inherently wrong, but I also can't seem to figure out how to handle it the other way if I need to use one module in multiple places on a page. For example, I have a membership module that I have and I'm attaching to the header section of my web page. This would be intended for logging in, registration, and performing a 'forgot password' type workflow.
On another page dedicated to changing a password (from a reset link) the header is also present, but I want to include the password reset functionality in the membership module. I've read that one methodology of designing your application is by functionality/feature. I figured membership was an appropriate application of that, but now I'm not sure since I am having trouble applying the membership module more than once on any particular page.
Am I on the right track, or is there a preferred method for this? Should I have a separate module for the header and one for the rest of the page? Should I just bite the bullet and load everything? (I hope not...)
I should also note that this is an ASP.Net MVC application where we are still heavily relying on MVC for serving views and partial views. As such I wanted to use a render javascript section to dynamically load only the javascript necessary for that page to function. Is this a farce?
<header ng-app="membership">
//stuff for header membership functions
</header>
<div ng-app="membership">
//somewhere else that needs membership, outside of header
</div>
I personally like Mini SPAs (Silos) instead of full SPA. You can watch Miguel A Castro's video, and download the source at his website.
What it does is when a request comes in, it goes to ASP.Net MVC Route first. Then, Angular Route takes over the rest. It is a very slick design.
FYI: Angular 2 is right around the corner, so I went ahead and updated those to Angular 1.5 Compotent so that I can convert to Angular 2 easily later.
If you want, you can stop there. I went one step future, and use Strongly Typed Views using Matt Honeycutt's Building Strongly-typed AngularJS Apps with ASP.NET MVC 5 approach.
Then I implemented Angular Helpers like Axel Zarate's ANGULAR.NET – HELPERS FOR ASP .NET MVC 4.
On an Angular application, as it is a Single Page Application, yes, all your javascript must be loaded. It's the code of your application and it's necessary. That's done only once on first page load.
You're always on the same page, but on a different state.
One good approach is to define a master module who include all other modules. Those modules can also include other "sub modules" they need.
angular.module('App', [
'App.Membership'
// ...
// All others modules you need, including 3rd party modules
])
Then, on each module, you can define the different states associated and their controller
angular.module('App.Membership', [
// Module dependencies
])
.config(['$stateProvider', function($stateProvider) {
//State definition
$stateProvider.state('membership', {
parent: 'app',
url: '/member',
controller: 'MembershipCtrl',
template: '<ui-view/>'
});
}]);
You can also add a global controller to handle elements who are always present, like a header.
Hope this helps

How does backbone with require.JS work?

I am trying to understand how requireJS and backbone work. With this site when I open the DevTools in Chrome and opened a Sources Tab. I see a long list of folders/files (see image below) which seems to be the source code when it's uncompressed. However, I don't see it being loaded via the Network Tab.
I wonder how does it tie in and is it normal that the source code gets exposed like this, and whether it is normal that all views are being loaded even I just requested one page (i.e. the search page, see image below). I understand that modern Javascript applications like Angular likes to preload the application before it's presented. But wouldn't it be causing a lot of unnecessary traffic to users? especially those on mobile view?
First, your question mixes two things.
BackboneJS and RequireJS are completely unrelated
What you observe (module dependency structure in the scripting panel vs. all those files actually not downloaded) is due to the Debugger support of "Source maps"
Since I guess your confusion is caused by this I'll start with ...
Source maps
Modern browsers support source maps. Their intention is to reveal the original source code when it has been concatenated and/or minified into one file.
The source map file describes e.g. the symbol ZZyb at line 1 char 20563 is mapped to e.g. the file/somewhere/in/the/tree at line 34 char 1 and is named someView.
Minified files reference the source map using the
# sourceMappingURL=getaround-min.js.map
signature.
More on source maps: http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
When downloading the minified file (https://www.getaround.com/js/150502002818/getaround-min.js) on that website you've linked, you will observe that signature at the end of the file:
//# sourceMappingURL=getaround-min.js.map
You can then download that file. This is what your debugger does.
RequireJS vs. BackboneJS
You can use RequireJS to modularize your own code or in conjunction with other Frameworks that do not already ship with such technologies.
AngularJS for example has it's own dependency management which allows you to define named dependencies and finally you start the application. This allows you to just concatenate (and minify) all sources into one file without taking care of the definition order.
Even though Backbone and Require are unrelated they work very well together.
RequireJS
RequireJS implements the so called AMD spec.
A module defines dependencies and a callback to implement that module.
depA:
// Require depB and depC and after they've been loaded
// call the callback function and pass those
// dependencies. Finally return that module.
define(["depB", "depC"], function(depB, depC){
// by convention depB will resolve to depB.js relative
// to "depA"'s path
// object, string, number, function your module is made of
return something;
});
RequireJS will download the dependencies, store (cache) them intenally and pass them to the callback. This process repeats down the dependency tree. When a dependency has already been downloaded (by another upstream module) it can be passed directly without downloading it again.
depB:
define(["depC", "depD"], function(depC, depD){
// depC has already been loaded and cached - doesn't
// need to be downloaded again
});
RequireJS optimization
Downloading all dependencies file by file can (and - on internet seites - should) be avoided by packaging them using r.js. The modules will be converted into into one file during build time.

How can I get an environment specific URL into my AngularJS controller?

Situation
Our web project in production has a root URL like so: http://example.com. Our local dev instances (don't ask me why) default to a URL like so: http://localhost/SubDir where SubDir is a placeholder for the actual virtual subdirectory in IIS.
This is not the problem. As much as I would like to abolish that subdirectory URL thing, that is only illustrating a problem. If we were to move to a different domain or URL later on that incorporates a subdirectory URL, it would not be a problem for all of the instances in code where we use helpers to generate URLs (e.g. #Url.Action("GetUpdates"), etc).
Currently we have quite a bit of javascript that has been moved to external .js files that uses jQuery to get URL strings from hidden inputs whose values have been set to a Url helper like above. This is not too bad, it works.
The Problem
AngularJs. It is not the problem. It has however uncovered the problem. We want to remove jQuery from the project eventually. Right now, I am getting the URLs in my controller using jQuery (I am willing to break rules in an effort to get something out on time if I can be reasonably assured I will be given time to fix it later). It is now time to fix it, and I am at a loss.
Between the two environments, I get the following from #Url.Action("GetUpdates"):
On http://example.com/: => /Contest/GetUpdates
On http://localhost/SubDir: => /SubDir/Contest/GetUpdates
The Question
How can I get an environment dependent URL into my AngularJs controller without the use of the helpers in that controllers file? I originally thought it might be as simple as using the hidden inputs and setting the ng-model, but does not seem to have worked. I have also looked into using an extension, RazorJS, but hoped that there would be a better way of doing it more inline with the Angular paradigm.
Anyone have any ideas? How do you get URLs into your controllers?
If you are able to change your environment config server side you can put the variable inline in a module constant. Then you can inject into your main app.
Here's a Plunker
// inline
angular.module('Preload',[]).contstant('CONFIG', {'BASE_URL':'http://localhost/foo'});
// inject
var app = angular.module('MainApp', ['Preload']);
// Controller
app.controller('MainCtrl', function($scope, CONFIG) {
$scope.base_url = CONFIG.BASE_URL;

Categories

Resources