how to implement google+ sign-in with angularjs - angularjs

I have an AngularJS app, and I want to implement G+ sign-in. I've gone through their samples, and they work as standalone apps.
https://developers.google.com/+/web/signin/
In my Angular app, I am able to display the G+ sign-in button. But I'm stuck on the callback. Do I put the callback function in my controller js file?
If so, and given this controller:
app.controller('myController', function ($scope) {
function signinCallback(authResult) {
On my data-callback, how do I name it so that it goes to signinCallback inside myController?
<span id="signinButton">
<span
class="g-signin"
data-callback="signinCallback"
data-clientid="123456789.apps.googleusercontent.com"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read"
</span>
</span>

The Google+ PhotoHunt sample app demonstrates an AngularJS integration with Google+. The sample is available in Ruby, Java, Python, and C#/.NET for web.
Of note should be the following code in the AngularJS front-end:
Markup to render the button in:
<span id="signin" ng-show="immediateFailed">
<span id="myGsignin"></span>
</span>
JavaScript to glue the markup to code:
$scope.signIn = function(authResult) {
$scope.$apply(function() {
$scope.processAuth(authResult);
});
}
$scope.processAuth = function(authResult) {
$scope.immediateFailed = true;
if ($scope.isSignedIn) {
return 0;
}
if (authResult['access_token']) {
$scope.immediateFailed = false;
// Successfully authorized, create session
PhotoHuntApi.signIn(authResult).then(function(response) {
$scope.signedIn(response.data);
});
} else if (authResult['error']) {
if (authResult['error'] == 'immediate_failed') {
$scope.immediateFailed = true;
} else {
console.log('Error:' + authResult['error']);
}
}
}
$scope.renderSignIn = function() {
gapi.signin.render('myGsignin', {
'callback': $scope.signIn,
'clientid': Conf.clientId,
'requestvisibleactions': Conf.requestvisibleactions,
'scope': Conf.scopes,
'apppackagename': 'your.photohunt.android.package.name',
'theme': 'dark',
'cookiepolicy': Conf.cookiepolicy,
'accesstype': 'offline'
});
}
Within processAuth, you should see an access token and can update your UI to reflect this. You can also see the full controller's JavaScript code on GitHub.

I am not sure if this works, but I would try it like this:
module.factory("GPlusAuthService", function ($q, $window) {
var signIn;
signIn = function () {
var defered = $q.defer();
$window.signinCallback = function (response) {
$window.signinCallback = undefined;
defered.resolve(response);
};
gapi.auth.signIn({
clientid: "123456789.apps.googleusercontent.com"
cookiepolicy: "single_host_origin"
requestvisibleactions: "http://schemas.google.com/AddActivity"
scope: "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read",
callback: "signinCallback"
})
return defered.promise;
};
return {
signIn: signIn;
}
});
module.controller('myController', function ($scope, GPlusAuthService) {
$scope.signIn = function() {
GPlusAuthService.signIn().then(function(response) {
});
}
});
<span id="signinButton" ng-controller="myController">
<span class="g-signin" ng-click="signIn()"></span>
</span>

Function that is going to be called after user agrees to sign in is specified in data-callback, this function needs to be globally accessible, that is bound to window object.
Accessing global object from controller is an anti-pattern, as a middle ground you can use $window provided by Angular, which you can mock in your tests

Related

How to pass data from one view to another with Angular

I need to pass data between views. I have a view where you check items and then another view where those items you can check get put. The problem is you lose all data when you redirect to another page so I lose all the data on the checked items.
Possible solutions?:
Calls to DB to save all the items and then just deleting when done (Seems improper and wasteful use of server)
Someone told me to you can actually POST to a page and then redirect
Saving the Data in an Angular Service (I tried this by just saving a number in a variable but it didn't seem like it worked. Saw this on another SO post)
EDIT:
I just saw something about a AngularJS factory but it doesn't seem like it work with dynamic data and It seems like I tried that with the service thing and it didn't work.
Also here is the code for the service testing. Theres also just the controller methods calling the GetTest and test methods.
MutualService
var test = function (data) {
test1 = data;
console.log(data);
};
Test: function (data) {
return test(data);
},
GetTest: function () {
return test1;
}
View1
<button style="float: right; margin-bottom:20px;" class="btn btn-sm btn-primary" onclick="changeLocation()"> Change Location</button>
<button style="float: right; margin-bottom:20px;" class="btn btn-sm btn-primary" ng-click="vm.Test(2)"> Purchase Order</button>
<script>
changeLocation = function () {
window.location.href = '/Purchasing/Manage/CreateEditPurchaseOrder';
}
</script>
So what you can do here is create an AngularJS Service with the value to share. Inject the Service into either a controller or directive for each view. Then by assigning the service variable to both Scopes you can have the same variable in both places.
angular.module('myModule')
.service('Test', [
function () {
var test = this;
test.myValue = 'default';
return test;
}
]
);
angular.module('myModule')
.directive('viewOne', [ 'Test'
function ( Test ) {
return {
restrict: 'E',
templateUrl: 'my/path/to/viewOne',
scope: {},
link: function ( $scope ) {
$scope.myValue = Test.someValue;
}
};
}
]
);
angular.module('myModule')
.directive('viewTwo', [ 'Test'
function ( Test ) {
return {
restrict: 'E',
templateUrl: 'my/path/to/viewTwo',
scope: {},
link: function ( $scope ) {
$scope.myValue = Test.someValue;
}
};
}
]
);
You can use Tempdata for passing data from one view to another view.
Please check below answer.
public ActionResult Index()
{
var model = new Review()
{
Body = "Start",
Rating=5
};
TempData["ModelName"] = model;
return RedirectToAction("About");
}
public ActionResult About()
{
var model= TempData["ModelName"];
return View(model);
}
for check below link also
http://www.squaredroot.com/2007/12/20/mvc-viewdata-vs-tempdata/

implementing advertisement directive in angular js

I am a newbie angular. I am working with an angular application. My client requirement is to add an advertisement in some pages. I have the data like position for advertisement, advertisement image etc. I would like to implement this functionality as creating an angular directive. So I can call this directive as tag in my pages. So can anyone tell how to write this directive?
Please see the code below:
zentieraDirectives.directive('advertisement',function($http,$rootScope){
$http.post($rootScope.STATIC_URL + 'admins/getadvertisement').success(function(response){
console.log("success advertisement");
return {
template: 'Name: <img src="https://angularjs.org/img/AngularJS-small.png" /> <span ng-click="closeAdvertisement()">X</span>'
};
}) .error(function(err){
console.log("Error"+err);
});
});
When I check on console, I got "success advertisement", but not returned the template. I checked this on another way
app.directive('advertisement', function() {
return {
template: 'Name: {{advertisement}} <img src="https://angularjs.org/img/AngularJS-small.png" /> <span ng-click="closeAdvertisement()">X</span>'
};
});
My need is that, on the success of api call to node, I have to return the template. My view page is
<h1>advertisement</h1>
<advertisement ng-show="advertisementShow"></advertisement>
app.directive('navBannerTop', ['NavBannerServiceTop','$rootScope', function (nbs,$window) {
return {
restrict: 'E',
//scope: true,
scope: {},
template:' <div> <img ng-src="{{zentieraUrl}}/assets/images/adBanner/{{banner_pic_url}}"></div>',
link: function ($scope,$element,$attr,$rootScope) {
var imagePosition=$attr.imageposition;
nbs.getImage(imagePosition).then(function(result){
$scope.banner_pic_url = result.data.banner;
});
}
};
}]);
Finally I have solved the problem. First I create a directive. In that directive, I returned a template. The directive uses a service too.
app.service('NavBannerServiceTop', ['$http', '$q', function ($http, $q,$rootScope) {
var deferred = $q.defer();
var service = {};
service.getImage = function (imagePosition) {
var params={
position:imagePosition
};
$http.post(Config.STATIC_URL + 'users/getadvertisement',params).success(function (data) {
var adImage=data.data.banner;
var advlink=data.data.advlink;
deferred.resolve(data);
}).error(function () {
deferred.reject('some error');
});
return deferred.promise;
};
return service;
}]);
In the service, I take the data from server, ie the image url.This image url is passed to directive. In the view side I call the directive as a custom tag.
I create a little example of this
http://embed.plnkr.co/HD0KGabjWoq7bnwGaN5E/
I create a directive for the advertisement, and the "X" is for close this.
The functionality is in the controller (this not recomend but is for example).
I hope solve your doubt

$http.get method not working on ng-submit

I want $http.get method to work when a form is submitted.
Here is my code. The object $scope.questions is being set when the method is called but the data doesn't show up in the div. Moreover, when the $http.get method is outside the signIn() function it works just fine.
$scope.signIn = function(data) {
$location.path('/profile');
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(questionData) {
$scope.questions = questionData;
console.log($scope.questions);
});
};
<div>
User Profile
<br/>Question Posted
<br/>
<input ng-model="query.title" id="value" type="text" placeholder="Search by Title..." ">
<div>
<ul>
<li ng-repeat="question in questions | filter: query ">
{{question.title}}
</li>
</ul>
</div>
<br/>
</div>
You need to move your $location.path('/profile') inside your http request. Remember that a http request is async call. You should redirect after getting the data not before.
$scope.signIn = function(data) {
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(questionData) {
$scope.questions = questionData;
console.log($scope.questions);
$location.path('/profile');
});
};
If you're redirecting to another route with a completely separate scope you will lose any scope you're setting in the success handling.
From what I'm reading you're clicking a button to do an action. After that action you're redirecting to another page with a separate controller and trying to persist the data.
Unfortunately, Angular hasn't figured out a great way to do this. The easiest way to persist data through controllers and scope is to create a service that will store it in one controller and grab it in another controller.
For instance:
$scope.signIn = function(data) {
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(questionData) {
$location.path('/profile');
storageService.store("question", questiondata)
});
};
Your new factory to persist data through:
angular.module('moduleName').factory('storageService', [
function () {
return {
store: function (key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
get: function(key) {
return JSON.parse(localStorage.getItem(key));
},
remove: function(key) {
localStorage.removeItem(key);
}
}
}
]);
Other controller to access data:
$scope.question = storageService.get("question");
// remove localstorage after you've grabbed it in the new controller
storageService.remove("question");
An alternative to doing the somewhat 'hacky' way of using localStorage to persist data through controllers is to use ui-router and have a resolve on the route you're redirecting to.
For instance:
$scope.signIn = function(data) {
$state.go('profile');
};
In your route file:
.state('profile', {
url: '/profile'
controller: profileControllerName,
templateUrl: 'profileHtmlTemplate.html',
resolve: {
'questions': [function() {
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(res) {
return res.data;
});
}]
}
}
In your profile controller:
Inject your 'questions' resolve into your controller and assign `$scope.question = questions;
This will make the HTTP call as soon as you click the route, return the data if successful, then render the page. It will NOT render the page if the resolve does not return success. This will ensure your data will be loaded before you load the page that depends on that data.
I would highly recommend using services to hold your HTTP calls for specific parts of your application. If you have a GET questions, POST question, PUT question. I would create a questionService and make all my HTTP methods there so you don't have to clutter your routes. You would only have to call:
.state('profile', {
url: '/profile'
controller: profileControllerName,
templateUrl: 'profileHtmlTemplate.html',
resolve: {
'questions': [function() {
return questionService.getQuestions(id).then(function(res) {
return res.data;
})
}]
}
}

Refresh a Bootstrap navbar using AngularJS

I am currently developing a new project that uses AngularJS and Twitter Bootstrap 3.0 for styling.
The project also uses ASP.NET MVC WebAPI to provide a RESTful API with role based security as well as generating bearer and refresh tokens using Owin and OAuth.
One of the key aspects of the project is that it must be able to refresh the navbar menu by adding and/or removing menu options depending on the roles/permissions assigned to individual users. If a user is currently logged into the application and a system administrator decides to add or removed roles for the logged in user I would like AngularJS to automatically reload the navbar, which will magically show or hide options based on the roles the user has.
I do not know very much about AngularJS at this point and would like to know if this is possible? I have heard something called $scope.apply() and that it could be used for this, but as an inexperienced AngularJS user I am not sure how this could be used.
This is a portion of my view that displays the menu bar, and as you can see I am using functions to show/hide menu options. I'd like these functions to be re-evaluated again if their values change once a new refresh token has been generated by a WebAPI call.
<li data-ng-if="isAuthenticated()" class="dropdown">
Invoice <b class="caret"></b>
<ul class="dropdown-menu">
<li><a data-ng-if="isUserInInvoiceRole()" data-ui-sref="addInvoice">Add Invoice</a></li>
<li data-ng-if="isUserInInvoiceRole()" class="divider"></li>
<li><a data-ng-if="isUserInCreditNoteRole()" data-ui-sref="addCreditNote">Issue Credit Note</a></li>
<li data-ng-if="isUserInCreditNoteRole()" class="divider"></li>
<li><a data-ui-sref="showDaybook">Daybook</a></li>
<li class="divider"></li>
<li><a data-ui-sref="showCustomerLedger">Customer Ledger</a></li>
</ul>
</li>
At present the only way I can force the navbar to be refreshed is by doing a page refresh via F5, which proves that the role based system works, but I'd like it to work automatically by reloading the navbar.
Controller
'use strict';
appModule.controller('indexController', ['$scope', '$state', 'authService',
function ($scope, $state, authService) {
$scope.isAuthenticated = function () {
return authService.isAuthenticated();
};
$scope.isUserInCreditNoteRole = function () {
return authService.isAuthenticated() && authService.isUserInCreditNoteRole();
};
$scope.isUserInInvoiceRole = function () {
return authService.isAuthenticated() && authService.isUserInInvoiceRole();
};
$scope.isUserInOrderRole = function () {
return authService.isAuthenticated() && authService.isUserInOrderRole();
};
$scope.isUserInAdminRole = function () {
return authService.isAuthenticated() && authService.isInAdminRole();
};
}]);
Auth service
Here is the auth service with the relevant code. Bear in mind that the [roles.xxx] are just constants.
'use strict';
appModule.factory('authService', ['$http', 'roles',
function ($http, roles) {
var authServiceFactory = {};
var authentication = {
isAuth: false,
roles: "Anon"
};
var checkRoles = function (access) {
var result = false;
for (var a in access) {
console.log(access[a]);
for (var b in access[a]) {
if (authentication.roles.indexOf(access[a][b]) >= 0) {
result = true;
break;
}
}
if (result)
break;
}
console.log('result ' + result);
return result;
};
var isUserInInvoiceRole = function () {
return checkRoles([roles.invoice]);
};
var isUserInOrderRole = function () {
return checkRoles([roles.order]);
};
var isUserInCreditNoteRole = function () {
return checkRoles([roles.creditNote]);
};
var isInAdminRole = function () {
return checkRoles([roles.admin]);
};
var isAuthenticated = function () {
return authentication.isAuth;
}
authServiceFactory.isAuthenticated = isAuthenticated;
authServiceFactory.isUserInCreditNoteRole = isUserInCreditNoteRole;
authServiceFactory.isUserInInvoiceRole = isUserInInvoiceRole;
authServiceFactory.isUserInOrderRole = isUserInOrderRole;
authServiceFactory.isInAdminRole = isInAdminRole;
return authServiceFactory;
}]);
I have managed to resolve this myself after understanding how AngularJS watches updates to a controllers' scope.
I simply repopulated the authentication object in the authentication service, after a new refresh token had been retrieved and the nav bar updated instantly.

How to change skin and make it persistant with an angularjs factory?

I want to create a form for the user to pick the skin he wants among a series.
I provide the factory Config to keep track of his choice thru routes.
The factory provides a way to save the config in cookies thru $scope.$watch('config.skin', function(){}) mechanism in order to preserve his choice thru multiple sessions.
The factory is as follows:
app.factory("Config",function($cookies){
console.log("Factory Config…");
return {
config: {
skin: "Gray"
},
save: function(s) {
console.log("Config.save() "+mydump(s,2));
this.config = s;
$cookies.config = JSON.stringify(this.config);
},
load: function() {
if ($cookies.config) {
try {
this.config = JSON.parse($cookies.config);
console.log("App controller: read config from cookies as: ");
for (var i in this.config) {
console.log ("— "+i+" = "+this.config[i]);
}
} catch(e) {
config = null;
}
}
if (!this.config) {
this.config = {"skin": "Gray"};
console.log("App controller: init config from controler ("+this.config+")");
}
return this;
}
};
});
The Config replaces the $scope.config in the controller.
The skin switching is provided thru a ng-class as follows:
<div ng-controller="myCtrl" ng-class="{'skin{{config.skin}}':true}">
<!-- more html -->
</div>
Currently, though my ng-class is updated by the $scope.config.skin as expected, the class itself is not, though not achieving the execpected overall feature.
Any idea?
I've provided a fiddle that demonstrates the issue: http://jsfiddle.net/stephanedeluca/SeUY7/
Interpolation won't work here. Instead, use:
<div ng-controller="myCtrl" ng-class="'skin' + config.skin">
Working fork of your Fiddle

Resources