I'm really confused about importing a VueJs component.
I'm using Vuejs 2.2.4, and I need to import a Vuejs component. Here is my app.js:
Vue.component('Test', require('./Test.vue'));
const app = new Vue({
el: '#vue-app',
});
Assume app.js is located in MyProject/js/app.js
And here is my component SimpleCompnent.vue :
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Simple Component</div>
<div class="panel-body">
I'm an Simple component!
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Simple Component mounted.')
}
}
</script>
Assume SimpleCompnent.vue is located in MyProject/js/SimpleCompnent.vue
Seems like Vue can't load the component! It throws this error in the browser console:
Uncaught ReferenceError: require is not defined
Indeed, require cannot be used in a browser context without proper support, so you have couple of options:
Create (or fix) support for require.js in your app (see how here). As a first step, make sure you have a script tag that fetches require.js and has a data-main attribute that points to your app's entrypoint.
Use a CommonJS implementation for the client, like webpack or browserify, so requires can be written naturally in client-side code.
Use another module system implementation, e.g. on top of system.js or ES2015.
Either way, if you chose an implementation that uses imports (i.e. an ES2015 module system), you may want to use a transpiler that down-compiles your code to a language level the browser supports (avoiding those nasty Unexpected token import errors).
Try:
import Test from './Test.vue'
You can see an example of it here.
Related
I have obviously a misconception of how the vue3 "In-DOM Root Component Template"-mechanism is working. Any hints appreciated!
I modified an example vite project to use "In-DOM Root Component Template".
index.html
<body>
<div id="app">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
</div>
<hello-world msg="Vite + Vue"></hello-world>
</div>
<script type="module" src="/src/main.js"></script>
</body>
main.js
import { createApp } from 'vue'
import './style.css'
import HelloWorld from './components/HelloWorld.vue'
const app = createApp({})
app.component('HelloWorld',HelloWorld)
app.mount('#app')
HelloWorld is the default example component, installed by vite install.
Result: The rendered output is empty, the div#app-innerHtml is not used as Template as expected.
I had an js error here const app = createApp()
Error: Cannot read properties of undefined (reading 'render').
Vue Options should not be undefined. Please replace it with:
const app = createApp({})
You register you component in PascalCase as HelloWorld and use it the same way in HTML. But you should use kebab-case <hello-world>.
There is an explanation in the Vue Docs Using a Component about this:
If you are authoring your templates directly in a DOM (e.g. as the
content of a native element), the template will be subject
to the browser's native HTML parsing behavior. In such cases, you will
need to use kebab-case and explicit closing tags for components
Please pay attention to the explicit closing tags also.
The app works When you fix both problems. Here is the working playground
https://stackblitz.com/edit/vue-n2v2y4?file=public/index.html
Currently, I am trying to implement a keen-slider library(https://www.npmjs.com/package/keen-slider).
For installation, we need to add import 'keen-slider/keen-slider.min.css'.
In that case, the keen slider CSS is added to global, as you know.
The CSS is included globally in the page markup. From my perspective, it should be included only on pages where the slider is used
Is there any solution to solve this problem?
I'm not sure to understand the issue. You can always choose to import a file (CSS or whichever format you want) globally or in a specific file.
For your use-case, as soon as you install the dependency (npm install keen-slider --save), you will be able to import the minified CSS into the needed component. For example:
import React from 'react'
import 'keen-slider/keen-slider.min.css'
import { useKeenSlider } from 'keen-slider/react'
export function IndexPage(){
const [sliderRef, slider] = useKeenSlider()
return <section className="slider-wrapper">
<div ref={sliderRef}>
<div class="keen-slider__slide">1</div>
<div class="keen-slider__slide">2</div>
<div class="keen-slider__slide">3</div>
</div>
</section>
}
With this approach, you will be only importing the keen-slider.min.css in the IndexPage.
I think, you can try to lazily load your component via:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
Also you should do import 'keen-slider/keen-slider.min.css' inside of OtherComponent.
More info here: https://reactjs.org/docs/code-splitting.html
I am new to Vue.js and trying to create a custom component that uses jQuery formBuilder plugin. When I include the component file inside another component, I am getting an error:
Uncaught ReferenceError: jQuery is not defined in /resources/js/form-builder.min.js
I created a custom component with name formBuilder.vue. Here is the component code:
<template>
<div class="content">
<formBuilder/>
</div>
</template>
<script>
// import './jquery.min.js';
// import './jquery-ui.min.js';
// import './form-builder.min.js';
export default {
created() {
},
data() {
return {
}
},
mounted() {
jQuery(this.$el).formBuilder();
},
methods: {
}
}
</script>
In app.js file, which is placed in resource/js/app.js, I am calling this vue to be recursively used by other components:
window.Vue = require('vue');
require('./bootstrap');
require('admin-lte');
require('./datatable');
import router from './router';
import Datepicker from 'vuejs-datepicker';
import CKEditor from 'ckeditor4-vue';
import FullCalendar from 'vue-full-calendar';
import 'fullcalendar/dist/fullcalendar.css'
import Vue from 'vue';
import jQuery from 'jquery'
import './form-builder.min.js';
Vue.use(VueRouter)
Vue.use(FullCalendar);
Vue.use(CKEditor)
Vue.component("vue-datepicker", Datepicker);
Vue.component('FormBuilder', require('./components/tools/formBuilder.vue').default);
const app = new Vue({
el: '#app',
router
});
This is the component file where i am using formbuilder component
<template>
<div class="content-wrapper">
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark">Questionnaire</h1>
</div>
<div class="col-sm-6"></div>
</div>
</div>
</div>
<div class="content">
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<FormBuilder/> <!--- used formbuilder component --->
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
created() {
},
data() {
return {
}
},
methods: {
}
}
</script>
I have attached the error as well.
Can you guys help me find where I am doing wrong?
Thanks in Advance.
Importing an object into Vue's app JS doesn't automatically produce that object for use by other components.
There are at least two ways to do this (though I recommend avoiding all this and just importing jQuery in the components that need it):
Option 1: Vue.prototype
In your app JS, add jQuery to the Vue prototype after you import it, which will make it accessible to every component using the syntax this.jQuery:
Vue.prototype.jQuery = jQuery
Option 2: window object
Alternatively, you could add it to the window object after importing and use it like window.jQuery:
window.jQuery = jQuery
Option 3: Individual imports
It's probably more readable/maintainable to simply import it in components that use it:
import jQuery from 'jquery'
and then you can use it with the syntax in your example.
That worked for me (Vue 3)
for some reason i had to stop the cli and restart
window.$ = window.jQuery = require('jquery');
Eslint may return "Unexpected top level property" "$". You will need to insert an exception in your package.json
"env": {
...
"jquery": true,
},
It is important to know that jquery will only be available in .vue files. Therefore, your extensions and libraries may report an error. In these cases you will have 2 options:
Transform libraries into a .vue template
Make a local import on top of them.
import jQuery from 'jquery'
I'm using css modules in my react project and using web pack for bundling. While using Jest for testing, as the jest will try to import css files like normal JS files got the below error,
SyntaxError: Unexpected token .
The solution that I found is to use "identity-obj-proxy" to mock scss/css files.But now I cannot use css selectors to test components.For example
Test
it('renders 2 children', () => {
expect(component.find('.mockyApp').children().length).toBe(2);
});
render method
render() {
if (this.state.host) {
return (
<div className={style.mockyApp}>
<div className={style.sidePage}>
<SideBar clickHandler={this.setPage} selected={this.state.page}/>
</div>
<div className={style.mainPage}>
{this.renderComponent()}
</div>
</div>
);
}
// ... .. rest of render method
}
I'm using import style from './mocky.scss'; to import styles and using the style object for class names. Before using css-modules the above test used to work.Now my question is how will I be able to test using css selectors and what change needs to be done to make this work?. Googling didn't help
I don't think there exists a good solution for this problem yet.
Few ways you can still test it:
1) Add a static class name just for testing:
<div className={`${style.mockyApp} mockyApp`}>
<div className={style.sidePage}>
<SideBar clickHandler={this.setPage} selected={this.state.page}/>
</div>
<div className={style.mainPage}>
{this.renderComponent()}
</div>
</div>
2) Use a data attribute to target that element.
Component
<div className={`${style.mockyApp} mockyApp`} data-jest="mockyApp">
<div className={style.sidePage}>
<SideBar clickHandler={this.setPage} selected={this.state.page}/>
</div>
<div className={style.mainPage}>
{this.renderComponent()}
</div>
</div>
Render
it('renders 2 children', () => {
expect(component.find('[data-jest=mockyApp]').children().length).toBe(2);
});
Both ways work but they include adding stuff to the DOM which gets shipped to production, which means more bytes being sent to your users.
If you are going with the second approach, you can consider writing a Babel plugin that strips out all data-jest attributes from the DOM in the transpilation process.
I'd like to use two separate layouts for my aurelia app. Difference between them is that one doesn't have a sidebar. Currently I'm using one layout file defined as below:
<template>
<div class="container">
<router-view></router-view>
</div>
</template>
If an active route needs this sidebar to appear I'm just putting it into its view.
What I'd like to achieve is to add another layout that would have this sidebar by default:
<template>
<require from="../common/elements/sidemenu/sidemenu"></require>
<div class="container">
<sidemenu></sidemenu>
<router-view></router-view>
</div>
</template>
So the question is - how to do this? Is it even possible with an aurelia app to have multiple layouts (or master pages, however you call those)?
Use aurelia.setRoot()
You can manually set up your application by specifying a script with configure instructions in your index.html. Typically, this is set to main.
index.html
<body aurelia-app="main">
In this script you can specify a root view model using aurelia.setRoot('root'). If no argument is provided, the convention is to use 'app'.
main.js
aurelia.start().then(() => aurelia.setRoot());
However, you can inject the aurelia object anywhere in your application, and call the setRoot function at any time to load a different root view model.
home.js
#inject(aurelia)
export class HomeViewModel {
constructor(aurelia) {
this.aurelia = aurelia;
}
doStuff() {
this.aurelia.setRoot('withSidebar');
}
}
One common use case for this is having a login page, and I've created a complete template for this use case that you can review, clone, or fork here: http://davismj.me/portfolio/sentry/