Google Calendar Api React 'gapi not found' - javascript

I am new to google calendar api and react so I'm sure there is something small I'm missing here. I cannot import the necessary google api libraries to call "gapi." I have try to import them like I would do from local libraries but still get the error "gapi is not defined". I need to use the "gapi" in my component so I don't think I can call and append the script to the body using the componentDidLoad.
// Libraries
import React, {Component} from 'react';
//...import other libraries
//import google libraries in order to use "gapi" and call "checkAuth"
import 'https://ajax.googleapis.com/ajax/libs/angularjs/1.2.32/angular.min.js';
import 'https://apis.google.com/js/client.js?onload=checkAuth';';
var CLIENT_ID = 'MY_CLIENT_ID_IS_HERE';
var SCOPES = ["https://www.googleapis.com/auth/calendar"];
class NewCalendar extends Component {
constructor(props) {
super(props);
this.checkAuth = this.checkAuth.bind(this);
}
checkAuth() {
console.log('checkAuth running...')
gapi.auth.authorize( //ISSUE
^issue with the last line
{
'client_id': CLIENT_ID,
'scope': SCOPES.join(' '),
'immediate': true
}, this.handleAuthResult);
}
...
}
export default NewCalendar;
Does anyone know how to resolve this issue?
Thanks a million.

I struggled with similiar issues. Thats how I solved it. In this case you Need to put the window. scope infront. But hopfeully you found a solution until now ;) Want to share this anyway, maybe it's not the best solution but works for me for the Moment.
componentDidMount() {
this.loadApi();
}
loadApi() {
const script = document.createElement("script");
script.src = "https://apis.google.com/js/api.js";
document.body.appendChild(script);
script.onload = () => {
window.gapi.load('client:auth2', this.checkAuth.bind(this));
}
}
bye

I am pretty new to React and JSX but it seems that you might have ideas to answer your problems here:
GAPI is not defined - ReactJS - Google Sheets
https://github.com/anthonyjgrove/react-google-login/blob/master/src/index.js#L33
It seems that import only works for local files, and that you will need to to async load of the gapi (https://jsx.github.io/doc/importref.html)
Hope that helps

Place your https://apis.google.com/js/api.js inside a script tag inside of your index.html file, below your meta tag. That should be it.
Then in the browser, refresh the page and in your JavaScript console, you should be able to write out gapi and you should be able to see an object like so: {load: f}.
That object would be the Google API that is available on the window scope of your browser.

Related

import third party JS library in open source LWC

After wasting significant amount of time on how to import jQuery,
I got below 2 ways
in HTML with local path or CDN:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
IN JS with local path or CDN:
var script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.4.1.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
But unfortunately both of the above methods won't work in LWC and there is no documentation available on how to do the same.
Below approach works fine in my index.html page to import jQuery in my lwc project.
<script src="./resources/js/jquery-3.5.1.min.js"></script>
I also wasted so many hour on how to import CSS in lwc as there is no documentation available on importing third party CSS also but some how I manged to import css by using below code
constructor() {
super();
const styles = document.createElement('link');
styles.href = './resources/css/bootstrap.css';
styles.rel = 'stylesheet';
this.template.appendChild(styles);
}
So I tried some similar approach to import JS and this doesn't give any errors at the console log but the same doesn't work at all, tried in both constructor and connectedCallback but no luck.
connectedCallback() {
const jq = document.createElement('SCRIPT');
jq.src = './resources/js/jquery-3.5.1.min.js';
jq.type = 'text/javascript';
this.template.appendChild(jq);
}
if anyone has any idea about how to import the JS library in open source LWC then please do let me know, would highly appreciate your help.
First thing that we need to do is to add the JQuery JS file in the
Static Resource. The Static Resource should look something like
below:
JQuery Static Resource
Include JQuery in LWC (Lightning Web Component)
In the JS Controller, we first need to import loadScript() method from
lightning/platformResourceLoader module. We can also include loadStyle
method if we want to include an external CSS file.
import { loadScript, loadStyle } from
'lightning/platformResourceLoader';
Import the Static Resource that we created earlier as well. Check
this implementation to include Static Resource in Lightning Web
Component.
Finally, in the renderedCallback method, call loadScript that we
imported earlier and pass a reference to the current template (this)
and the Static Resource. This method returns the Promise. The then()
function will be called if the Promise is resolved. The catch()
function will be executed if there is an error. We are using
renderedCallback as we want to load the Scripts once the component
is loaded and rendered on UI.
Now, to access the JQuery method in Lightning Web Component, there
is some catch. Ideally, there are multiple ways to call JQuery
methods. The most common one is below:
$(".className").hide();
This will hide the element with class=”className”. But in Lightning
Web Component, we must use it like below:
$(this.template.querySelector('.className')).hide();
That is all. We just need to reference the elements using
queryLocator. Then, we can call the JQuery methods.
import { LightningElement } from 'lwc';
import { loadScript, loadStyle } from
'lightning/platformResourceLoader';
import jQuery from '#salesforce/resourceUrl/JQuery';
lwcJquery.js
import { LightningElement } from 'lwc';
import { loadScript, loadStyle } from
'lightning/platformResourceLoader';
import jQuery from '#salesforce/resourceUrl/JQuery';
export default class LwcJquery extends LightningElement {
renderedCallback(){
loadScript(this, jQuery)
.then(() => {
console.log('JQuery loaded.');
})
.catch(error=>{
console.log('Failed to load the JQuery : ' +error);
});
}
slideIt(event){
$(this.template.querySelector('.panel')).slideToggle("slow");
}
slideRight(event){
$(this.template.querySelector('.innerDiv')).animate({left:
'275px'});
}
}
Here, I have used slideToggle() and animate() JQuery methods to add
some animation.

How to use external JavaScript objects in Vue.js methods

I'm trying to get Stripe working with my Vue.js 2 application. For PCI-DSS reasons, Stripe requires that their Javascript is always loaded from js.stripe.com. I've followed the instructions in:
How to add external JS scripts to VueJS Components
How to include a CDN to VueJS CLI without NPM or Webpack?
but I get a 'Stripe' is not defined error when I try to use the library. These solutions seemed to be aimed at merely getting a <script> tag into the output HTML (e.g. for analytics), not actually consuming the functions and objects in that script.
Here's what my component Javascript looks like:
<script>
export default {
name: "PaymentPage",
mounted() {
let stripeScript = document.createElement('script');
stripeScript.setAttribute('src', 'https://js.stripe.com/v3/');
document.head.appendChild(stripeScript);
let s = Stripe('pk_test_Fooo');
console.log(s);
}
}
</script>
I also tried adding the script tag to my public/index.html file instead, but I get the same outcome. This would probably be my preferred route, since Stripe encourages developers to import their script on all pages on the site.
<!DOCTYPE html>
<html lang="en">
<head>
// ...
<script src="https://js.stripe.com/v3/"></script>
</head>
How can I pull a script from an external CDN and use it within my component's Javascript?
I'm aware of some libraries to integrate Vue.js with Stripe (e.g. matfish2/vue-stripe and jofftiquez/vue-stripe-checkout), but the former doesn't import properly for me (I'm hitting issue #24) and the latter is built against the older Stripe API and the new version is still in beta.
You aren't giving the script time to load before checking if Stripe is there. What you need is something like this:
<script>
export default {
name: "PaymentPage",
mounted() {
let stripeScript = document.createElement('script');
stripeScript.setAttribute('src', 'https://js.stripe.com/v3/');
stripeScript.onload = () => {
let s = Stripe('pk_test_Fooo');
console.log(s);
};
document.head.appendChild(stripeScript);
}
}
</script>
Thanks to yuriy636's comment, I realised that errors were only from the linter, which presumably can't statically figure out what I'm up to.
I opted to put the script into index.html, then ensured I squashed linter errors with:
// eslint-disable-next-line no-undef
let s = Stripe('pk_test_Fooo');
In my case, I still had errors calling functions of the specific script. So it was required to specify the ¨window¨ scope. Also, if you need to access any Vue element inside the ¨onload¨function, you need a new variable for the ¨this¨ instance.
<script>
export default {
name: "PaymentPage",
mounted() {
let stripeScript = document.createElement('script');
// new variable for Vue elements.
let self = this;
stripeScript.onload = () => {
// call a script function using 'window' scope.
window.Stripe('pk_test_Fooo');
// call other Vue elements
self.otherVueMethod();
};
stripeScript.setAttribute('src', 'https://js.stripe.com/v3/');
document.head.appendChild(stripeScript);
}
}
I worked with this on Vue 2.6.
Just install the npm package npm install #stripe/stripe-js and use it like a regular import
import { loadStripe } from "#stripe/stripe-js";
export default {
async mounted() {
// init stripe
const stripe = await loadStripe('your_stripe_key_here');
this.stripe = stripe; // store the stripe instance
// access the stripe instance in your methods or where you want to use them
},
}
It's working as of 6th Jan 2022.

How to use an external non vue script in vue

I try to use an external script (https://libs.crefopay.de/3.0/secure-fields.js) which is not vue based
I added the script via -tags into index.html
But when I try to intsanciate an object, like in the excample of the script publisher.
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
Vue says "'SecureFieldsClient' is not defined"
If I use this.
let secureFieldsClientInstance =
new this.SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
secureFieldsClientInstance.registerPayment()
Vue says: Error in v-on handler: "TypeError: this.SecureFieldsClient is not a constructor"
My Code:
methods: {
startPayment () {
this.state = null
if (!this.selected) {
this.state = false
this.msg = 'Bitte Zahlungsweise auswählen.'
} else {
localStorage.payment = this.selected
let configuration = {
url: 'https://sandbox.crefopay.de/secureFields/',
placeholders: {
}
}
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
secureFieldsClientInstance.registerPayment()
// this.$router.replace({ name: 'payment' })
}
}
}
Where is my mistake?
EDIT:
Updated the hole question
Here is a minimal Vue app for the context your provided, which works:
https://codepen.io/krukid/pen/voxqPj
Without additional details it's hard to say what your specific problem is, but most probably the library gets loaded after your method executes, so window.SecureFieldsClient is expectedly not yet defined. Or, there is some runtime error that crashes your script and prevents your method from executing. There could be some other more exotic issues, but lacking a broader context I can only speculate.
To ensure your library loads before running any code from it, you should attach an onload listener to your external script:
mounted () {
let crefPayApi = document.createElement('script')
crefPayApi.onload = () => this.startPayment()
crefPayApi.setAttribute('src', 'https://libs.crefopay.de/3.0/secure-fields.js')
document.head.appendChild(crefPayApi)
},
I found the solution.
the import was never the problem.
I had just to ignore VUEs/eslints complaining about the missing "this" via // eslint-disable-next-line and it works.
So external fuctions/opbjects should be called without "this" it seems.
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
You could download the script and then use the import directive to load the script via webpack. You probably have something like import Vue from 'vue'; in your project. This just imports vue from your node modules.
It's the exact same thing for other external scripts, just use a relative path. When using Vue-CLI, you can do import i18n from './i18n';, where the src folder would contain a i18n.js
If you really want to use a CDN, you can add it like you normally would and then add it to the externals: https://webpack.js.org/configuration/externals/#externals to make it accessible from within webpack

How do you import a javascript package from a cdn/script tag in React?

I'd like to import this javascript package in React
<script src="https://cdn.dwolla.com/1/dwolla.js"></script>
However, there is no NPM package, so I can't import it as such:
import dwolla from 'dwolla'
or
import dwolla from 'https://cdn.dwolla.com/1/dwolla.js'
so whenver I try
dwolla.configure(...)
I get an error saying that dwolla is undefined. How do I solve this?
Thanks
Go to the index.html file and import the script
<script src="https://cdn.dwolla.com/1/dwolla.js"></script>
Then, in the file where dwolla is being imported, set it to a variable
const dwolla = window.dwolla;
This question is getting older, but I found a nice way to approach this using the react-helmet library which I feel is more idiomatic to the way React works. I used it today to solve a problem similar to your Dwolla question:
import React from "react";
import Helmet from "react-helmet";
export class ExampleComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
myExternalLib: null
};
this.handleScriptInject = this.handleScriptInject.bind(this);
}
handleScriptInject({ scriptTags }) {
if (scriptTags) {
const scriptTag = scriptTags[0];
scriptTag.onload = () => {
// I don't really like referencing window.
console.log(`myExternalLib loaded!`, window.myExternalLib);
this.setState({
myExternalLib: window.myExternalLib
});
};
}
}
render() {
return (<div>
{/* Load the myExternalLib.js library. */}
<Helmet
script={[{ src: "https://someexternaldomain.com/myExternalLib.js" }]}
// Helmet doesn't support `onload` in script objects so we have to hack in our own
onChangeClientState={(newState, addedTags) => this.handleScriptInject(addedTags)}
/>
<div>
{this.state.myExternalLib !== null
? "We can display any UI/whatever depending on myExternalLib without worrying about null references and race conditions."
: "myExternalLib is loading..."}
</div>
</div>);
}
}
The use of this.state means that React will automatically be watching the value of myExternalLib and update the DOM appropriately.
Credit: https://github.com/nfl/react-helmet/issues/146#issuecomment-271552211
for typescript developers
const newWindowObject = window as any; // cast it with any type
let pushNotification = newWindowObject.OneSignal; // now OneSignal object will be accessible in typescript without error
You can't require or import modules from a URL.
ES6: import module from URL
What you can do is make an HTTP request to get the script content & execute it, as in the answer for how to require from URL in Node.js
But this would be a bad solution since your code compilation would depend on an external HTTP call.
A good solution would be to download the file into your codebase and import it from there.
You could commit the file to git if the file doesn't change much & are allowed to do it. Otherwise, a build step could download the file.
var _loaded = {};
function addScript(url) {
if (!loaded[url]) {
var s = document.createElement('script');
s.src = url;
document.head.appendChild(s);
_loaded[url] = true;
}
}
how to load javascript file from cdn server in a component
Add the script tag in your index.html and if you are using Webpack, you can use this webpack plugin https://webpack.js.org/plugins/provide-plugin/

How can I make add firepad to my reactjs project?

So I've been learning react, and wanted to make a basic firepad instance. My current setup is having one container div in my index.html, and having all of my react components rendering through that div. My current attempts and the code I'm showing with this have been in an environment with gulp and browserify, but I'm also playing around with ES6 and webpack. So I'm pretty flexible about getting this working as I learn. Here's the code:
"use strict"
var React = require('react')
, Firebase = require('firebase')
, fbRoot = 'myURL'
, CodeMirror = require('codemirror')
, Firepad = require('firepad')
, firepadRef = new Firebase(fbRoot + 'session/')
, myCodeMirror = CodeMirror(document.getElementById('firepad'), {lineWrapping: true})
, myFirePad = Firepad.fromCodeMirror(firepadRef, myCodeMirror, { richTextShortcuts: true, richTextToolbar: true, defaultText: 'Hello, World!'});
var WritePage = React.createClass({
render: function(){
return (
<div>
<div id="firepad"></div>
</div>
);
}
});
module.exports = WritePage;
The first error I was getting was that it couldn't find the codemirror.js file. Although CodeMirror was being correctly defined in Chrome's dev tools, I moved that from requiring the npm package to just linking the 2 needed codemirror files to my html. It then gave me an error about not being able to take .replaceChild of undefined. I then tried moving all of the dependency files over to my index.html, but still had the same .replaceChild error. Anyone have any experience with react and firepad? I read in the reactfire docs that it's one way binding from firebase to my site, which for my case making a read-only firepad would be fine. Like I said, I'm flexible all of this stuff is new to me.
From the link that Michael provided.
The problem is that you are trying to reference a DOM element before React has rendered your component.
, myCodeMirror = CodeMirror(document.getElementById('firepad'),{lineWrapping: true})
, myFirePad = Firepad.fromCodeMirror(firepadRef, myCodeMirror, {richTextShortcuts: true, richTextToolbar: true, defaultText: 'Hello, World!'});
By moving this code into componentDidMount(), it runs after the CodeMirror DOM element has been constructed and you'll be able to reference the DOM node. You will also probably find it easier to use the React ref attribute instead of document.getElementById().
Use these npm packages - brace, react-ace, firebase, firepad.
Since firepad needs aceto be present globally, assign brace to global var
like(not the best way, but works) before importing firepad
import firebase from 'firebase/app';
import 'firebase/database';
import brace from 'brace';
global.ace = brace;
global.ace.require = global.ace.acequire;
import Firepad from 'firepad';
Use ref to get instance of ReactAce and initialize it in componentDidMount using:
new Firepad.fromACE(this.firepadRef, this.aceInstance.editor, options);
Similarly for CodeMirror editor.
Hoping, this would be of some help.

Categories

Resources