bootstrap-vue modal not displaying - vue.js

environment
dotnet core 2.1.0
"bootstrap-vue": "^2.0.0-rc.11",
"nuxt": "^1.4.1",
"vue": "^2.5.16",
"vue-axios": "^2.1.1",
"vue-router": "^3.0.1",
"vue-server-renderer": "^2.1.8",
"vue-template-compiler": "^2.5.16",
"vue-toasted": "^1.1.24",
"vuex": "^3.0.1",
"vuex-router-sync": "^4.0.1"
I can't figure out how to get a simple bootstrap-vue modal working. The modal-sample component renders, with the button visible, but when the button is clicked nothing happens (modal doesn't "show").
However, in the vue dev tools, I can see the show event was emitted. Also, if I copy and paste the code in the bootstrap-vue playground it works, so it has to be my set up. Not sure if it matters but it's also running in a dotnet core environment.
webpack.config
const VueLoaderPlugin = require('vue-loader/lib/plugin');
...
resolve: {
extensions: ['.js', '.vue'],
alias: {
'vue$': 'vue/dist/vue',
...
}
...
,
module: {
rules: [
{ test: /\.vue$/, include: /ClientApp/, use: 'vue-loader' },
{ test: /\.js$/,
include: [/ClientApp/,
require.resolve("bootstrap-vue")],
use: 'babel-loader' },
{ test: /\.css$/,
use: isDevBuild ? ['vue-style-loader', 'style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader' }) },
{ test: /\.(png|jpg|jpeg|gif|svg)$/,
use: 'url-loader?limit=25000' }
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin({use: 'site.css', fallback: 'vue-style-loader'})
])
}];
app-root.vue
import Swapshift from './modal-sample'
Vue.component('modal-sample', Swapshift);
modal-sample.vue
<template>
<div style="margin-top: 20px; padding: 10px;">
<b-button variant="primary" v-b-modal.newSwapShiftModal>New Swap Shift</b-button>
<b-modal id="newSwapShiftModal" title="New Swap Edit" >
<div class="d-block text-center">
<h3>Hello From My Modal!</h3>
</div>
</b-modal>
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex'
import bModal from 'bootstrap-vue/es/components/modal/modal'
import bModalDirective from 'bootstrap-vue/es/directives/modal/modal'
export default {
components: { bModal },
directives: { bModalDirective },
data() {
return {
swapshift: {
id: 1,
status: {
id: 1,
description: 'Requested'
}
}
}
},
computed: {
},
methods: {
},
async created() {
console.log('...in modal-sample1');
}
}
</script>

HTML attributes all get translated to lowercase. This includes parts of the directive attribute on your button. So what is happening is that when the v-b-modal directive receives the modifiers (ie. .newSwapShiftModal), it receives newswapshiftsodal from the browser (all attributes are always lowercased by the browser).
So you need to set the id on the modal to also be lowercase (as attribute values inside quotes retain their case).
<template>
<div style="margin-top: 20px; padding: 10px;">
<b-button variant="primary" v-b-modal.new-swap-shift-modal>New Swap Shift</b-button>
<b-modal id="new-swap-shift-modal" title="New Swap Edit" >
<div class="d-block text-center">
<h3>Hello From My Modal!</h3>
</div>
</b-modal>
</div>
</template>
Example fiddle showing case sensitivity issues with IDs: https://jsfiddle.net/4cnk28yw/
EDIT: also register the directive with the correct name (as mentioned by #ittus):
import { mapActions, mapState } from 'vuex'
import { BModal, VBModal } from 'bootstrap-vue'
export default {
components: { BModal },
directives: { 'b-modal': VBModal },
// ...
}

Directive name should be b-modal. You should try changing:
directives: {
'b-modal': bModalDirective
}

Related

add Base64UploadAdapter for ckeditor

I use component locally method for use ckeditor and add Base64UploadAdapter plugin in config file.
but i have error ckeditor-duplicated-modules
how can i add truly Base64UploadAdapter plugin to ckeditor in nuxt component for Reuse this component.
//ckEditorNuxt
<template>
<ckeditor
:editor="editor"
:value="value"
:config="config"
:tagName="tagName"
:disabled="disabled"
#input="event => $emit('input', event)"
/>
</template>
<script>
let Classiceditor
let CKEditor
if (process.client) {
Classiceditor = require('#ckeditor/ckeditor5-build-classic')
CKEditor = require('#ckeditor/ckeditor5-vue2')
} else {
CKEditor = {component: {template: '<div></div>'}}
}
export default {
name: "ckEditorNuxt",
components: {
ckeditor: CKEditor.component
},
...and more
and use in this code.
<template>
<v-card height="100%">
<h4 class="pa-2">{{ title }}</h4>
<client-only placeholder="loading...">
<ckEditorNuxt v-model="contentHolder" :config="editorConfig"/>
</client-only>
</v-card>
</template>
<script>
import ckEditorNuxt from "#/components/ckEditor/ckEditorNuxt";
import {Base64UploadAdapter} from "#ckeditor/ckeditor5-upload";
export default {
name: "PersianCKEditor",
components: {
ckEditorNuxt,
},
props: {
title: String
},
data() {
return {
editorConfig: {
plugins: [
Base64UploadAdapter
],
placeholder: this.title,
removePlugins: ['Title'],
and more...

ESLint + Prettier warning in Vuejs

I have installed ESLint + Prettier in my Vuejs project. Saving files causes the prettier to throw the following warning. Much appreciated if someone could explain what causes this warning.
"Replace `·:to=\"{·name:·'About',·query:·{·lang:·$i18n.locale·}·}\"·tag=\"button\">About</router-link` with `⏎········:to=\"{·name:·'About',·query:·{·lang:·$i18n.locale·}·}\"⏎········tag=\"button\"⏎········>About</router-link⏎······`"
The vuejs file:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>|
<router-link
:to="{ name: 'About', query: { lang: $i18n.locale } }"
tag="button"
>
About
</router-link>
<p>{{ $route.query.lang }}</p>
<h2>{{ $i18n.locale }}</h2>
</div>
<router-view />
</div>
</template>
.prettierrc.js:
module.exports = {
singleQuote: true,
semi: false
}
.eslintrc.js:
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/essential', '#vue/prettier'],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'prettier/prettier': ['error']
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
env: {
jest: true
}
}
]
}
The line-wrapping you're observing is done by Prettier's core formatting. You can avoid it by setting the max line width (printWidth) to something longer than 80.
Configure Prettier with:
// <root>/.prettierrc.js
module.exports = {
printWidth: 200, // max number of characters per line (default: 80)
}
And configure ESLint's prettier/prettier options:
// <root>/.eslintrc.js
const prettierOptions = require("./prettierrc");
module.exports = {
rules: {
"prettier/prettier": ["error", prettierOptions],
},
};

How to implement ag-grid into nuxt.js

How to integrate ag-grid to work with nuxt.js via the nuxt.config file?
The error I'm getting:
commons.app.js:16278 Uncaught TypeError: Cannot read property '_init' of null
at AgGridVue (commons.app.js:16278)
at Function.Vue.use (commons.app.js:16233)
at Module../plugins/ag-grid.client.js (app.js:5186)
at webpack_require (runtime.js:791)
at fn (runtime.js:151)
at Module../.nuxt/index.js (app.js:1997)
at webpack_require (runtime.js:791)
at fn (runtime.js:151)
at Module. (app.js:236)
at Module../.nuxt/client.js (app.js:1308)
ag-grid.client.js:
import Vue from "vue";
import { AgGridVue } from "ag-grid-vue";
Vue.use(AgGridVue);
nuxt.config.js:
plugins: [
"#/plugins/element-ui",
"#/plugins/tooltip",
"#/plugins/calendar",
"#/plugins/ag-grid.client.js"
],
The file to load table into:
<template>
<div class="flex h-full">
<no-ssr>
<ag-grid-vue style="width: 500px; height: 500px;"
class="ag-theme-balham"
:columnDefs="columnDefs"
:rowData="rowData">
</ag-grid-vue>
</no-ssr>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
columnDefs: null,
rowData: null
};
},
beforeMount() {
this.columnDefs = [
{ headerName: "Make", field: "make" },
{ headerName: "Model", field: "model" },
{ headerName: "Price", field: "price" }
];
this.rowData = [
{ make: "Toyota", model: "Celica", price: 35000 },
{ make: "Ford", model: "Mondeo", price: 32000 },
{ make: "Porsche", model: "Boxter", price: 72000 }
];
}
};
</script>
In the file "ag-grid.client.js", you can't add a component with Vue.use, you need to use Vue.component and it'll register it globally:
import Vue from 'vue'
import { AgGridVue } from 'ag-grid-vue'
Vue.component('ag-grid-vue', AgGridVue)
And then you don't need to set the tag "".

Vue 2.5: Passing prop to component. Prop gets bundled in variable name

I'm new to Vue.js and my first try is to make a simple line-chart using ChartJS (vue-chartjs bundle).
I've used the "HelloWorld.vue" as base material, and created a LineChart.js
The problem is that in HelloWorld, i got my variable called datacollection, this name gets passed into my LineChart.js. How do I fix so I dont get the variable name as an object
I get:
datacollection:
{
labels: {...},
datasets: {...}
}
I want:
{
labels: {...},
datasets: {...}
}
Thus, in my LineChart.js I need to do .datacollection. This will make my LineChart.js less reusable, since I always have to remember to name all my variables calling LineChart 'datacollection'.
LineChart.js:
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: ['data', 'options'],
watch: {
'data': function (value) {
// I get the update from backend, but I have to use .datacollection (the variable name from the calling page)
console.log('Ändrat: ', value)
this.renderChart(value.datacollection, this.options)
}
},
data () {
return {
gradient: null,
gradient2: null
}
},
mounted () {
console.log('data in component', this.data)
/*
this.data contains datacollection: {
labels: {
...
},
datasets: {
....
}
}
This wont render any graph since I dont do .datacollection
*/
this.renderChart(this.data, this.options)
}
}
My Graph.vue page:
<template>
<div class='hello'>
<h1>{{ msg }}</h1>
<h2>Graph</h2>
<!-- this.datacollection is printed as expected, {labels: {}, datasets: {}} -->
<p>{{ this.datacollection }}</p>
<section>
<line-chart
:data='{datacollection}'
:options='{chartOptions}'
:width="400"
:height="200"
>
</line-chart>
</section>
<section>
<reactive-example></reactive-example>
</section>
</div>
</template>
<script>
export default {
name: 'Graph',
mounted: function () {
this.axios.get('graph/').then(response => {
console.log(response.data)
this.datacollection = response.data
})
},
data: function () {
return {
msg: 'Welcome to Your Vue.js App',
datacollection: {
labels: ['January', 'February'],
datasets: [
{
label: 'First',
backgroundColor: '#f87979',
data: [40, 20]
},
{
label: 'Second',
backgroundColor: '#aa7979',
data: [20, 30]
}
]
}
}
}
}
</script>
<!-- Add 'scoped' attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
My dependenicies (versions)
"dependencies": {
"axios": "^0.17.1",
"chart.js": "^2.7.1",
"vue": "^2.5.2",
"vue-axios": "^2.0.2",
"vue-chartjs": "^3.0.2",
"vue-router": "^3.0.1"
}
What do I miss?
In your template, you have the following:
<line-chart
:data='{datacollection}'
:options='{chartOptions}'
:width="400"
:height="200"
>
</line-chart>
In ES2015, {datacollection} is shorthand (see New notations in ECMAScript 2015) for creating a new object with a datacollection property with the value of datacollection as its value. In Vue, everything in the quotes of a binding is treated as a javascript expression, so in most modern browsers what that syntax does is create a new object with a datacollection property and pass that object to the component.
Instead, just remove the braces.
<line-chart
:data='datacollection'
:options='chartOptions'
:width="400"
:height="200"
>
</line-chart>

vue babel-loader SyntaxError: Unexpected token on ":click" syntax

I use render function like this:
.script.js:
methods: {
handleClick(data){
console.log(data)
},
render(h, { node, data, store }) {
return (
<span>
<span>
<span>{node.label}</span>
</span>
<span style="float: right; margin-right: 20px">
<a href="javascript:;"
:attr="data.id" #click="handleClick">Edit{data.id}
</a>
</span>
</span>
);
}
}
But babel encoutners error saying the :click has Unexpected token.
.vue:
<template src="./template.html"></template>
<script src="./script.js"></script>
package.json:
"vue": "^2.2.6"
"vue-router": "^2.4.0"
"element-ui": "^1.2.8",
"babel-core": "^6.24.0",
"babel-loader": "^6.4.1",
"babel-plugin-transform-vue-jsx": "^3.4.2",
"vue-loader": "^11.3.4",
"webpack": "^2.3.1",
webpack:
{
test: /\.vue$/,
loader: `vue-loader`,
options: {
loaders: {
js: 'babel-loader'
}
}
},
{
test: /\.js$/,
loader: `babel-loader`,
exclude: /(node_modules)/
}
.babelrc:
{
"presets": [
["es2015", { "modules": false }], "stage-1", "stage-2", "stage-3"
],
"plugins": [
["transform-vue-jsx"],
["transform-object-assign"],
["component", [{
"libraryName": "element-ui",
"styleLibraryName": "theme-default"
}]]
]
}
When i run gulp dist, babel throws an error like follows:
Namespaced tags/attributes are not supported. JSX is not XML.\nFor attributes like xlink:href, use xlinkHref instead.
As #Bert Evans suggested,
after re-reading the reademe docs of https://github.com/vuejs/babel-plugin-transform-vue-jsx, I figured out that i just wrote the code without understanding the syntax of vue-specific jsx syntax.
As the docs says:
Note that almost all built-in Vue directives are not supported when using JSX, the sole exception being v-show, which can be used with the v-show={value} syntax. In most cases there are obvious programmatic equivalents, for example v-if is just a ternary expression, and v-for is just an array.map() expression, etc.
The equivalent of the above in Vue 2.0 JSX is:
render (h) {
return (
<div
// normal attributes or component props.
id="foo"
// DOM properties are prefixed with `domProps`
domPropsInnerHTML="bar"
// event listeners are prefixed with `on` or `nativeOn`
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
// other special top-level properties
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
key="key"
ref="ref"
// assign the `ref` is used on elements/components with v-for
refInFor
slot="slot">
</div>
)
}
So, i changed my code to
render(h, {node,data,store}) {
const link = {
href: `/#/schema-type/${data.id}`
};
return (
<span>
<span>
<span>{node.label}</span>
</span>
<span>
edit
</span>
</span>
);
}
And it works!
Try to write your html as a string:
Vue.component('my-component', {
template: '<div>A custom component!</div>'
});
It looks like you are used to React, but it write a little different.