Laravel / Livewire does not work in laravel mix complied app.js - javascript

I use Laravel with Livewire. I wanted to react to an event in js. Once its emitted, an js alert should appear.
The problem seems to be in app.js were I have my js function. I receive an error, Livewire is not available. I use Laravel Mix to compile it, and it compiles all fine.
Error: Uncaught TypeError: Livewire.on is not a function
app.js:
import Livewire from '../../vendor/livewire/livewire/dist/livewire';
Livewire.on('testEvent', function () {
alert("test");
});
It looks like an import problem. I've removed the package and tried it again and I also thought its a timing problem, so I executed on document load but still the same problem.
I've then decided to push it directly to the stack through a components blade file, and here it works all fine.
#push('scripts')
<script>
Livewire.on('testEvent', function () {
alert("test");
});
</script>
#endpush
Pushing it to the stack should not be required as I've seen other code snippets without it and the error seems to be a simple import problem?

Use the browser Inspector and look if #livewireStyles and #livewireScripts are loaded in page. Be sure that Livewire already is installed

Please note that there are some js codes which #livewireScripts puts after the actual livewire.js file. so ...
make sure loading Livewire inside global window object for later accesses.
window.Livewire = require("../../public/vendor/livewire/livewire.js");`
create a new file called livewire.js with these lines
if (window.livewire) {
console.warn(
"Livewire: It looks like Livewire's #livewireScripts JavaScript assets have already been loaded. Make sure you aren't loading them twice."
);
}
window.livewire = new window.Livewire();
window.livewire.devTools(true);
window.Livewire = window.livewire;
window.livewire_app_url = "";
window.livewire_token = "ZgcGN7YWdBf2wfwJQoDJ3pUHfwhBmAAlSoeBpQXD";
/* Make sure Livewire loads first. */
if (window.Alpine) {
/* Defer showing the warning so it doesn't get buried under downstream errors. */
document.addEventListener("DOMContentLoaded", function () {
setTimeout(function () {
console.warn(
"Livewire: It looks like AlpineJS has already been loaded. Make sure Livewire's scripts are loaded before Alpine.\\n\\n Reference docs for more info: http://laravel-livewire.com/docs/alpine-js"
);
});
});
}
/* Make Alpine wait until Livewire is finished rendering to do its thing. */
window.deferLoadingAlpine = function (callback) {
window.addEventListener("livewire:load", function () {
callback();
});
};
let started = false;
window.addEventListener("alpine:initializing", function () {
if (!started) {
window.livewire.start();
started = true;
}
});
document.addEventListener("DOMContentLoaded", function () {
if (!started) {
window.livewire.start();
started = true;
}
});
Make sure you are using the latest version of livewire and use your own updated version of #livewireScripts js codes which automatically gets appended after the actual livewire.js script tag.

Related

"Cannot read property ClassList of Undefined" error after moving Javascript into modules

I'm very new to JS and am running into an issue while trying to separate some JS into modules. I'm thinking that this is a simple fix, but I'm hoping someone here can help steer me in the right direction. My code works fine if I just put it all into one JS file and link it directly with index.html via a tag, so something is breaking specifically from the move over to a module.
Within my HTML, I have several elements that will change visibility depending on the buttons a user clicks while on the site. The JS as it was written in the original script file worked fine before I attempt to place it in a module:
showHideSections = (section) => {
if (section.classList.contains("hidden")){
section.classList.remove("remove-tab");
section.classList.remove("slideout");
... };
So, I added export const to the start of the code to export it to a main.js file:
export const showHideSections = (section) => { ...
And then imported it to main.js:
import { ..., showHideSections, ... } from "./modules/script.js"
window.addEventListener("DOMContentLoaded", () => {
...
showHideSections();
... });
And now I'm ending up with Uncaught TypeError: cannot read property "ClassList" of undefined.
I'm guessing this has to do with the order in which the code is running now that the JS has moved into a module, but after a few attempts with directing the code to execute differently, I'm feeling stuck. I've tried adjusting the addEventListener on main.js to execute on "load" vs on DOM Content loading. I have also tried creating an object for the element within the script.js file as a workaround, but no dice there, either.
Any thoughts?
Well, it seems you are not passing the section argument in the method call:
import { ..., showHideSections, ... } from "./modules/script.js"
window.addEventListener("DOMContentLoaded", () => {
const section = document.querySelector("#someSelectorHere");
showHideSections(section);
});

How do I overcome a "function is not defined" error when loading an external .js file?

I'd like to create a JS plugin (with ES6) so that it can be called from an HTML file, like this:
<div id="emails-box"></div>
<script src="emails-box.js"></script>
<script>
const container = document.querySelector('#emails-box')
EmailsBox({container, ...options})
//some code
</script>
and it can be used independently.
What the EmailsBox will do is to take the container and add a children div with a box to store a bunch of emails.
I've tried to do this for 2-3 days, but everytime I try to load the .js file, I get a:
EmailsBox is not defined
I'm getting desperate. Could you someone give me some light? Thanks!
EDIT: In my emails-box.js file, I could have something like this:
var EmailsBox = function(obj){
console.log("EmailsBox called")
// some code
return true;
}
Worked fine for me. Make sure that emails-box.js is in the same folder as index.html and the name matches the one you're linking to. working setup
Most likely the file path of your .js file is referenced wrong. So first make sure that you referenced file right. If it is, then try to define function like don't assign it to variable, it might not be defined on load page.
function EmailsBox(obj){
// some code
}
And if you really need it assigned to variable try using ready function.
var EmailsBox = function(obj){
console.log("EmailsBox called")
// some code
return true;
}
<script>
(function() {
EmailsBox({container, ...options})
})();
</script>
When calling the function, make sure options variable is defined.
So that instead of calling:
EmailsBox({container, ...options});//when options is not defined,
define options first and then call the EmailsBox function like so:
var options = 'hello'; //for example
EmailsBox({container, ...options});
If your emails-box.js file is properly referenced, it should work just fine.
There is a good chance that the problem with your source but if its because its not loading which would be weird then try using js to load the script if this doesn't work its wrong for sure and you should check it is right
var source = 'source here to script file';
var script = document.createElement('script');
script.onload = function () {
//what you want to do with this script
};
script.src = source();
document.head.appendChild(script);

How to add script to React component and use as constructor function

I'm trying to load external javascript (https://github.com/spite/ccapture.js) to my React.js component.
Currently the code looks like this:
let aScript = document.createElement('script');
aScript.type = 'text/javascript';
aScript.src = "CCapture.min.js";
document.head.appendChild(aScript);
This code correctly appends script to the page (checked the HTML).
But now I'm wondering how can I use the contents of the script in a constructor function. Specifically, per the documentation - it would look something like this..
var capturer = new CCapture({
framerate: 60,
verbose: true
});
The error I'm getting says the CCapture is not defined. Am I missing something here? Not sure how to pull from the library itself.
I've added a function to make sure it is loading before the function itself runs per this instruction, https://stackoverflow.com/a/42848407/8497330.
I'm also not using the npm package because it does not work for the 'webm' format. Looking for a bandaid while the npm package is corrected.
First of You should load your script asynchronously. For instance, you can use this gist: loadScript.
This loadScript function returns a promise which you can use to wait for your library to load.
Secondly, you should not put your code inside the constructor and instead in the componentDidMount like this
componentDidMount () {
loadScript('CCapture.min.js')
.then(() => {
var capturer = new CCapture({
framerate: 60,
verbose: true
});
})
// you can even handle the loading error for your script
.catch((error) => {
console.log('Error when loading CCapture.min.js: ', error);
});
}
In cae you need it you could aslo save the capturer instance in your component state (using this.setState({capturer})) or directly inside the instance object of your component like this.capturer = capturer;
The most likely cause is that the script hasn't been loaded and evaluated by the browser before you're making your call. The is an excellent (and detailed) description of what is happening in this Answer: https://stackoverflow.com/a/14786759/105518
In my experience, the last piece of advice in that answer is generally the least painful to implement: leverage JQuery's getScript function. It handles wiring up all the bits for you:
$.getScript("CCapture.min.js", function () {
const capturer = new CCapture({
framerate: 60,
verbose: true
});
});

The correct order to load Google Client api gapi and angular js

It's kind of tricky how to load js files in an Angular project together with Google Client js api.
This question is talking about the correct order of doing this.
Angular Js and google api client.js (gapi)
And there is an Official Doc talking about this,
https://cloud.google.com/developers/articles/angularjs-cloud-endpoints-recipe-for-building-modern-web-applications/.
One thing in the doc is that it uses window.init() inside of init which will be causing an infinite loop.
As willlma pointed out, we should use a different name for the function.
But I have met an error of
Uncaught TypeError: window.initGAPI is not a function
The project is created by using yeoman generator for angular.
The order of loading js in index.html
<script src="scripts/app.js"></script>
<script src="scripts/controllers/main.js"></script>
<script src="scripts/controllers/about.js"></script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>
app.js(only the latter part of this file):
var init = function(){
console.log("gapi init");
window.initGAPI();
}
main.js:
angular.module('testApp')
.controller('MainCtrl', function ($scope, $window) {
$window.initGAPI = function(){
console.log("controller inti");
}
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
});
I have put some logs to test and found that the definition for $window.initGAPI is executed before loading the cliet.js which calls window.init, but inside of window.init, window.initGAPI is not defined. It seems in the main controller, defining a function called initGAPI to object window failed.
I think is not so easy to correctly load both libraries each in its way, because both are asynchronous in a different way.
Instead, is easier to let one load the other.
The first and simplier approach is to put the client.js lib at the end of all scripts, and then do a manual Angular bootstrap when the Google library is fully loaded.
Other method could be the opposite, so let Angular create the Google client.js script tag and load the library.
Check this project: https://github.com/canemacchina/angular-google-client
I've create this library to help me using Google client library in Angular, and it use the second method...
I had a similar issue. Perhaps you can try something like this for the init function so that it retries again when the controller is not loaded yet.
function init() {
if (window.initGapi != undefined) {
window.initGapi();
}
else {
setTimeout(init, 500); // wait for 500 ms
}
}

Why is this Javascript library available in browser but not in PhoneGap?

I have defined a library in Javascript that works great when I am in a browser but whose name isn't found when running under PhoneGap on my device.
The library is defined as so:
(function(bsdi, $) {
bsdi.SomeName = "XYZ";
bsdi.addDays = function (date, days) { ...stuff here...}
....
}(bsdi = window.bsdi || {}, jQuery));
Later, in a .js file that is loaded last, I have:
function knockoutFn() {
var self = this;
if (bsdi.SomeName == "XYZ") { <<--- CRASHES HERE, "bsdi not defined" but only on Device
...stuff here...
}
}
// Happens to use Knockout...
var koFn = new knockoutFn();
ko.applyBindings(koFn);
function init() {
if (isPhoneGap) {
document.addEventListener("deviceready", onDeviceReady, false);
}
else {
koFn.InitPage();
}
}
function onDeviceReady() {
// Now safe to use the Cordova API
koFn.InitPage();
}
What happens is that a normal web browser handles this just fine. However, when I download to my iPhone using the PhoneGap Build app, it gets to "bsdi.SomeName" and crashes because bsdi is not defined. I thought that my method for defining the bsdi library was correct but, obviously, there is something in PhoneGap that doesn't like this. Note that "isPhoneGap" is true and we do use the addEventListener on the device.
Any ideas are greatly appreciated!
UPDATE: On a hunch, I tried moving the bsdi object into the same .js file as the code that uses it. In this case, it finds the object and uses it correctly. When it is an external file, however, it fails. And yes, I have triple-checked that the file exists and is at the correct location. Again, it works fine in a browser!
If window.bsdi isn't defined, then (as posted in your question) your initialization code never ensures that window.bsdi is defined by the time the code is finished. All it does is add those properties to the new empty object passed in, but that won't have any effect on anything once the initialization function is finished.

Categories

Resources