How bind angular component function to google signin button - javascript

I'm new to angular so please be kind. I have been struggling to figure out how to connect the google signin callback button to my angular component. I'm trying to receive the OAuth token on the client-side in order to send to my back-end but I am unable to get a hold of the response inside my angular component. The obstacle I'm encountering is the inability to have the google button call my angular component function.
Based on the latest google signin api in order to add a google OAuth button via html you need to do the following. I attempted to do this via their javascript library but wasn't successful.
<html>
<body>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
function handleCredentialResponse(e) {
//e.credential contains the JWT token
}
</script>
<div id="g_id_onload"
data-client_id="YOUR_CLIENT_ID"
data-callback="handleCredentialResponse">
</div>
<div class="g_id_signin" data-type="standard"></div>
</body>
</html>
I wanted to encapsulate this into a component and get that function called in my component.ts file. So I did the following with onGoogleSignin being a component function.
<script src="https://accounts.google.com/gsi/client"></script>
<div id="g_id_onload"
[attr.data-client_id]="google_login_id"
[attr.data-callback]="onGoogleSignIn">
</div>
<div class="g_id_signin"
[attr.data-text]="buttonTxt"
[attr.data-theme]="theme"
></div>
The project compiles and runs but when I run it I get the following issue in the console
[GSI_LOGGER]: The value of 'callback' is not a function. Configuration ignored.
The properties bind no problem but it's the function that doesn't work. So the only hack I have come up with is to put the following in the index.html file
<script>
function onGoogleSignIn(e) {
console.log(e);
window.authRef.zone.run(() => { window.authRef.googleSigninFunction(e); });
}
</script>
Modifying the component.html to not bind to the component function like below:
<div id="g_id_onload"
[attr.data-client_id]="google_login_id"
data-callback="onGoogleSignIn">
</div>
And then put the following into the constructor of my component:
constructor(
private ngZone: NgZone) {
window['authRef'] = { component: this, zone: this.ngZone,
googleSigninFunction: (e:any) => this.onGoogleSignin(e), };
}
All of this works but it requires to have a dependency on my component to be outside of my component which is not good practice. I know this is simply because I lack some basic understanding of angular.
Any help would be greatly appreciated
UPDATE:
I did add code on OnInit to inject the code into the DOM programmatically so that it will exist when google needs to bind to it. This allows me to not have to manually add the code into index.html but I'm sure there is a more elegant way to do this.

Related

Cannot call a server-side function located inside a library from client-side code

I tried the simplest way of calling Google Apps Script server-side function from my html using the sample code given here https://developers.google.com/apps-script/guides/html/reference/run. It works like a charm.
However, when I try to do the same thing in my actual project which has all the server code in a library, it doesn't work. I keep getting the error
"Uncaught TypeError: google.script.run.doSomething is not a function"
Here is a sample project that I created to recreate the issue
The Gdoc
Here look for "Test Menu" and click on "open sidebar" to invoke the functionality. Access the bound script to see the code and the usage of Library.
Library code
Any help with this would be much appreciated.
Example:
html:
<script>
function doSomething() {
google.script.run
.withSuccessHandler(function(msg){
window.alert(msg);//Thank's I got it.
})
.doSomething();
}
</script>
<body>
<input type="button" value="Do Something" onClick="doSomething();" />
</body>
gs:
function doSomething() {
return 'Thanks I got it';
}
You are trying to call DocumentApp.getUi() from the library.
As you can see here
A script can only interact with the UI for the current instance of an
open document, and only if the script is bound to the document.
Your library is not bound to your document. This is why your code cannot work.
You can only move those parts of your code into a library that do no use getUi() or any Not-shared resources (e.g. triggers). The documentation specifies which resources are shared and which ones are not.

TYPO3 Frontent: Form Action results Page not found

I'm working on TYPO3 migration from 6.2.31 to 8.7.19.
In my templates I'm using a navigationbar which should filter a list of videos based on categories. The navigationbar is a formular:
<f:if condition="{loggedIn}">
<f:then>
<form name="audit_vw_filter" method="post" id="audit_vw_filterForm"
action="?tx_vidverwaltung_vidverwaltungfrontend[action]=listSelectedMember&tx_vidverwaltung_vidverwaltungfrontend[controller]=FrontendVideo">
</f:then>
<f:else>
<form name="audit_vw_filter" method="post" id="audit_vw_filterForm"
action="?tx_vidverwaltung_vidverwaltungfrontend[action]=listSelectedPublic&tx_vidverwaltung_vidverwaltungfrontend[controller]=FrontendVideo">
</f:else>
</f:if>
...
<f:for each="{categories}" as="category" iteration="i">
<div>
//list the category
<span id="fontRed{category.uid}" class="vw_navigationbarFilter filterLinkCategory" onclick="setActualCategory('{category.name}','{category.uid}')">{category.name}</span>
</div>
...
</f:for>
</f:form>
In JavaScript I declared every category as a submit when click on it.
...
$("#vw_filterForm").submit();
So now the action from my form should be executed and call my 'FrontendVideo' Controller which should give me a feedback in form of a debug.
public function listSelectedMemberAction () {
DebuggerUtility::var_dump("Hello World");
...
}
It seems like the function of the Controller isn't reached.
Instead there is a friendly "Page not found" :/
As Expected the URL is:
http://example.de/.../.../?tx_vidverwaltung_vidverwaltungfrontend[action]=listSelectedMember&tx_vidverwaltung_vidverwaltungfrontend[controller]=FrontendVideo
On the old version 6.2.31 it worked fine. So maybe there is a change of how I call a Controller function or maybe a problem with realurl etc....
Thanks in advance!
I found the problem:
In the older TYPO3 versions TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError'] was set to true by default, so if the cHash is empty the error message is outputed.
So I tend to revert the pageNotFoundOnCHashError to "false" as default value.
to do this go into your
Install Tool > All configuration > Frontend
and change pageNotFoundOnCHashError to false
[FE][pageNotFoundOnCHashError] = false

Adding email/password firebase login in Polymer Starter Kit app

I've been trying to add simple email / password signup/login for Firebase to the Polymer Starter Kit app. It comes stock with a Google auth sign in via a single button but there doesn't seem to be any instructions on how to set-up email/password register/login instead.
Here is the specific part of the code from the project's todo-auth.html file I've been struggling with:
<firebase-auth id="authenticate"
user="{{user}}"
location="{{location}}"
ref="{{refauth}}"
provider="">
</firebase-auth>
<paper-dialog modal
opened="[[!user]]"
entry-animation="scale-up-animation"
exit-animation="fade-out-animation">
<h2>Please sign in</h2>
<div>
<!-- Inputs I added to accept user credentials -->
<paper-input id="loginEmailInput"
no-label-float
label="Email"
on-keydown="">
</paper-input>
<paper-input id="loginPasswordInput"
no-label-float
label="Password"
on-keydown="">
</paper-input>
<paper-button on-tap="logIn">Login</paper-button>
<!-- Original Google sign-in code -->
<!-- <div class="google-sign-in"
tabindex="0"
on-tap="signIn">
<span class="google-sign-in-icon"></span>
<span class="google-sign-in-label">Google</span>
</div> -->
</div>
</paper-dialog>
I removed google from the provider property of the <firebase-auth> element and added a couple of input fields but don't really know where to go from there.
Here is the Polymer script part of todo-auth.html
<script>
Polymer({
is: 'todo-auth',
properties: {
user: {
notify: true
}
},
logIn: function() {
this.$.authenticate.login();
},
signOut: function() {
this.$.authenticate.logout();
this.user = null;
}
});
</script>
I've tried to find examples or guide tutorials on how to implement this but everything I've found has used the google based auth as login. Likewise, all other questions I've found here on SO have focused on google login.
I'd be grateful for any directions or pointers or tutorials on how to set it up. Thanks all in advance!
UPDATE
I managed to implement a new page with a form using the demo from the Google Web Components github repo.
I have a my-firebase.html file that imports everything I can think of to make it work. Imports look like this:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/polymerfire/firebase-auth.html">
<link rel="import" href="../../bower_components/polymerfire/firebase-app.html">
<link rel="import" href="../../bower_components/polymerfire/polymerfire.html">
I have also added the following for firebase-app and firebase-auth:
<firebase-app auth-domain="my-polymer-app.firebaseapp.com"
database-url="https://my-polymer-app.firebaseio.com/"
api-key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
</firebase-app>
<firebase-auth id="firebaseLogin" user="{{user}}" status-known="{{statusKnown}}" location="my-polymer-app.firebaseapp.com" provider="{{provider}}" on-error="errorHandler" on-user-created="userSuccessHandler" on-password-changed="us erSuccessHandler" on-password-reset="userSuccessHandler" on-user-removed="userSuccessHandler"></firebase-auth>
I am now getting the following error when I try to login(I have already set up a user in my Firebase App to test):
my-firebase.html:122 Uncaught TypeError: this.$.firebaseLogin.login is not a function
Which refers to this part of the code take from the Google Web Components repo.
login: function() {
var params;
try {
params = JSON.parse(this.params);
} catch (e) {
params = null;
}
if (this.provider == 'password') {
params = params || {};
params.email = this.email;
params.password = this.password;
}
this.$.firebaseLogin.login(params);
}
There are also red boxes around every instance of firebaseLogin on the page. No other errors are showing up so not sure what this means exactly. Again, I'd be grateful if anyone could point out what I'm missing here.
Use signInWithEmailAndPassword function instead of login function,
this.$.firebaseLogin.signInWithEmailAndPassword(username, password);

Inform AngularJS about file upload with Django

For my webpage I use Django 1.9 for the server-side and AngularJs for some client-side tasks (validation etc).
Also for the CSS I use Bootstrap (and the Angular-Ui).
Now I created the forms I need in Django which inserts them on the actual page. Amongst others, I have an input field of type file which lets the user upload a file.
When the user has chosen a file, I would like to do some checks in AngularJs. The problem is: I have no clue how I can get some kind of callback from Django to know that the upload-file window was closed.
My current solution involves a plain javascript function which is bound to the upload field and calls an AngularJs function, but this does not work properly.
So in my forms.py it looks like that:
class UploadForm(forms.Form):
fa_file = forms.FileField(label='Select a Fasta file',
widget=forms.TextInput(attrs={'type': 'file'})
The part of the html page where this field is inserted looks like that:
<div class="panel-body">
<input type="text" id="uploadFile" placeholder="Choose File" disabled="disabled"/>
<div class="file-upload btn btn-sm btn-primary">
<span>Upload</span>
{{ form.fa_file }}
</div>
</div>
The javascript function which is bound to the file-upload field is:
<script>
document.getElementById("id_fa_file").onchange = function () {
document.getElementById("uploadFile").value = this.value;
angular.element(this).scope().changeFaFileValue(this.value);
};
</script>
This on change method is executed whenever the user finishes choosing a file. Essentially this is the behavior I want to achieve and the AngularJS function of my controller 'changeFaFileValue' is executed as well.
But it seems that the execution happens in its own scope. I can tell because I have a watcher in my AngularJS controller for a variable which is changed in 'changeFaFileValue' and this watcher is not triggered when the function is called via this plain Javascript on change function.
But if I call the 'changeFaFileValue' from somewhere in my controller, the watcher executes as expected.
The methods in the controller look like this:
$scope.$watch('allow_submit', function(){
console.log("IT WORKED.");
});
$scope.changeFaFileValue = function(newPath){
$scope.fa_file_js = newPath;
$scope.allow_submit = !$scope.allow_submit;
}
I think I am missing something important here.
Can you please tell me what would be the correct way to achieve the desired behavior? Is my approach correct at all?

Integration of braintree causing issues

I'm working on Braintree for the first time and getting issues in very first step. I'm not able to access dropin functionality and other..
I need help to sort it out.
I followed steps given here : https://developers.braintreepayments.com/javascript+php/start/overview
First step is Javascript Client! - I followed as mentioned, added script
<script src="https://js.braintreegateway.com/v2/braintree.js"></script>
Then added HTML part
<form id="checkout" method="post" action="/checkout">
<div id="dropin"></div>
<input type="submit" value="Pay $10">
</form>
And at last I've added below script in script tag.
braintree.setup("CLIENT_TOKEN_KEY", 'dropin', {
container: 'checkout'
})
I have checked with Client Token Key obtained from our server.
for next step, I added configurations as mentioned
Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('use_your_merchant_id'); //updated with our merchant id
Braintree_Configuration::publicKey('use_your_public_key'); // updated with our public key
Braintree_Configuration::privateKey('use_your_private_key'); //updated with our private key
then added
$clientToken = Braintree_ClientToken::generate(array(
"customerId" => $aCustomerId
));
Now, Issues I'm getting -
When I updated $aCustomerId with our customer id, I got a Fatal Error of "customer_id" field undefined in Braintree_ClientToken. So removed array("customer"=>$aCustomerId) and got the client token..
That client token is used in brantree.setup('TOKEN_KEY','dropin',{container:'checkout'}) and got
Error: Unable to find valid container. -braintree.js(line 18)
I also mentioned once var braintree = Braintree.create("CLIENT_TOKEN_KEY"); above brantree.setup('TOKEN_KEY','dropin',{container:'checkout'}) at that time I've got TypeError: braintree.setup is not a function
I'm trying to sort it out this from last two days, but still I didn't get dropin screen as showed in demo.
Hope for good help..
Place all the scripts after the html / footer section, this will work:
<?php
require_once 'braintree-php-2.30.0/lib/Braintree.php';
Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('-----------');
Braintree_Configuration::publicKey('-----------');
Braintree_Configuration::privateKey('-----------');
if(isset($_POST['submit'])){
/* process transaction */
$result = Braintree_Transaction::sale(array(
'amount' => '234.00',
'creditCard' => array(
'number' => '30569309025904',
'expirationDate' => '05/14'
)
));
if ($result->success) {
print_r("success!: " . $result->transaction->id);
} else if ($result->transaction) {
print_r("Error processing transaction:");
print_r("\n code: " . $result->transaction->processorResponseCode);
print_r("\n text: " . $result->transaction->processorResponseText);
} else {
print_r("Validation errors: \n");
print_r($result->errors->deepAll());
}
}
$clientToken = Braintree_ClientToken::generate();
?>
<html>
<head>
</head>
<body>
<div id="checkout" method="post" action="/checkout">
<div id="dropin"></div>
<input data-braintree-name="number" value="4111111111111111">
<input data-braintree-name="expiration_date" value="10/20">
<input type="submit" id="submit" value="Pay">
<div id="paypal-button"></div>
</div>
<!-- Scripts -->
<script src="https://code.jquery.com/jquery-2.1.1.js"></script>
<script src="https://js.braintreegateway.com/v2/braintree.js"></script>
<script>
braintree.setup("<?php print $clientToken; ?>", "dropin", { container:
jQuery("#dropin") , form: jQuery("#checkout") ,
paymentMethodNonceReceived: function (event, nonce) {
// do something
}
});
</script>
</body>
</html>
I had this problem and solved it by putting the javascript at the end of the page. The alternative would be to enclose it in a document ready test.
The problem occurs because the braintree code tries to find the container as soon as the script is loaded. But if your code is in the head of the document, the container won't have been loaded, so it won't find the container and you'll get an error.
The comment about base64_encoding is incorrect. It works perfectly if the code is triggered after the container has been loaded without mucking around re-encoding an already encoded string.
I work at Braintree. Feel free to reach out to our support team if you have more questions.
The first error you were seeing, Unable to find valid container., will be thrown if the JavaScript cannot find the container you provided. The accepted values for a container are an ID string, DOM node, or jQuery object. Your example code should work, but if it doesn't you could try to pass in a different format, {container: $('#dropin')} for example.
Once you're sure you are passing in the correct container, I'd also recommend making sure you're interpolating in your client token correctly. If you view source on your page, your client token should be a base64 encoded string.
You want to make sure your <script src="https://js.braintreegateway.com/js/braintree-2.32.1.min.js"></script> is as close to the bottom of the page as possible. Right above your tag, if possible. This gives your browser time to load the DOM and then load the Braintree SDK.
Next you want to specify the "container" by passing in the container property to the setup() method. Something like this:
let checkout;
braintree.setup('CLIENT_TOKEN_KEY', 'dropin', {
container: document.getElementById('dropin'), // <- This line here.
onReady: function (integration) {
checkout = integration;
console.log(checkout)
}
});

Categories

Resources