Scenario:
I'm building an AppGyver Steroids mobile web app.
I chose to build a Multi Page Application using multiple WebViews to display parts of my app, because that way I can use native tabs, header bars and page transitions.
My JavaScript framework is AngularJS.
Since every WebView has its own DOM and JavaScript runtime, my AngularJS services are no unique singletons. This creates problems.
Appgyver suggests to load a hidden backgroundServices.html document as an always-there master document and house the singletons in my app there.
They provide a publisher/subscriber method using
window.postMessage("someMessage");
and
window.addEventListener("message", someMethod);
to communicate between WebViews.
Unfortunately they provide no example of this method and I'm really struggling to build a clean implementation.
Since I'm using Restangular I would like my REST services (that should be in backgroundServices) to return promises, and I can't figure out how to do that in a reusable way with a publisher/subscriber mechanism in between, without causing too much overhead..
How can I communicate with an AngularJS service only accessible using Events, and keep working with Promises?
I figure I need to make a "BackgroundServiceConnector" service available on every normal webview.
In this Service I would have a function
call(serviceName, function, parameters)
which I call like this:
var app = angular.module('homeApp', ['ngTouch', 'BackgroundServiceConnectorApp']);
app.controller('LoginCtrl', function ($scope, backgroundServiceConnector) {
$scope.doLogin = function(username, password){
backgroundServiceConnector("accountService", "authenticate", {username: username,password: password})
.then(function(){
//login OK logic
}, function(error){
//login Not OK logic
});
}
});
I think I'm more or less capable of implementing this, but I am unsure of:
how to make this usable for functions that do not return promises. (detect if the function returns a promise at the backgroundServices.html side)
if there isn't a more elegant way in which I don't have to pass "accountService" and "authenticate" as strings.
how I can - in the backgroundServices.html - parse the service name and function into an executable call.
how would I go about making the foreground services automatically "subscribe" to changes in the "model" at the background?
I know enough JavaScript to know it is a very extensible language offering a lot of freedom, but I don't know enough to be able to build a good solution for my scenario..
I would love for someone to help point me in the right direction and provide advice.
Thanks!
Related
I have developed a web app which is a QA forum using mean stack approach. Currently the project is working and I have implemented the basic requirements like login authentication using passportjs, then storing questions, answers, votes etc. in mongodb using mongoose.
Now I am required to add a state machine like workflow programmatically to the entire project where each module (eg.login module) will act as a state. And a flow for them must be defined.
I have looked into javascript workflow engines like workflow-4-node, bpmn.js, turbine.js. So my question is, how should I use these libraries without changing any code of my project, Is there any specific approach to do this, or am I required to change my entire code to implement the work flow.
Also in my project I am using ui.router(Routing module for angularjs) to switch between different pages and controllers (by using $stateProvider). So is this routing that I have implemented, and the state machine like workflow that I am required to do, same(different terminologies but same concept) or are they different?
NoFlo 0.8 provides a asCallback interface, allowing users to embed NoFlo graphs into existing JavaScript code.
So, if you have defined a NoFlo graph for a particular workflow, you can include it to your JavaScript app like this:
// Wrap a NoFlo graph
var myFunc = noflo.asCallback('my-project/MyGraph');
// Call the wrapped graph
myFunc({
inport: 'data'
anotherport: 'more data'
}, function (err, result) {
// Do something with the result
});
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
So, let's say that I am building a single-page app in JavaScript. For now I do not have a persistence layer in my app but I still need to write the code.
class App {
handleClick(event) {
User.saveToFile(event.target.value);
}
render() {
return 'Some template...';
}
}
So, I create my concrete user class. But for now just save it to the local storage.
class User {
constructor(localStorageHelper) {
this.localStorageHelper = localStorageHelper;
}
save(name) {
this.localStorageHelper.users.save({
name
});
}
}
When the database is ready, I need to switch to the database. If I was in an object-oriented language I can simply create an interface and use polymorphism or repository pattern to solve this problem.
I was wondering what if I create an app container to contain all of the concrete implementations. For example I can create a bindings.js file like the following:
import UserPersister from './Repos/Db/User'
import PostPersister from './Repos/File/Post'
const Bindings = {
'UserPersister': UserPersister,
'PostPersister': PostPersister
};
So now in my App.js file. I can do something like:
let User = Container.make('UserPersister');
class App {
handleClick(event) {
User.saveToFile(event.target.value);
}
render() {
return 'Some template...';
}
}
Now I can easily switch between different implementations by just changing them in bindings.js. If you've worked a little bit with Laravel this should seem familiar (except for the service providers of course).
This sounds OK to me but I am not sure if it is ACTUALLY OK to do this sort of thing in JavaScript. What advice would you give based on your experience with JavaScript?
If you want to reproduce laravel's pattern - that can be hard - but I can suggest you two technologies that can helps you with it. When you combained them you can easily implement quite similar code conception.
1 TypeScript
In fact you're using it in above code. It's a kind of JavaScript wrapper in which you can write a code similar to Java solutions. You have access here to polymorphism, inheritance and encapsulation like in typical PHP OOP. This can speed up your work a bit and it's pure and it's uses ECMAScript 2015.
2 AngularJS
The large JS Framework which is very strong and have big community. This one privides you for example injection service (like Laravel's IoC) which will automaticcly resolve all your dependencies. You can create easily repositories using $resources which is ajax wrapper for REST API requests. There are service providers that works greate on application load. And the best is that - yo can build one-page-application with Angular. It have many other advanteges. There is stable version 1 and unstable verison 2 which is developed in TypeScript.
With these two tools you can build awesome stuff for the frontend (client side). If you want more tools here it is:
PuppetJS - server side generating client side JS scripts (one implementation fort both sides!).
React - great library based on components
I'm designing the intranet web application for our company. One of the app. requirements is to provide "widget" platform. Which means that developers may create mini application, that will work inside the main web application and can use it's resources. Widgets could be independent of applications and they can have there own data models and behaviors. My task is to provide widget abstraction and widgets engine within application (widgets management and organizing on the application pages). I reviewed several JS "MV*" frameworks and it looks like Ember.js is the thing that I want to use. But I can't understand how to separate in Ember, the abstract functionality between widgets and the application. From one side, the main application is Ember application by itself that manages current widgets appearance, from other, widgets, are applications to. Is it possible to have nested apps in Ember, so can make something like:
Widgets.SpecificWidget1 = Em.Application.extend({
name:"I'm custom widget",
ready:function(){alert('Widget app Ready')}
});
App = Em.Application.create({
rootElement:"#widgetsPanel",
ready:function(){alert('main app Ready')}
});
App.WidgetsController = Em.ArrayController.create({
widgets:[Widgets.SpecificWidget1.create(),
Widgets.SpecificWidget1.create(),
Widgets.SpecificWidget1.create()]
});
App.WidgetsView = Em.View.extend({
});
<div id="widgetsPanel"></div>
<script type="text/x-handelbars">
<ul>
{{#each App.WidgetsController}}
{{#view App.WidgetsView contentBinding="this"}}
<li>{{content.name}}</li>
{{/view}}
{{/each}}
</ul>
</script>
If this way is not correct to do this, can you please tell what is the better way to do it?Thx
It's hard to tell what's happening in the code, but this is my best guess of what you're trying to do. This isn't designed to work as is, but it should put you on the path to what you want to do:
Widgets.SpecificWidget1 = Em.Object.extend({
name:"I'm custom widget",
ready:function(){alert('Widget app Ready')}
});
Assuming this is supposed to be the base model you're working from, the Widget is extending Ember.Object, as that's a tangible thing. As far as I can tell, there's not much to be gained from extending Ember.Application in most use cases, and in a basic scenario where your Ember Application is an entire page, you'll never want more than one.
App = Em.Application.create({
rootElement:"#widgetsPanel",
ready:function(){alert('main app Ready')}
});
App.WidgetsController = Em.ArrayController.create({
widgets : [Widgets.SpecificWidget1.create(),
Widgets.SpecificWidget1.create(),
Widgets.SpecificWidget1.create()]
});
As far as I can tell this is okay.
App.WidgetsView = Em.View.extend({
});
You don't really gain anything from this by itself. If you give it a 'templateName' attribute, you can bind it to a particular template defined in Handlebars to get some functionality, and wrap the general Widget to get a better MVC setup going. But for what you have, you could remove this.
For what I'm working on at the moment, I have a design setup that looks like this Fiddle: http://jsfiddle.net/PastryExplosion/99CMD/
I'm working on a Sencha Touch app, which currently isn't using controllers. I would like to use Ext.Router to take the visitor to a particular card in a panel. I've seen suggestions that it is possible to use the Ext.Router without using a strict MVC setup. But the example in the API looks like this (see: http://dev.sencha.com/deploy/touch/docs/?class=Ext.Router):
map.connect('dashboard', {controller: 'home', action: 'index'});
Is there a way to, for instance, put a function into map.connect that would show a particular card in a panel?
Second question: is it even worth trying to wrestle with this, or would it be easier to update the app with controllers? (It's a pretty small app in the early stages of development, and would probably have 3 controllers if we went that route.)
I had this same question and was hell bent on not using a controller because I had no time to restructure the code I was given. Like the chosen post reluctantly suggested I used the Ext.History class. If you call this in your onReady function it will activate the myPanel panel with the URL: www.mypage.com/#my-url-slug
function initialiseHistory() {
Ext.History.init();
urlToken = Ext.History.getToken();
if(urlToken == 'my-url-slug') {
Ext.getCmp('tabpanel').setActiveItem('myPanel', false);
}
}
Dirty I know.. but did the job.
The Router is kinda married to the controller and doesn't really provide a way to do what you're asking. If what you're trying to do is show a card based on the URL hash then ya go with a controller cause its trivial to implement.. if you're hell bent on not using a controller for some reason the only thing that comes to mind is Ext.History fires a 'change' event when the url hash changes, you could listen for that event and take appropriate action I suppose.