Angular: Multiple templates for single URL? - angularjs

I have a 'manager' panel which is used by users of all roles (admin and user currently).
The main problem is that I want to restrict any admin HTML views from being loaded (I will do this as a simple check on the backend, and will return 401 if they're not authorized to load the template). There are a bunch of things in the HTML I need to hide.
My problem is that means there are now 2 views for several sections.
So /settings while a user will show an entirely different view as /settings when you're an admin.
The controller will actually be shared, because the controller code is very close, but the HTML is very different.
I am currently using angular-router but I also checked out ui-router, I just have no clue how to structure either. I've spent a good bit of time looking at UI router, and while it is amazing looking I don't know the best way to lay it out.
I have about 10 routes/views that need to belong to each role, that will be different.

How about emitting a global variable says the current user is admin:
<script type="text/javascript">window.isAdmin = true</script>
And then in the route definition check for that variable:
...
when('/setting', {
templateUrl: isAdmin ? 'templates/admin/setting.html' : 'templates/user/setting.html',
controller: 'SettingController'
})
...
The other way around is to have the web server serve different view for the same view URL, based on user's role. As I understand you can do this already, right?
app.get('/templates/setting.html', function(req, res) {
if (user.role === "admin") {
res.send(...);
} else {
res.send(...);
}
});

Related

Restrict access to a page in Gatsby.js to logged in users

On my gatsby.js static site, I want to restrict access to my pages/dashboard page using client-side authentication. The plug-in, gatsby-plugin-meta-redirect says that I can create a redirect with this...
createRedirect({ fromPath: '/old-url', toPath: '/new-url', isPermanent: true });
...but I'm not sure where to place that in my code. I'm assuming gatsby-node.js, but I'm not sure how.
I want to do something like this,
if (user.loggedIn) {
// redirect to '/dashboard'
} else {
// redirect to '/'
}
This is assuming that the state of user is available throughout the site. Is this possible?
Also, in the gatsby-plugin-meta-redirect docs, it states that this plugin should be put last in the array in gatsby-config.js. But I already have gatsby-plugin-netlify placed last. Would that be a problem?
What you can do is give a programmatic, non-direct access to the /dashboard page using navigateTo in Link.
See this issue.

Angularjs route html5Mode direct url in .net MVC

I've seen a couple of similar questions/answers, but I still seem to be missing something. Everything works fine until I refresh the page or go to a URL directly.
I can either get a 404 or create the same url in mvc, but then it serves up the partial only on refresh and doesn't include the layout page.
There were a couple that suggested changing the MVC routing to:
routes.MapRoute(
name: "Application",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
When that is implemented, it means I can't access any other URL on the site normally and unless I am missing something, basically everything has to be put into a rest api or write a custom route for every url. Neither sounds very good.
So how can I have an html5 url (no hash tags in valid browsers) with angularjs and be able to browse to eg. Home/About or Home then click a link to About and have them show up the same with the same base layout page?
This may not be the best answer, so if anyone has any better ideas, please comment, otherwise maybe this will help someone else.
I realized that the MVC Ajax directive didn't detect angular calls, so I couldn't automate that side.
So in angular I did something like
.when('/Home/Contact', {
templateUrl: '/Home/NgContact'
In my MVC controller I have 2 actionresults:
public ActionResult NgContact(){
ViewBag.IsFromNg = 1;
return Contact();
}
public ActionResult Contact() {
return View("Contact"); //have to type in name, may look for NgContact.cshtml
}
Finally on any views these may call I put:
#if (ViewBag.IsFromNg == 1){ Layout = null; }
So there is a little repetition with each Actionresult having 2 copies, 1 for a full page load and 1 for any calls angular makes, but only 3 extra lines each.

How to deal with templates of completely different areas (but same website) with AngularJS

I have a webapp with a main index.html that shows each page through an ng-view and a routeProvider.
Now I'm adding an entry page for users who are still not logged in. This page could also have his own ng-view to slide different sections for non logged users (welcome, what is, sign in, sign up ecc...) and his own head with css scripts ecc...
I'd rather that both the webapp index and the entry page index address to www.example.com (so nothing like www.example.com/welcome ).
I thought about a structure similar to this:
webapp/
main/
page1/
page2/
welcome/
section1/
section2/
index.html
welcome.js (angular module for the entry page)
.htaccess
index.html
webapp.js (angular module containing the routeProvider for the webapp)
Currently I have that .htaccess that rewrites all the fake queries to index.html so that everything is handled here.
So in particular:
1) How can I say to the routerProvider of webapp.js to go to /welcome/index.html when the user is not logged in, if I already use this condition for the webapp main page? (Should I use the run method? a brief example will be helpful)
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when(...)
.when('/', {
templateUrl : 'main/webapp-main.html'
})
.when(...)
2) How do I prevent that everything in welcome/index.html will be loaded within the index.html ng-view? (maybe using ng-if to hide ng-view? or there is some way to control this behavour with the routerProvider?)
3) There is a better and simpler way to achieve all of this?
Thanks.
Update:
Ok I think there was an underlying problem in my question... I can't use a complete different page since everything is loaded in and switching to another page will cause the reload of the app loosing all the data.
So I suppose I should use the same main template for the entire website.
Then I add: there is a way in angularjs to load different style sheets dynamically?
this questions is old but i think is valid and can clarify someone a few thinks.
First of all you are suppose to use a single page for AngularJS apps, otherwise you will have to do something like a redirect link, and in your other-index.html load an entirely different Angular Application also loading every script needed in the first one.
1) Use ui-router is easy to work, and very robust, the only thing you need to have is a container for your ui-view then the ui-router will fill the container with the corresponding html
2) To prevent navigation you should do something like this:
angular.module('myApp', [])
.run(function($rootScope, mySessionService){
$rootScope.$on('$stateChangeStart',
function(event, next, nextParams, prev, prevParams) {
// The info of your currentUser could be obtain from a service
// or localStorage or cookies anyway you are already doing it
var authorized= checkAuthorization(next.authorazedRoles,
mySessionService.getCurrentRol());
if(!authorized) {
$rootScope.$state.go('defaultState');
// Or $rootScope.$emit('NOT_AUTHENTICATED');
// and some service will have to implement a listener for this emit
// $rootScope.$on('NOT_AUTHENTICATED', func..redirect to X State)
}
});
});

How to redirect in AngularJS without rendering template

I'm trying to redirect to an external page from my AngularJS file if the user enter a special url, for instance /test. I have gotten this to work in multiple different ways but all the different ways show a "flash" of the design from index.html. I would like it to go direct without rendering any html at all!
Here is a fiddle of one of the examples, but it is not the best place to test since I cant redirect from jsiffle.net :-)
$routeProvider.when("/test", {
resolve: {
controller: "Redirect"
}
});
Also had one example where I just used a controller and a empty template in the routing, but it gave me the same result.
Any ideas?
If you know the URL(routing) then use,
$location.path('the_URL');

Backbone.js change url without reloading the page

I have a site that has a user page. On that page, there are several links that let you explore the user's profile. I'd like to make it so that, when one of those links is clicked on, the url changes, but the top third of the page containing the user's banner doesn't reload.
I'm using Backbone.js
I have a feeling that I'm in one of those situation where I have such a poor understanding of the problem I'm dealing with that I'm asking the wrong question, so please let me know if that appears to be the case
My mistake was assuming that there was a special, built-in way of doing this in backbone. There isn't.
Simply running the following line of code
window.history.pushState('object or string', 'Title', '/new-url');
will cause your browser's URL to change without reloading the page. You can open up the javascript console in your browser right now and try it with this page. This article explains how it works in more detail (as noted in this SO post).
Now I've just bound the following event to the document object (I'm running a single page site):
bindEvents: () ->
$(document).on('click', 'a', #pushstateClick)
pushstateClick: (e) ->
href = e.target.href || $(e.target).parents('a')[0].href
if MyApp.isOutsideLink(href) == false
if e.metaKey
#don't do anything if the user is holding down ctrl or cmd;
#let the link open up in a new tab
else
e.preventDefault()
window.history.pushState('', '', href);
Backbone.history.checkUrl()
See this post for more info.
Note that you CAN pass the option pushstate: true to your call to Backbone.history.start(), but this merely makes it so that navigating directly to a certain page (e.g. example.com/exampleuser/followers) will trigger a backbone route rather than simply leading to nowhere.
Routers are your friend in this situation. Basically, create a router that has several different routes. Your routes will call different views. These views will just affect the portions of the page that you define. I'm not sure if this video will help, but it may give you some idea of how routers interact with the page: http://www.youtube.com/watch?v=T4iPnh-qago
Here's a rudimentary example:
myapp.Router = Backbone.Router.extend({
routes: {
'link1': 'dosomething1',
'link2': 'dosomething2',
'link3': 'dosomething3'
},
dosomething1: function() {
new myapp.MyView();
},
dosomething2: function() {
new myapp.MyView2();
},
dosomething3: function() {
new myapp.MyView3();
}
});
Then your url will look like this: www.mydomain.com/#link1.
Also, because <a href=''></a> tags will automatically call a page refresh, make sure you are calling .preventDefault(); on them if you don't want the page to refresh.

Resources