Load view without refreshing the page - angularjs

I am running angular 1.5 spa application with angular-ui-router, where I load states as the user clicks on links. My application has subdomains like subdomain.domain.com. What I want is to load a state across the subdomains. Like if I am on a state subdomain1.domain.com/view/view1 and has to go to subdomain2.domain.com/view/view2, can there be a possibility to load the state without having to reload the whole angular app. I saw something like $window.history.pushState, but that does not work with subdomains. All the different subdomains use the same piece of angular code, means all the subdomains are pointing to the same server (managed through AWS)

I think it's not related to angularjs, when you go to subdomain2.domain.com you are going to a whole different web domain, it's not different from going to www.google.com, so angular can't treat it like a sub-page navigation in the same domain.
I think a similar effect may be achieved using templateUrl's though, just put your needed view templates on second domain address like:
angular.module('myApp', ['ngRoute'])
.config(function($routeProvider){
$routeProvider.when("/something",
{
templateUrl: "http://subdomain1.domain.com/view/view1.html",
controller: "AppCtrl1"
}
).when("/somethingElse",
{
templateUrl: "http://subdomain2.domain.com/view/view2.html",
controller: "AppCtrl2"
};
})
But the main app still resides on the same domain.

Related

Angularjs: use config only for one controller

On one page I load content via ajax according to user picks (filters), to ensure that loaded content stays in place if user reloads or lands on the page, I put the picked filters into the url query string. Since I load the content via ajax on this particular page I don't need to reload the entire page every time a new filter is picked by the user, so I prevent browser to react on url change with the following config:
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
}]);
However this affects the entire app and prevents all other pages from reloading on url change, the behavior I don't want. How can I make this configuration to affect only one particular controller within my app?
If your goal is to prevent reloading the page when the query string changes, html5Mode is entirely the wrong tool for the job. You want reloadOnSearch: false which can be applied globally or to individual routes:
$routeProvider
.when('/foo', {
controller: 'fooCtrl',
templateUrl: 'foo.html',
reloadOnSearch: false
},
...
);
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
From Angular's documentation on $locationProvider, maybe the cause of that behavior is by design:
rewriteLinks - {boolean} - (default: true) When html5Mode is enabled,
enables/disables url rewriting for relative links.
If your app is reacting to the url to make a change as a sort of RESTful api I would recommend using ngRoute or even better uiRouter.
Hope that helps.
This is a tricky situation, and you might not like my suggestion; heck I don't even like this suggestion because it breaks the whole awesomeness of a single page application.
But what you could do, is to create a separate html file (lets call it pick-filters.html). On that new html file, have a new ng-app and therefore a separate app.js file for this particular page. In this new app.js file (lets call it pick-filters-app.js), you can use the app.config snippet that you have shown here. This should fix your problem of all pages not reloading because only pick-filters.html is referencing pick-filters-app.js which has this config snippet.

SaaS app with angularjs and nodejs, how do i organize different clients?

I’m trying to decide what to do I this scenario:
I want to create a product that I want to sell in a SaaS business model, I already have the backend more or less thought out and some code in place in nodejs. It handles oAuth, sessions, and controls the roles of the users when accessing a certain endpoint.
The doubt is in the frontend architecture:
Each client will share the same functionality, but the design of their page will be completely different from one another.
I want to put as much of the app logic that I can in services, so I can reuse it, my idea is to only change controllers/templates/directives from client to client, is this ok?
Should I have different folders and serve the static files for each client from nodejs?
ex:
in nodejs I would know the url for client1 was called so I would serve client1-index.html?
should I put each client in their own nodejs server and their own host?
what other ways are there?
I would like to be able to easily reuse the services as I’ll be introducing changes to the features or adding more, and I want to do this upgrades easily.
There will also be an admin panel that will be exactly the same for all of them, the part that will change is the one my client's users see.
Think of it as having many clients and giving each of them a store, so they can sell their stuff. They want an admin page and a public page. The admin page will the same for all, but the public page has to change.
So, and app that shares the same functionality across users but looks completely different for each one of them, how would you do it?
Since You seem to be using Angular, have you thought of using the routing service? See more about it Here : https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
Basically what it does is it based on the url loads a html page and a controller (JS file). For example if your user would just be move to url.com/client1 and angular would load client1.html and client1CTRL.
A Simple Structure would be the following:
Index.Html- References to any dependencies, and in the body only a ng-view tag
Templates (The Html Templates for each of the users)
Login
Admin
Client 1 etc...
Scripts (JS)
External Scripts (Jquery, Angular ETC)
Index.js ( This is where you would have all your js controllers for each page)
Stylesheets
CSS FILES GO HERE
Example Angular Routing: Tutorial
var App = angular.module('saasApp', []);
App.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/admin', {
templateUrl: 'templates/admin.html',
controller: 'AdminController'
}).
when('/client1', {
templateUrl: 'templates/client1.html',
controller: 'client1Controller'
}).
when('/login', {
templateUrl: 'templates/login.html',
controller: 'loginController'
}).
otherwise({
redirectTo: '/login'
});
}]);
Hope this works for what you are trying to do.
I guess your question is about Architecture. If I were to do same back-end and different front ends I would've implemented virtual template structure.
Permissions
I would have:
a super user that has rights to setup multiple stores.
an admin user that can manage a particular store
Super User template management.
I would have base templates in /admin/templates and when I create a new store I would copy them and stick them in database
I would create a menu with all the templates on the left hand side and have wysiwyg editor that allows me to modify those template for particular customer and upload additional assets (images, pdfs etc)
Template would support swig syntax
I would create a server route /get/tempalte/:id and dynamically parse those templates on server using swig engine
I hope this helps. The key here is to be able to update templates via browser and distribute them to new shops/customers via web panel.

How i can maintain angular-fullstack client and admin different template

I want to use different different types of template in client side and admin side using angular-fullstack.
Can you please let us know how i can achieve this. My routes look like Ex:
www.sitename.com - main site with theme1 (http://demo2.jlvextension.com/probusiness/)
www.sitename.com/administrator - administrator dashboard with theme2 (http://www.theme-guys.com/materialism/angular/)
It seems to me like you're trying to create two very different front ends. I recommend building two different angular applications that utilize the same api's and domain. You could put an entire admin angular application at www.[sitename]/admin.
We also had a requirement like this and initially we had both in one SPA, where we distinguished each page by URL. The URL 'admin/login' loaded admin login page while '/login' loaded the login page for others. The $routeProvider config is given below.
$routeProvider.when("/admin/login", {
templateUrl: "app/admin/login.html",
controller: "AdminCtrl"
}).
when("/login", {
templateUrl: "app/user/login.html",
controller: "LoginCtrl"
}).
Later when the application became big and difficult to maintain, we ported the admin part to a separate application like Gabriel suggested above.
you can resolve this problem with creating a directive with different
templates,This plunker should demonstrate what needs to be done,
but basically:(you should just change the value of isAdmin property
to simulate ). good luck

Using UIRouter templates with MVC 4 Routing

I'm trying to create an ASP MVC 4 project with Ui-Router, however I've come across a problem.
My current server-side routing configuration looks like this:
// Controller/Action route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}");
// Redirect any other routes to Site/Index so AngularJS can handle routing
// Place routes above this otherwise they will be ignored
routes.MapRoute(
name: "Catch-All Redirect to Index",
url: "{*url}",
defaults: new { controller = "Site", action = "Index" }
);
And client-side
angular.module('loluk.home')
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('index', {
url: '',
templateUrl: '/home/index'
});
}]);
Site/Index, the redirect action, simply contains the HTML file that has the ng-app directive. Any other actions/controllers will return API data, or a template. So, in my case, I have Home/Index which returns a template containing <h1>Hello, World!</h1>.
This is all fine and dandy if one of my states in ui-router requests "home/index" via templateUrl for my application. However, the problem I have now is that if I browse to http://localhost/Home/Index, I will see the template in it's raw form - rather than what I am expecting to see, which is the whole application in the Home/Index state. This makes sense as that is how I have configured it.
I initially thought "OK, well I can solve this problem by redirecting everyone to Site/Index (where the main file is stored) and using inline templates". Well, this works well, until you consider that
The HTML file containing index.html is going to get ridiculously large and contain every template
This breaks escaped_fragment crawling
So right now I am at a loss of how to make this work; I could use inlining, but that would make web pages load slowly and break SEO. I could stick with what I have.. but that will break any bookmarks that end-users create.
Making template calls a ChildActionOnly worked well until the fact that ChildActionOnly will return a server 500 (rather than a redirect), and UI-Router appears to not qualify as a "Child Action" as requesting the template through templateUrl also triggered the server 500.
I did come across this question, however it doesn't express how exactly to solve the template situation.
Another avenue I have just pursued is having a templates area that contains all of my templates, and an api area that contains all of my api details (/templates/ and /api/ respectively). This solves the whole reloading page problem, though I am still unsure of how to approach the escaped_fragment crawling from this point of view.
I've accomplished this by creating two Areas in MVC - one for API that routes to /api/ and one for Templates that routes to /templates/. AngularJS will make calls to /template/{controller}/{action} which will return a plain HTML view, and make RESTful calls to /api/{controller} for retrieving data.
It's not a perfect solution but it works.

How can I handle a browser refresh in an AngularJS SPA application?

My AngularJS application uses
ui-router
an index.html file
all calls for login and data go to an ASP.NET Web Controller with a URL that starts with /api/xxx.
When a user enters myapp.com then the server index.html which is what I want. When the user now selects links on that page then ui-router shows the appropriate templates inside the index.html and the browser URL bar correctly displays addresses like these:
myapp.com/home
myapp.com/home/overview
myapp.com/city
myapp.com/city/london
Note that my configuration is set up like this:
.config([
'$httpProvider', '$locationProvider', '$sceProvider', '$stateProvider',
function (
$httpProvider, $locationProvider, $sceProvider, $stateProvider) {
$sceProvider.enabled(false);
$locationProvider.html5Mode(true);
If a user now clicks on refresh then the browser forgets that it was on index.html and tries to find the web page: myapp.com/city/london etc which of course does not exist. It then shows an error page saying the page does not exist.
How can I handle this situation? I would like a user clicking on myapp.com/city to refresh and ideally go back to myapp.com/city
EDIT
When you use HTML5 modle ruting with angular you must tell your server how to handle the request If you arrive at one of those routes, for example if you try to go to myapp.com/city you will get an error because the server is going to look for a city.html page at the root of the server which won't be there. If you navigate to that route from within your app it will work fine, but if you copy and paste that into your browser address bar you'll get a 404 because the server does not understand how to get to city.html. An easy fix would be to avoid using HTML5 routing mode. According to the angular docs you need to do some URL rewriting to make your server understand how to route to those pages:
From the docs:
Using HTML5 mode requires URL rewriting on server side, basically you
have to rewrite all your links to entry point of your application
(e.g. index.html)
You can also have a look here, this answer discusses how to get HTML5 routing working with your server.
when the user refreshes the application, you can lead them to login page or default page. which can be done by the following code.
app.run(['$location', function ($location) {
$location.path('/login');
}]);

Resources