MEAN Stack - pass variables from html view to ng-controller - angularjs

I have developed a profile page which contains several modules such as, let's say : personal info and friends.
Each modules is a ng-controller which makes database calls but I would like to be able to pass the id of the user of whom the profile is being displayed so that database calls are dynamics and retrieve data related to this user.
How I am supposed to do that?
Thanks in advance,
Manuel
* Clarification *
I am using express.js which handles authentication and session management (with Passport).
Once the user is logged in he reaches the "/profile" page.
I didn't particularly want to handle routing on several sides so I decided to handle all routing on Node side. So I have created routes for get and post calls.
Now, when the user arrives on "/profile" I would like the different modules (personnal info, friends, etc.) to update based on the person connected.
I managed to do non-dynamic call :
app.controller('UserInfo', [
'$scope', '$http',
function($scope, $http) {
$http.get("/api/users/info/1")
.then(function(response) {
$scope.user = response.data.local;
});
}
]);
But this doesn't depend on the context. So I would like now to create get calls the same way but being able to pass the id (or any other proper way) of the user to retreive his data.
Would you have any recommendation as to how to proceed? Any link to tutorials on how to handle this in multi-page MEAN application? Most of documents I found on the internet are related to single-page applications and don't answer my need.
Thanks!

If your UI handle who am I, you will get some security breach.
Your server need to know who is connected. (with a cookie or something like that).
Here is an exemple : https://blog.nodejitsu.com/sessions-and-cookies-in-node/

Related

Connecting Two AngularJS App Projects

I need idea on how to create a app structure of two separate Angularjs App folder.
Let's say:
In my XAMPP/htdocs, I have a separate folder of Angularjs App folder. The A app folder and the B app folder need to integrate(I don't know if it is the right term) to each other.
Example, there's a SignIn in A app folder, when the credentials is valid, it will redirect to B app folder, when Signout in B app folder, user will be redirected to A app folder.. something like that..
My question is, How I can connect that two (A and B app folder)?
I hoped I discussed it well enough to understand. Thanks.
You can use services to achieve this objective.
As you have two different apps and you need to create a bridge between them, a good way is to create services that can be injected where you need them.
A AngularJs service is created inside an AngularJs App, by declaring it using your angular module like this:
angular.module("YourAngularModuleName").factory("MyCustomService",
[
"injectedDependency",
function(injectedDependency)
{
var serviceInstance={};
serviceInstance.operationYouNeed = function(){
//do your stuff.
return;
};
return serviceInstance;
}
]);
This service above is a example structure of a service called "MyCustomService" that has a method called "operationYouNeed".
On your AngularJs App controller, you can inject your MyCustomService and call operationYouNeed as you may need it.
Considering the scenario you exposed, I don't know the way you are keeping the logged user context, but you can evaluate the user action on the service method and then call a $location.path("your app2 root url") in order to redirect the user or, if is the case, call a $window.location.href = "your app2 root url" in order to cause a page reload.
In applications that I write, I use to implement a token based authentication and store the temporary toke as a private cookie, so if I had your app scenario, on App2 I would inject $cookies on my Service and use it to retrieve the temporary cookie in order to check session validation and also decide if I need to redirect my user or not.
Another kind of concept you can implement here is to use a third AngularJs app in which you declare your common service, so you don't need to create any dangerous circular reference between your two apps.
I don't know the deepnes of your AngularJs knowledge but you allways need to declare a module dependency whe you does something like this, by including it on your AngularJs app module, like so:
angular.module("YourAngularModuleName",["anotherDepencyModule", "another", ...]);
Hope it helps.
Cheers.

Angular Router - Using abstract state to access service

Using mean.js:
I have a large application that is divided by say, offices. Each office accesses the same application in the same way, but employees of an office may only access information pertaining to that office. Company administrators may access the app fully, switching between office contexts. The caveat is that there are no user accounts (no login/auth) for office employees, only admin accounts for the administrators.
I'm exploring doing it in the following way:
I created an access module with a service that stores the office context, passing it to the backend when making API calls. This is set upon application startup from config files.
This is well and good, but I need to allow the administrators to switch office contexts. I use a link <a ui-sref="Context({ officeID: 'x' }) (in the navbar dropdown, so accessible from every state) to access the angular router:
.state('Context', {
url: '/Context/:officeID',
controller: 'ContextController',
controllerAs: 'vm'
});
This passes the officeID to the ContextController, which would set the ContextService.officeID variable. At this time, I believe I would make an api call from the ContextController to refresh the current state's data to reflect the current context. Not sure how to do that.
I feel that I have some options here, which I am unsure how to implement:
I can make the Context state abstract, and every other state a child, but that seems bulky. If this is correct, how do I tell the current state to refresh it's data?
I could enter the Context state, set the ContextService.officeID, and immediately redirect back to the previous state, which upon entering, should make an api call using the new context. If this is correct, how do I properly perform that redirect?
I could scrap how this is being done entirely, but I don't know where I would start. Any advice is welcome.
I figured out something that feels a bit more elegant.
I still use the Context route. I've included the ContextService in all of my angular modules, and call it when the context needs to be set.
I tried to redirect using $location.path(...), which was a major headache. Using $state.go($state.previous.state.name) works a treat.
Even better, if you use routes that depend on resolves, you can further redirect using $state.go($state.previous.state.name, $stateParams);

Best way to load customer parameters in a multi-tenant angularJS application

We have a multi-tenant Angular JS single page application. The routing for the application uses a customer identifier as part of the URL - #/home/<KEY> or #/search/<KEY>/<search term> for instance. In theory the first page served could be of any type. Each page calls an API using the customer key and other values picked up from the URL to get data for the page. So far so good.
We have some parameters - a logo, copyright statement, default language (for internationalization) - that can be loaded using a separate API call that also uses the customer KEY. These parameters need to be available as strings in partials, to drive the internationalization and perhaps in controllers.
The question is where to call the API to get these parameters and how to set them / make them available for the rest of the app. I have looked at a bunch of questions in this general area but can't find a concrete suggestion. Should we use a config in app.js? Call another script from index.html?
Appreciate people's advice.
The right place would be to make an API call immediately after authentication to get the various Customer specific configuration data like the Customer settings for logo, language and then put them in the session storage of the browser.
I have done an implementation using Microsoft ADAL js as per the documentation given here. https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/README.md.
You can do this Api call in the login success event handler or similar ones in angular.
Example:
$scope.$on("adal:loginSuccess", function () {
$scope.testMessage = "loginSuccess";
});
HTH

Angular adding extra logic to 404 handling on non angular routes

I have an angular site hosted in S3, and I have a 404 route set up (I use hash), if someone for example does
mysite/#/gibberish
goes to
mysite/#/404
and on the s3 bucket we have a redirect rule in place for
mysite/gibberish
goes to
mysite/404.html
all is well
Now I just want to add an extra logic on top that if someone types in
mysite/customerid
which is a 404 to somehow redirect this to an angular controller so I can send this request to right page.
So somehow in my redirect in S3 rule add a reg exp for some incoming request and rather than serve 404.html send it i.e. mysite/#/handlethis
Is this possible ?
Depending on the router of your choice, you could do something like the following (which is what we've done (well, not precisely this, but close)):
ui-router
app.config(function ($urlRouterProvider) {
var regx = /\/#\//; // match against /#/
$urlRouterProvider.otherwise(function ($state, $location) {
if (!regx.test($location.path()) { // if no match
$state.go('customHandlingState', /** params **/, /** configuration **/ });
// Transition to your custom handler state, with optional params/config.
}
});
});
You could pair this up with custom stateChange[Start|Stop|Error|Success] handlers in the run block of your app to customise it to your liking.
I would supply an example of how to do this with ngRoute, but I gave up on ngRoute two years ago and haven't looked back since. As such I have no suggestion to give, nor was I able to find a solution to the problem you present.
I would strongly suggest you scrap the S3 portion of this recipe as it will make your life a lot easier when it comes to client side routing (speaking from personal experience here, it's my opinion on the matter - not fact) and handle your 404's/500's on the client with custom state handlers.
If need be you could hook into some logging service and store some data whenever a client/person ends up in an erroneous state.
I suppose my 'counter question' is; What do you gain from using S3 redirect rules? So as to get a better understanding for the needs and goals here.
Some reference material to go along:
ui-router#$state.go
ui-router#$urlRouterProvider.otherwise
I would suggest using routeParams
https://docs.angularjs.org/api/ngRoute/service/$routeParams
the route would look like this:
/mysite/:cid
then access the id with the controller:
$routeParams.cid
I hope this could help
You can manually configure your server to always serve your index.html(your main html file which includes reference to angular script) on all incoming http requests. Client routing will be handled by Angular

AngularJs authorization layout

I am building a large application with Web API and AngularJs. I built the secure web api with authentication and claim-based authorizations. One requirement is that different users can view different modules on the same template.
I am new to AngularJs. I did the authentication in client side with the tokens. Also, in web api, I created a service to get all the permission given a user id. The response is a list of resource(contoller)/action(method) pairs. How do I implement the correct layout based on authorization rules on client side? Does that solely rely on web api permissions response and show/hide (ng-hide/ng-show) content based on the permissions?
Is this a good approach? What other modules/directives do I need to look into? Such as the loader for not loading the nested route until user request the parent route.
To add complexity, this site also need to work in bi-lingual. I think ng-translate. I mentioned this because it may open up another discussion on whether this may favor MVC instead of AngularJs. But the preference is Angular if the above two problem can be resolved.
All the authentication & authorisation & validation should be done server-side. You can adjust the user interface based on the roles/claims the server tells the browser the current user has.
One way to do this is to create something like a roles/userprofile controller, which will respond with a list of roles the current user has. On the client side you’ll probably want something you can inject everywhere, so you’re able to determine user interface behaviour.
myApp.factory(‘myUser’, function(Roles, $q) {
// Create a promise to inform other folks when we’re done.
var defer = $q.defer();
// For this example I’m using ngResource
Role.query({
/*
No params — let the server figure out who you ‘really’ are.
Depending on WebApi configuration this might just be
as simple as this.User (in context of the controller).
*/
}, function(roles) {
var user = {
roles: roles,
isInRole: function(role) {
return user.roles.indexOf(role) !== -1;
}
};
defer.resolve(user);
});
return defer;
});
Because the factory above is returning a promise we can enforce that myUser is resolved before a certain route/controller instance is created. One little trick I use is to gather all my route definitions in one object, loop through them with an angular.forEach and add a resolve.myUser property to each of them. You can use this to pre-load/initialize other stuff too.
Now inject the myUser anywhere you like:
myApp.controller(‘MyController’, function($scope, myUser) {
// Expose it on the current scope
$scope.myUser = myUser;
});
… and in your markup …
<div class=“my-content-thingy”>
<p>Lorem del ipsum …</p>
<button class=“btn” ng-if=“myUser.isInRole(‘content-editor’)”></button>
</div>
Note: You’ll probably want to use ng-if and not ng-show; the latter keeps the element in the DOM.
Just keep in mind that you don’t authenticate anything on the client side; that all done server side. A simple way is to place Authorize attributes on the appropriate controller actions.
Hope this helps.
A proper approach is to build AngularJS routing configuration as per Authorization on the server. This should be build just after the user is authorized and before the AngularJS app is initialized. That way the authorized user sees a "complete" app based on his roles etc. Using ng-show/ng-hide is not a good way to do it. Also each view should be doing only one thing. So load separate views based on the task that needs to be completed.
Regarding multi language support, this is independent of Authorization. Some time ago, I wrote a custom AngularJS filter that used the jQuery i18next plugin. It was a pretty simple implementation.
However you can now use https://github.com/i18next/ng-i18next
(Sorry for misunderstanding the problem).
I think that using ng-hide/show is not much of a problem. At the end of the day, the user does not have access to the data. I think it should rely on the api permissions + show/hide of presentation. Depends on the complexity you want... You can use MVC with angularjs since it's a large application.

Resources