How do I create a delegating Angular multi host site? - angularjs

I work in an environment where we develop a solution using several (a lot of) servers. They microservice style is the role model.
To be able to upgrade systems they must be switchable/replaceable (including the user interface) in runtime.
The principal solution that have been decided upon is that
a Portal/Proxy is the only visible system for the end user
The proxy is "aware" af the supporting servers
The proxy has some basic user interface with for instance menues. Might be in collaboration with the subsystems (several entries in the menu etc.)
A user requests a page with some dynamic content
The portal relays/proxy the query of "content" part of the page to the subsystem.
Any REST-calls needed by the client is also proxied through the main server.
The REST calls are of course very simple but I am too n00b in Angular to really understand how to make the "mix.
Point number 5 is of course the tough part. IF the subserver would have been visible an iframe (eeek!) could have been used but not in this case.
I need some sort of "delegation" within a page, anything done before? How DOES the microservice flagships handle the User Interface?

I have now evolved from n00b to n00b++ regarding Angular.
The solution lies within the HTML-snippets used for templates within Angular.
I can define a html template with a JS file and an HTML file. The JS file refers to the HTML page by a URL. Usually (in the samples I have seen) the path is relative like:
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
.controller('View1Ctrl', [function() {}]);
But by using an absolute path I can refer to an external resource:
angular.module('myApp.view2', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view2', {
templateUrl: host + '/app/view2/view2.html',
controller: 'View2Ctrl'
});
}])
.controller('View2Ctrl', [function() {}]);
Notice I added a parameter 'host' calculated by looking at the script tag including this JS file.
var scripts = document.getElementsByTagName('script');
var src = scripts[scripts.length - 1].src;
var host = src.match(new RegExp('https?://[^/]*'))[0];
But the third problem to address is to handle the CORS problem. In my test environment (node.js+express) I just added the 'cors' library and I could access my "external" site.
var express = require('express'),
cors = require('cors'),
app = express();
app.use(cors());
app.use("/", express.static(__dirname));
app.listen(8001, function(){
console.log('CORS-enabled web server listening on port', 8001);
});

Related

AngularJS application continuously redirects within BPM and thus crashing browser

I included a standalone AngularJS project in IBM BPM by keeping all the project assets (html, css & js files) in resources (teamworks.war) and keeping the index.html and AngularJS's main controller in customHTML in BPM's coach view.
Routing file for AngularJS (app.js):
angular.module('demoApp', ['ui.tree', 'ngRoute', 'ui.bootstrap'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when("/tree", {
controller: "treeCtrl",
templateUrl: "template.html"
})
.otherwise({
redirectTo: '/tree'
});
}]);
BPM loads the AngularJS app again and again (using '/tree ' instead of '/tree' as the template name) as seen from elements in developer tools in ng-view and ultimately the browser gets crashed.
Although the same AngularJS app works perfectly fine on browser independently (without being included in BPM).
How can this behaviour be avoided in BPM?
Sometimes third party libraries have limitations which you would not have locally.
When it is not possible to change the source code of that particular project, you might be better off by incurring a small stylistic penalty in your own code, so that you can integrate with the other software.
In this case, if you cannot change the configuration to omit the space, you could change your own template name to '/tree ', which will have an unnecessary space after your template name, but should be called on properly through BPM.

Angular JS views not working when integrated with Django

I am new to this Django-Angular JS integration. I created few web pages in AngularJS, views were working fine. As soon as I integrated with Django, first I had to correct paths to work but still views are not working. The view part stays blank and also grows in length (as if it goes into some loop!). Any idea guys?
EDIT:
Below is the way I am calling the view inside verbatim section of index.html
<div ng-view=""></div>
My js config file:
'use strict';
var mainAngular = angular.module('bazaar',['ui.bootstrap', 'ngRoute', 'ngCookies']).run(function($http, $cookies) {
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
});
mainAngular.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: "../static/views/welcomeView.html"
})
I have just pasted the code which I am using for view call. Let me know if its helpful or you guys need more details.
Well, I found out the issue so thought to drop the answer as well so that It may be helpful for other newbies like me.
I was including js file in my view ealier (which was working completely fine when run as a separate page using Tomcat) , but as soon as I integrated with Django I had to remove all js file path from <script> tag and Bingo !!

Angular fails to load template

I'm trying to compartmentalize an Angular app and running into issues getting the ngView working properly. The route seems to be configured correctly, as when I log its properties I get: $route, $routeParams, and $location, I get:
Object {routes: Object, reload: function, updateParams: function}
Object {}
and
LocationHtml5Url {$$html5: true, $$protocol: "http", $$host: "localhost", $$port: 3000, $$parse: function…}
I read here that the $routeParams can appear empty due to its aynchrynous nature, so I don't think thats an issue, but I'm not sure what I'm missing.
Heres the err message:
GET http://localhost:3000/partials/projectBlocks 404 (Not Found)
I know I'm supposed to be routing relative to the root of my app, which I believe I am, so I'm not sure why its looking for the partial in what appears to be the ../public/.../ folder (app is typical express structure)
Heres my code:
jade view (in ./views)
div(ng-controller='projects')
div(ng-view)
partial view (./views/partials)
p hey you found me!
controller (in /public/ directory)
angular.module('mean-man')
.controller('projects', ['$scope', '$http', '$route', '$routeParams', '$location', function($scope, $http, $route, $routeParams, $location){
console.log($route);
console.log($routeParams);
console.log($location);
this.$route = $route;
this.$location = $location;
this.$routeParams = $routeParams;
angular app.js file (in /public/ directory)
(function(){
angular.module('mean-man', ['ngRoute','ngAnimate','mm.foundation'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider){
$routeProvider
.when('/:member', {
templateUrl: 'partials/projectBlocks',
controller: 'projects',
controllerAs: 'project'
});
$locationProvider.html5Mode({enabled:true,requireBase:false});
}]);
})();
I was going off the AngularJS official documentation and this site, so my code may be a mix of the two, thanks for any help / references!
AngularJS won't compile the Jade templates for you. You have it setup to look at 'partials/projectBlocks', and since I assume you are using '/public' for your static server directory, it's going to expect a file at '/public/partials/projectBlocks' relative to your project's root directory.
To solve this problem, you need to either setup some middleware that will check if the request is looking for a file in the partials directory, and if so, compile it using Jade so that it will exist when the request reaches the static server middleware, or, manually compile the Jade into HTML using something like HTML2Jade and create a new file in the '/public/partials' directory called 'projectBlocks'. AngularJS will not assume an HTML extension, so if you make the file called 'projectBlocks.html', you must change the template URL to 'partials/projectBlocks.html'
After a quick Google search, you can use Connect Jade to accomplish the first suggestion I made above. Simply follow the instructions in the README, and it will act as a Jade compiler and static server for that directory.
I ended up finding the solution in another answer here:
Express and AngularJS - web page freezes when attempting to open home page
The short of it is I got myself confused between my Express routers and Angular routers. I had moved my partials/projectBlocks around while debugging trying to find the correct file structure because the one I'd created didn't seem to work. But, when I got it connected it would stall out the browser. Turns out I left out the handler for the actual Angular request, causing it to never go through and timing out.

How to use pyjade as part of clientside and serverside application?

I'm creating a single page application using flask. If I understand the process correctly, then ill be having flask serve up a single page (html and css) upon the first GET request. From their, the client will only receive data and the it will use already stored html (partials/other pages) to modify the site.
Ideally, I would like to use something that provides a nicer syntax then html, something like slim, haml or jade. Though i don't need the templating aspect, as this functionality will be provided through angularJS.
Assuming the above is correct, my confusion is how to use pyjade (or any such tool) with flask to transform the partials that the client side application would be using. For example, if i have some client side code that creates the routes like so...
var app = angular.module('App');
app.config(function($routeProvider){
$routeProvider.when('/', {
templateURL: 'partials/home.jade',
controller: 'HomeController'
}).otherwise({ redirectTo: '/' });
});
Then i would need home.jade to be transformed into home.html when it was served up to the client. Assuming I understand what 'should' be done correctly, how do I do this?
One such solution would be manually transform the home.jade into home.html and keep my code like this:
var app = angular.module('App');
app.config(function($routeProvider){
$routeProvider.when('/', {
templateURL: 'partials/home.jade',
controller: 'HomeController'
}).otherwise({ redirectTo: '/' });
});
I'm using Flask, PyJade, and jQuery as a controller. You can install PyJade with,
sudo pip install pyjade
And then according to the documentation you can insert the following line in your Flask app,
app.jinja_env.add_extension('pyjade.ext.jinja.PyJadeExtension')

Is it possible to build a hybrid app with Angular?

I build an AngularJS application that I expected to work as a hybrid application for mobile devices. As such the application would run locally from the file system.
When the $routeProvider gets the html file I get the following message.
This is a CORS violation obviously but the file is local and trying to access another local file. It's not like a web site is trying to access a clients local files. This is the client.
I can't spin up a web server to serve up the local files because this will be packaged up and deployed as a local application.
I know people build hybrid mobile applications all the time. What I can't figure out is how they do this with AngularJS and why AngularJS doesn't either offer a solution or prescribe how to get around CORS.
I'm open to all suggestions. Thanks all.
XMLHttpRequest cannot load file:///D:/SubversionRits/SourceCode/Verso%20-%20Mashup%20Proposal/MarshupSource/MashupCoreUI/core/apps/mashup/welcome/welcome.html. Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, https, chrome-extension-resource. VM36 angular.js:8380
Error: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'file:///D:/SubversionRits/SourceCode/Verso%20-%20Mashup%20Proposal/MarshupSource/MashupCoreUI/core/apps/mashup/welcome/welcome.html'.
Here is my route config
mashupApp.config(function ($routeProvider, $httpProvider) {
// I've tried all these with no effect.
//$httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
//$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
//$routeProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
//$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
//$httpProvider.defaults.useXDomain = true;
//delete $httpProvider.defaults.headers.common['X-Requested-With'];
$routeProvider
.when('/about', {
templateUrl: 'apps/mashup/about/about.html',
controller: 'aboutController',
resolve: {
loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
// you can lazy load files for an existing module
return $ocLazyLoad.load({
name: 'mashupApp',
files: ['apps/mashup/about/aboutController.js', 'apps/mashup/~appServices/dataService.js']
});
}]
, sessionLoad: function ($route, sessionLoad) { return sessionLoad.loadCompleted(); }
}
})
.when('/', {
templateUrl: 'apps/mashup/welcome/welcome.html',
sessionLoad: function ($route, sessionLoad) { return sessionLoad.loadCompleted(); }
}
})
;
});
I don't know the details, but I'm pretty sure HabitRPG's Android app uses Angular.
https://github.com/HabitRPG/habitrpg-mobile
Ok, I figured it out.
Running a web app from a file doesn't work because of CORS but when you are packaged up in Phonegap or Cordova inside the Intel XDK everything works.
I took my application and created a blank Intel XDK project and copied my web files to it without changing anything.
It all worked!
Thanks for those who offered ideas and suggestions. I really appreciate it.
I see how this can work now.
If you want to create a hybrid mobile app with AngularJS, you should definitely checkout the Ionic Framework.
From the Ionic website:
A match made in heaven. Ionic utilizes AngularJS in order to create a framework most suited to develop rich and robust applications. Ionic not only looks nice, but its core architecture is for serious app development, and AngularJS ties in perfectly.
You can't access the files directly due to browser security settings, but you can store data etc in localstorage and use that when the app is offline.
Someone has put together an example here http://amitavroy.com/justread/content/articles/html5-local-storage-angular-js

Resources