I'm trying to add popovers from bootstrap 4 into my vue.js app. I could probably use something like https://www.npmjs.com/package/vue-popperjs, but I'd like to make it work old way, without using additional libraries (just so I could figure out the principle on how to do that)
I have installed Popper.js with npm install --save popper
In my webpack.config.js I also have:
plugins: [
new WebpackNotifierPlugin(),
new webpack.ProvidePlugin({
_: 'lodash',
$: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
jQuery: 'jquery',
popper: 'popper'
})
],
Then I'm tring to build a vue component:
<template>
....
<button type="button" class="btn btn-link" title="" data-container="body" data-toggle="popover" data-placement="bottom" data-original-title="Connection String" aria-describedby="popover253231">
Click to show
</button>
....
</template>
<script>
const _ = require("lodash");
const $ = require("jquery");
// This doesn't work
//const poppper = require("popper");
var d = {
data() {
...
},
created: function() {
// Load data with $http module
},
updated: function() {
$(function () {
$('[data-toggle="popover"]').popover()
})
},
};
export default d;
</script>
The button will appear only after load, because it has a parent element that has v-for binding on the data loaded with ajax.
I don't know how to require popper, so the line $('[data-toggle="popover"]').popover() resolves (it cannot find function popover())
Also the line const popper = require("poppper") doesn't work either with the error Module parse failed: 'return' outside of function. My guess is that I can't load popper with require, because it is not built for it.
After some struggling and trying completely random ideas, I had the one that worked. Turns out the problem was that I was using bootstrap that is installed into ASP.NET MVC as a bundle (so it added it as <script src='..'/> to the page).
So after I:
npm install --save bootstrap
Added bootstrap: 'bootstrap' to ProvidePlugin definition in webpack.config.js
Added require("bootstrap") into my vue file
It started to work. I didn't even have to require 'popper' for some reason - probably because bootstrap already contains it?
Though I am still not sure whether this is a proper way to solve the problem
Using Vuejs Directive
const bsPopover = (el, binding) => {
const p = []
if (binding.modifiers.focus) p.push('focus')
if (binding.modifiers.hover) p.push('hover')
if (binding.modifiers.click) p.push('click')
if (!p.length) p.push('hover')
$(el).popover({
animation: false,
placement: binding.arg || 'top',
trigger: p.join(' '),
html: !!binding.modifiers.html,
content: binding.value,
});}
Vue.directive('tooltip', {
bind: bsTooltip,
update: bsTooltip,
unbind (el) { $(el).tooltip('dispose') }});
Related
I am trying to create a popover in the Javascript of my Angular 12 project. I am using Boostrap v5.0.1. I can't seem to get rid of a name error when I am trying to create the popover:
var exampleEl = document.getElementById(item.name + index);
var tooltip = new bootstrap.Popover(exampleEl, {
container: 'body',
animation: true
});
Typescript is telling me "Can't find name bootstrap".
I have added bootrap.js to my angular.json file:
"scripts": [
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
]
According to the docs, popper.js is included in the bundle file. I am not using jQuery and do not want to include it. I have not seen another post with a similar issue so I must be just overlooking something small. Any ideas?
Posting this declaration at the top of the file worked:
declare var bootstrap: any;
I installed bootstrap 4, jquery, popper by npm. When I load website it show error in console about can't get file popper.js, I check again that I see one file popper.js was load by require.js and one file popper.js was noticed was not found by bootstrap. They have different path. file success have path: http://localhost:9000/Libs/popper.js/dist/umd/popper.js and file fail is http://localhost:9000/popper.js
In below picture, pic 1 show configure path of library js. Pic 2 show librarys was load success, and pic 3 notice popper.js was not load.
I don't understand why bootstrap can't recognize popper.js was loaded by requie.js.
Everyone can help me explain about problem for me.
Thanks!
Try using:
bootstrap.bundle.js
or:
bootstrap.bundle.min.js
https://getbootstrap.com/docs/4.0/getting-started/contents/
The docs show that those two files mentioned come with popper included so you won't need to require it.
If that doesn't work search your source files for /popper.js it may be as simple as fixing a reference somewhere else.
Instead of doing this:
require(["bootstrap"], function(bootstrap) {
// do nothing
});
Try this which loads popper first:
require(["popper"], function(popper) {
window.Popper = pop
require(["bootstrap"]);
});
Alternatively you can use the CDN links. Bootstrap suggests using the CDN versions before you include the compiled bootstrap.
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
Hey this is my first response on a stackoverflow question but since I have been struggling with it myself, I wanted to share my answer. Just like other answers say, bootstrap requires the popper js but it references popper itself on the root so it doesn't matter if you load it or not, bootstrap looks for it on the root while you have it on a deeper directory. Look at the code below and you can see it uses require('popper.js'):
bootstrap.js
The solution is to use require to define module "popper.js" and exactly as this name like below:
require.config({
baseUrl: 'lib',
paths: {
main: 'main',
jquery: 'jquery/dist/jquery',
'jquery-slim': 'jquery/dist/jquery-3.3.1.slim.min',
'jqueryUnobtrusive': 'jquery-validation-unobtrusive/jquery.validate.unobtrusive',
'bootstrap': 'bootstrap/dist/js/bootstrap',
'knockout': 'knockout/knockout-latest',
'ajax': 'jquery-ajax/jquery.unobtrusive-ajax',
'shop': '/scripts/shop/shop',
'domready': 'requirejs/domready',
'shoporder': '/scripts/shoporder/shoporder',
'popper': 'popper.js/dist/umd/popper'
}});
define("popper.js", ['popper'], () => {
require(['popper'], () => {
require(['bootstrap']);
});
define(['main', 'jquery', 'jquery-slim'], () => {
require(['jqueryUnobtrusive', 'ajax']);
require(['knockout']);
require(['jquery']);
require(['popper.js']);
});
This way bootstrap looks for the correct directory.
Bootstrap requires Popper to be available in the global scope, you can solve the issue by adding exports to the shim configuration:
shim: {
bootstrap: {
deps: ['jquery','popper']
},
popper: {
exports: "Popper"
}
}
Also you need to make sure that bootstrap defines the name of the module correctly. You can check that in the opening lines the bootstrap.js file
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? factory(exports, require('jquery'), require('popper'))
: typeof define === 'function' && define.amd
? define(['exports', 'jquery', **'popper'**], factory)
: (...)
I tried to require materialize in Vue and Laravel
in bootstrap.js I have
window.Materialize = require('materialize-css');
in App.vue component I have
mounted(){
Materialize.toast('I am a toast!', 4000)
}
and received
"Uncaught ReferenceError: Materialize is not defined"
message.
Either drop a script tag with materialize js or, make sure jquery is loaded before requiring materialize.
I suppose you have a browserify setup and if you do you can do something like that:
require('jquery')(window);
require('materialize-css')(window);
Or something like that:
global.jQuery = require('jquery')
global.Materialize = require('materialize-css')
Or import globally jQuery only then simply var Materialize=require('materialize-css') and use the variabile instead.
For webpack setups add a plugin for the stuff you have installed via npm and need globally:
plugins:[
new webpack.ProvidePlugin({
$: "jquery",
jQuery:'jquery',
jquery:'jquery'
}),
],
I am trying to achieve the following:
bundle (in this order) jquery, tether, and bootstrap.js.
load this bundle within a HTMLpage and beneath it load other page specific scripts.
To achieve this I am using webpack 2 and the CommonsChunkPlugin. Here is my config.
For entries I have:
const scriptsEntry = {
blog_index: SRC_DIR + "/js/pages/blog_index.js",
blog_about: SRC_DIR + "/js/pages/blog_about.js",
vendor: ["jquery", "tether", "bootstrap"]
};
In the plugins section:
scriptsPlugins.push(
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
filename:"vendor.bundle.js",
minChunks: 2
}),
...
}));
Inside 'index.html' I load the bundles:
<script src="{{ url_for('static', filename='dist/js/vendor.bundle.js') + anti_cache_token }}"></script>
<script src="{{ url_for('static', filename='dist/js/home.js') + anti_cache_token }}"></script>
Inside the source directory in the blog_index.js I make use of jquery:
import $ from "jquery";
$(".home-click").click(function () {
alert("clicked from .home-click");
});
The result:
everything bundles without any errors.
when I click .home-click the alert box fires as expected.
checking the bundled files I see that:
vendor.bundle.js contains: jquery, tether, and bootstrap.
looking inside, for instance, blog_index.js (after it was run through webpack 2), I notice that the jquery import is not bundled inside this file, but vendor.bundle.js (this is as expected).
However, I have the following problem when I check the browser console:
I tried switching the order of the libraries in this line vendor: ["jquery", "tether", "bootstrap"], but nothing changed--the error is still there.
Do you know how can I solve this, preferably without using additional webpack plugins?
Bootstrap's javascript assumes that jQuery is hooked on the window object, it does not require it or anything.
By bundling stuff up, you do not expose variables to the global scope, or at least you should not be doing that. So the bootstrap code cannot find jQuery.
Add this to your plugins and you should be ok
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
tether: 'tether',
Tether: 'tether',
'window.Tether': 'tether',
})
This will replace all instances where jQuery is assumed as global with the export of the jQuery package, which is the jQuery object. Same for Tether
I have about 3 different errors that can occur while loading the same page. I get different errors when I refresh the same page: jquery ui loads before jquery, or underscore does not load in time to be a dependency. Is there a way to make sure the configuration modules wait until their depenedencies load before loading themselves? I am using the following:
main.js
require.config({
paths: {
jQuery: 'libs/jquery/jquery-wrapper',
Underscore: 'libs/underscore/underscore-wrapper',
Backbone: 'libs/backbone/backbone-wrapper',
}
});
require([
'src/app',
'order!libs/jquery/jquery-min',
'order!libs/jquery/jquery-ui-min',
'order!libs/jquery/jquery.ui.selectmenu',
'order!libs/underscore/underscore-min',
'order!libs/backbone/backbone-min',
], function (App) {
App.initialize();
});
I grab injected dependencies from the page.
app.js
define([
'jQuery',
'src/global'
], function ($) {
var initialize = function () {
var d = $('#dependencies').html();
require($.trim($('#dependencies').html().toString()).split(','), function () {
});
}
return {
initialize: initialize
};
});
I was using Require v2, which got rid of order. I switched back to version 1 and the problem was resolved.
I switched to Require 2.0 and employed a shim that is working for the most part.