I started a new Symfony 5.2.x application which will have only some minimal javascript. For that, I decided to use AlpineJS. For the static files, I'm using Webpack Encore.
I read AlpineJS documentation and I even have an example for how instantiate a new AlpineJS instance. I'm not using defer property when I'm including JS.
Here's a part of my code:
HTML:
<nav x-data="navbar()">...</nav>
app.js:
import 'alpinejs';
function navbar() {
return {
...
}
}
However, when I'm refreshing the page, there's an error when I access the console log. "TypeError: navbar() is not a function". What should I do in this case? Have anyone tried to use this framework with Webpack Encore?
You can fix this using window.navbar = navbar;, like so:
import 'alpinejs';
function navbar() {
return {
...
}
}
window.navbar = navbar;
Explanation of this: bundlers (like Webpack) try to keep functions scoped to their modules, ie. not to pollute the global window scope. However when Alpine.js reads x-data="navbar()" it tries to find navbar in the global/window scope (ie. window.navbar), hence the fix.
Related
We are trying a POC of adding Typescript and Webpack to our Angularjs project.
I am able to get my webpack bundle to generate, however at runtime the program cannot find the various functions in my validator.js. Can you please offer some advice?
login-view.components.ts
declare var findFormNode: any; //function in validator.js
//LogInUser
self.login = function ($event, command) {
if (findFormNode($event.target.id)) {
...
}
}
main.ts is importing the file
import "./../../../CommonStaticFiles/include/js/Validators.js";
bundle.js
eval("/* WEBPACK VAR INJECTION */(function($) {/*\r\n\r\n VALIDATORS\r\n\r\n ... n\n\nfunction findFormNode(
error
ReferenceError: findFormNode is not defined
at LoginController.self.login (login-view.component.ts:28)
at fn (eval at compile (angular.js:NaN), <anonymous>:4:267)
at callback (angular.js:29019)
In order for your functions to be properly imported, there are few things that you have to make sure of.
First, make sure you are exporting your functions correctly. Here's an example of how to export a function from Validator.js:
export const validateFunc1 = ():void => {};
Next, you have to make sure you are using proper import syntax. In order to import the function above, you would do the following:
import {validateFunc1} from "./../../../CommonStaticFiles/include/js/Validators.js";
Alternatively, if you want to import all exported functions at once, then you can use this syntax:
import * as validatorFuncs from "./../../../CommonStaticFiles/include/js/Validators.js";
Lastly, check that the location of Validators.js is correct. It's a common mistake to be looking in the wrong directory. Your code editor can usually help you find the right path to use.
I am installing Flickity using npm: npm i flickity.
Flickity version is 2.2.0
Then I call and use like this:
import Flickity from 'flickity'
const flickity = new Flickity(el, options)
console.log(flickity)
I have checked the function Flickity and realize that it is minified after building via webpack, and it seems to return the different result for flickity object. Therefore, it causes the action/methods on flickity object to behave differently. Please see the attached screenshot below for better illustration:
Development environment:
Minified via webpack:
Could anyone give suggestions on what is wrong in my situation to fix this issue?
Update: One important piece of information I haven't mentioned is that flickity object is initialized inside a vue component. It might be the reason for this problem.
carousel.vue
import Flickity from 'flickity'
export default {
data () {
return { options } // options object
}
mounted () {
this.instance = new Flickity(this.$el, this.options)
console.log(this.instance)
}
}
I am using vue 2.6.10. The result this.instance is different on the two environments as I stated above. I still need help on this issue.
The right syntax is:
import Flickity from 'flickity';
EDIT:
It seems to work correctly, take a look at my snippet (I've used a react template but also plain es6 should be fine)
I have a fresh Laravel 5.8 installation and I would like to include the js modules from MDBootstrap.
In my bootstrap.js file I have:
require('./mdb/modules');
The ./mdb/modules.js file has:
exports.modules = [
'./js/_intro-mdb-pro.js',
'./js/scrolling-navbar.js',
'./js/vendor/jquery.easing.js',
'./js/vendor/velocity.js',
'./js/vendor/chart.js',
'./js/vendor/wow.js',
... 30 more
];
The compilation works ok, but of course, it doesn't take any effect from these modules include.
I don't know how to include all of them at once as they are not looking like a regular module so I can import like 'import * from 'my-module'
I also tried the ES6 way:
import * as MDBootstrap from './mdb/modules';
but I got the same result: successful compilation without including them into the compiled js file.
The content of these 'modules' doesn't seem to look like a normal module where we export default {} or some other functions or variables. It looks like:
//mdb/js/scrolling-navbar.js
"use strict";
(function ($) {
var SCROLLING_NAVBAR_OFFSET_TOP = 50;
$(window).on('scroll', function () {
var $navbar = $('.navbar');
if ($navbar.length) {
if ($navbar.offset().top > SCROLLING_NAVBAR_OFFSET_TOP) {
$('.scrolling-navbar').addClass('top-nav-collapse');
} else {
$('.scrolling-navbar').removeClass('top-nav-collapse');
}
}
});
})(jQuery);
Even 'exports.modules = [..]' is not familiar to me. I know about 'module.export = ...' but this 'exports' looks like it's a Node.js object.
I know there's also another method to include the dist version of the plugin. I also tried it, but I got some errors: 'Identifier '_classCallCheck' has already been declared'. I looked deeper and I found that actually many of those files are declaring the '_classCallCheck' function and of course that it a redeclare error. Maybe I can refer to this particular error directly to them (MDBootstrap).
So here I am, trying to include and use these modules/files in my Laravel project without success. Any help is appreciated.
I have put my js files eva.min.js/feather.min.js and so on in vendor dir, then I imported them in ember-cli-build.js app.import('vendor/eva.min.js'). But how to use it?
I tried something like import eva from 'eva'/'eva.min'/'eva.min.js' or import Eva from 'eva'; and so on, but it doesn't work.
app.import('vendor/eva.min.js');
app.import('vendor/bootstrap.min.js');
app.import('vendor/feather.min.js');
app.import('vendor/popper.min.js');
app.import('vendor/jquery-slim.min.js');
app.import('vendor/swipe.js');
import Swipe from 'swipe';
Console usually gives me the could not find the module error.
And I don't have a deep background in programming, so I would highly appreciate if you explained the problem as simple as possible.
UPD: I found all js code as npm package (it happens that the js files weren't third-party)
https://www.npmjs.com/package/feather
https://www.npmjs.com/package/popper.js
https://www.npmjs.com/package/jquery-slim
https://www.npmjs.com/package/swipe
https://www.npmjs.com/package/bootstrap
https://www.npmjs.com/package/eva-icons
But all your responses were helpful. Anyway in the near future I expect to use third-party libraries.
A quick way is to use scriptjs and it allows you to load any javascript into your component in the following way: (I am using Yammer as an example)
import $scriptjs from 'scriptjs';
componentDidUpdate() {
//script loader
setTimeout(function(){
$scriptjs('https://c64.assets-yammer.com/assets/platform_embed.js',
() => {
window.yam.connect.embedFeed(YammerHelper.loadComments());
});
}, 1000);
}
You should get the idea how to consume it. Check their docs with lots of examples.
This is not the best solution. But one way of using the third party js is,
1) say you have a function in your js file vendor/third-party.js
someFunction = function (element) {
...
console.log("works")
};
2) Then import it in your ember-cli-build.js
...
app.import('vendor/third-party.js');
...
3) After importing restart your server.
Use the function directly in your controller/component as
window["someFunction"]
Unless the JavaScript library being used explicitly supports the import X from 'y' syntax then when you import in the build using the app.import syntax you just use it in your app just as the plugin documentation describes.
So for Swipe you would do the following.
Based on this documentation: https://github.com/thebird/Swipe
// ember-cli-build.js
app.import('myswipe.js`);
// component.js
/* global Swipe */ // This silences the linter from throwing errors...
classNames: ['swipe'],
didInsertElement() {
this._swipe = Swipe(this.element, {
option1: option1
});
}
// component.hbs
<div class='swipe-wrap'>
{{yield}}
</div>
This codes creates a component to control your swipe plugin.
This code would create a swipe object and isolate it to the component.
Again when you use the app.import you are just loading the library on boot. The library does whatever it says it will do in the docs. Sometimes they register a global object, sometimes they dont.
I am using ember-remarkable because I want to add both markdown parsing and syntax highlighting to my project. The only thing it's missing is line numbers, which I want to add by using this library: highlightjs-line-numbers.js
I override ember-remarkable's md-text component with the following:
import MDTextComponent from 'ember-remarkable/components/md-text';
export default MDTextComponent.extend({
tagName: null,
didRender() {
this._super(...arguments);
this.$("code[class*='language-']").each((i, block) => {
this.$(block).addClass('hljs');
hljs.lineNumbersBlock(block);
});
}
});
Everything works! However, my editor complains that hljs is not defined, even though it is available on the page.
How do I avoid this error?
If it is ES6 modules, just import it. Otherwise you can use it as window.hljs.
When you run your js code in browser, window is the root of the global variables. So you can access it as window.hljs.
If you run your code in Fastboot, this should be a better way to access global objects: (window || Fastboot || global).hljs.
On the other hand, instead of using the global object container, you can just prevent linter to give this error. For eslint, see this configuration: Specifying Globals.
You should explicitly import your dependencies, if for no other reason than to communicate to future readers. import hljs from 'highlightjs-line-numbers'