Кнопка Google Signin в AngularJS иногда не отображается
Я пошел по этой ссылке https://developers.google.com/identity/sign-in/web/sign-in чтобы получить Google Signin на веб-сайте Angular.
Я видел какое-то странное поведение. Кнопка signin иногда появляется, но не всегда. Когда я обновляю страницу, обновляется только 1 из 5, появляется кнопка.
Я пробовал в Chrome и Safari, и оба имеют одинаковое поведение.
Код:
Индекс.html
<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-client_id" content="my_client_id">
Вход.html
<div class="g-signin2" data-onsuccess="onSignIn"></div>
Вход.js
angular.module('app').controller('LoginCtrl', function($scope) {
window.onSignIn = function(googleUser) {
// Get some info
}
});
2 ответа:
Я предполагаю, что платформа.сценарий js ожидает события DOM-ready, а затем ищет ваш div с помощью класса"g-signin2". Хотя в Angularjs все работает немного по-другому. Причина, по которой это иногда работает, заключается в том, что иногда ваш div был отрисован Angular, а иногда не был отрисован до события DOM-ready. Существуетдокументация о том, как получить тот же результат с помощью собственного javascript. Я привел пример, который следует за вашим маршрутизирующий.
<!doctype html> <html lang="en" ng-app="app"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div ng-view></div> <script src="https://apis.google.com/js/platform.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script> <script src="https://code.angularjs.org/1.4.6/angular-route.min.js"></script> <script> angular.module('app',['ngRoute']) .config(['$routeProvider',function($routeProvider){ $routeProvider .when('/log-in', { template: '<button ng-click="logInCtrl.onLogInButtonClick()">Log In</button>', controller: 'LogInController', controllerAs: 'logInCtrl' }).otherwise({ redirectTo:'/log-in' }); }]) .controller('LogInController',function(){ var self = this; //to be able to reference to it in a callback, you could use $scope instead gapi.load('auth2', function() {//load in the auth2 api's, without it gapi.auth2 will be undefined gapi.auth2.init( { client_id: 'CLIENT_ID.apps.googleusercontent.com' } ); var GoogleAuth = gapi.auth2.getAuthInstance();//get's a GoogleAuth instance with your client-id, needs to be called after gapi.auth2.init self.onLogInButtonClick=function(){//add a function to the controller so ng-click can bind to it GoogleAuth.signIn().then(function(response){//request to sign in console.log(response); }); }; }); }); </script> </body> </html>
Или как директива:
После написания предыдущих примеров я нашел лучший и более простой способ его реализации. С помощью этого кода вы наследуете ту же кнопку, что и обычно.<!doctype html> <html lang="en" ng-app="app" ng-controller="MainController"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <google-sign-in-button on-sign-in="onSignIn(response)" g-client-id="CLIENTID.apps.googleusercontent.com"></google-sign-in-button> <script src="https://apis.google.com/js/platform.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script> <script> angular.module('app',[]) .controller('MainController',['$scope', function ($scope) { $scope.onSignIn=function(response){ console.log(response); } }]) .directive('googleSignInButton',function(){ return { scope:{ gClientId:'@', callback: '&onSignIn' }, template: '<button ng-click="onSignInButtonClick()">Sign in</button>', controller: ['$scope','$attrs',function($scope, $attrs){ gapi.load('auth2', function() {//load in the auth2 api's, without it gapi.auth2 will be undefined gapi.auth2.init( { client_id: $attrs.gClientId } ); var GoogleAuth = gapi.auth2.getAuthInstance();//get's a GoogleAuth instance with your client-id, needs to be called after gapi.auth2.init $scope.onSignInButtonClick=function(){//add a function to the controller so ng-click can bind to it GoogleAuth.signIn().then(function(response){//request to sign in $scope.callback({response:response}); }); }; }); }] }; }); </script> </body> </html>
<!doctype html> <html lang="en" ng-app="app" ng-controller="MainController"> <head> <meta charset="UTF-8"> <title>Document</title> <meta name="google-signin-client_id" content="CLIENTID.apps.googleusercontent.com"> </head> <body> <google-sign-in-button button-id="uniqueid" options="options"></google-sign-in-button> <script src="https://apis.google.com/js/platform.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script> <script> angular.module('app', []) .controller('MainController', ['$scope', function($scope) { //for more options visit https://developers.google.com/identity/sign-in/web/reference#gapisignin2renderwzxhzdk114idwzxhzdk115_wzxhzdk116optionswzxhzdk117 $scope.options = { 'onsuccess': function(response) { console.log(response); } } } ]) .directive('googleSignInButton', function() { return { scope: { buttonId: '@', options: '&' }, template: '<div></div>', link: function(scope, element, attrs) { var div = element.find('div')[0]; div.id = attrs.buttonId; gapi.signin2.render(div.id, scope.options()); //render a google button, first argument is an id, second options } }; }); </script> </body> </html>
Я нашел другой способ решить проблему немного проще.
Объяснение от @sniel идеально, но я дам вам знать более простое решение.
Вы можете использовать приведенный ниже пример кода очень симиралиры с использованием $watch https://developers.google.com/identity/sign-in/web/build-button
<!-- html part --> <div id="signInButton"></div> //gapi is Asynchronously loaded so you need to watch $scope.$watch('gapi', function(newValue,oldVale){ if(newValue !== oldVale){ if(gapi){ gapi.signin2.render('signInButton', { 'onsuccess': $scope.onSuccess, 'onfailure': $scope.onFailure, 'scope':'https://www.googleapis.com/auth/plus.login' } ); } } });