vuejs2 onclick will not call defined method function - javascript

Very simple but seems to not be working. Must be because i'm new to VueJS. I downloaded this repo https://github.com/creotip/vue-particles. As I want to create a under construction page using this style.
Problem: I need to create a hamburger menu icon in the top right hand corner which on click calls a method to hide and show a div ( really basic stuff ). I've followed the vue JS tutorials and what people have said on stack overflow but I just cant get my template to speak to the method.
When I click on the hamburger button i keep getting "_vm.hello is not a function". What am i doing wrong? Please see screenshot. There must be something simple to solve this.
Heres what my code looks like:-
app.vue
<template>
<div id="app">
<div class="wrap-banner">
<div class="button_container" #click="hello()">
<span class="top"></span>
<span class="middle"></span>
<span class="bottom"></span>
</div>
</div>
</template>
main.js
import Vue from 'vue'
import App from './App'
import Home from './components/home'
Vue.use(Home)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App },
methods: {
hello: function() {
alert('hello')
}
}
})
Screenshot

You need to move hello method to App.vue
App.vue
<template>
<div id="app">
<div class="wrap-banner">
<div class="button_container" #click="hello">
Demo Panel
<span class="top"></span>
<span class="middle"></span>
<span class="bottom"></span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {};
},
methods: {
hello: function() {
alert("hello");
}
}
};
</script>
main.js
import Vue from "vue";
import App from "./App";
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
Checkout demo at https://codesandbox.io/s/8y5yzv00nj

Vue File Architecture
You need to be aware that a Vue file normally has 3 components (HTML, Js and CSS). This file then needs to be processed with a compiler (babel for example) in order to make it readable for the browser. See Vue Single File Components for more information.
Clean Solution
The vue-cli gives you a working starter template with babel and webpack all preconfigured. Just create a vue project and change the template as needed.
Install Vue-CLI
vue create my-project
npm run dev
Quick Solution
If you do not want to use a compiler, just implement it like following:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
methods: {
hello: function() {
alert('hello')
}
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ message }}</p>
<button #click="hello()">Click me</button>
</div>

Related

Vue.js - Prism code is not shown from a computed property

For the purpose of learning Vue, I am trying to create a very simple app that will return highlighted code from the input in real-time. I went through a few Prism tutorials and examples, but can't get this to work. Any help or guidance will be appreciated, as I am just getting started with Vue and I have a feeling that I am mixing something up.
This is HelloWorld.vue:
<template>
<div>
<h1>Prism Demo</h1>
<div id="editor">
<textarea v-model="message"></textarea>
<div>{{ highlighteddMessage }}</div>
</div>
</div>
</template>
<script>
import Prism from 'vue-prism-component'
export default {
data() {
return {
message: `var myFunction = function() {
statements
}`
};
},
computed: {
highlighteddMessage: function () {
return Prism.highlight(this.message, Prism.languages.js);
}
}
}
</script>
<style scoped>
...
</style>
And my main.js:
import Vue from 'vue'
import App from './App.vue'
import "prismjs";
import "prismjs/themes/prism-funky.css";
import "prismjs/components/prism-scss.min";
import "prismjs/plugins/autolinker/prism-autolinker.min";
import "prismjs/plugins/autolinker/prism-autolinker.css";
import Prism from "vue-prism-component";
Vue.component("prism", Prism);
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
I think the problem is in how I am trying to use Prism in the computed property, but I am unable to fix it. WIll appreciate any hints on correctly using Prism in Vue.
You should add Prism to your components option components:{Prism} and then in the template wrap the code with that component and no need to create a computed property :
<div>
<h1>Prism Demo</h1>
<div id="editor">
<textarea v-model="message"></textarea>
<prism language="javascript">{{ message }}</prism>
</div>
</div>
</template>
<script>
import Prism from 'vue-prism-component'
export default {
data() {
return {
message: `var myFunction = function() {
statements
}`
};
},
components:{
Prism
}
}
</script>

Random loading errors with vue-material components

I started playing with Vue.js and VueMaterial this week. It's really fun and totally new for me as I didn't do Javascript for years (Native Android being my cup of tea).
I am currently stuck with a very strange issue that I would say related to my lack of knowledge with the framework lifecycle.
Issue
The first time I am loading/refreshing manually the project in Chrome, it fails loading the VueMaterial components for some reason, and I get the message below:
Unknown custom element: md-toolbar - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I get this message with every single VueMaterial components I use in the project (md-whiteframe, md-input-container, and so on).
And the result appears as below:
Now, if I specifically change the URL in chrome by giving the path of another component (e.g. Home), then some components are correctly displayed (except the toolbar for some reason).
I go back (with Chrome), and land on the first component, except that now, everything is displayed correctly, still except the toolbar (see below).
On certain occasion (really rare and completely randomly, the Toolbar is displayed correctly.
Context
I installed vue-cli via npm and built the scaffold with the webpack template, then installed VueMaterial with npm as well.
Code
Below, some bits of the code.
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import VueMaterial from 'vue-material'
import 'vue-material/dist/vue-material.css'
Vue.config.productionTip = false
let colorPrimary = {
color: 'red',
hue: 700,
hexa: '#D32F2F'
}
let colorAccent = {
color: 'yellow',
hue: 600,
hexa: '#FDD835'
}
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
Vue.use(VueMaterial)
Vue.material.registerTheme('default', {
primary: colorPrimary,
accent: colorAccent,
warn: colorPrimary,
background: 'white'
})
Vue.material.setCurrentTheme('default')
App.vue
<template>
<div id="app">
<toolbar></toolbar>
<router-view></router-view>
</div>
</template>
<script>
import Toolbar from './components/Toolbar';
export default {
components: {
Toolbar
},
name: 'app'
}
</script>
<style src="./styles/general.css"></style>
Toolbar.vue (custom component)
<template>
<div id="toolbar">
<md-toolbar class="md-primary">
<h2 class="md-title" style="flex: 1">Firebucket</h2>
</md-toolbar>
</div>
</template>
<script>
export default {
name: 'toolbar'
}
</script>
<style scoped src="../styles/toolbar.css"></style>
Login.vue
<template>
<div id="login" class="bg-primary">
<md-whiteframe md-elevation="2" id="login-form">
<span class="md-title text-primary">{{wording.login}}</span>
<md-input-container>
<label>{{wording.username}}</label>
<md-input></md-input>
</md-input-container>
<md-input-container>
<label>{{wording.password}}</label>
<md-input></md-input>
</md-input-container>
<router-link id="login-button" tag="md-button" to="XX" class="md-raised md-primary">{{wording.login}}</router-link>
<br />
<md-button class="md-primary">{{wording.createAccount}}</md-button>
</md-whiteframe>
</div>
</template>
<script>
export default {
name: 'login',
data () {
return {
wording: {
login: 'Login',
createAccount: 'Create an account',
username: 'Username',
password: 'Password'
}
}
}
}
</script>
<style scoped src="../styles/login.css"></style>
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from './pages/Login'
import Home from './pages/Home'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/home',
name: 'home',
component: Home
},
{
alias: '/',
path: '/login',
name: 'login',
component: Login
}
]
})
--
Again, web development is not my thing, I've heard a lot of good thing about Vue.js so I wanted to give it a try. But sorry if I am missing something really obvious.
I really can't wrap my head around the fact that it's not working the first time but working fine when I go back...
PS: the router-link (in Login.vue) doesn't work neither, nothing happens when I tap the button, but I guess that's a different issue.
Any idea anyone? General feedback on the code posted above is more than welcome so I can improve it.
The code is available on GitHub, if that can help.
Thanks a lot!
You are adding the VueMaterial plugin after you create your Vue. Instead, add it before.
Vue.use(VueMaterial)
Vue.material.registerTheme('default', {
primary: colorPrimary,
accent: colorAccent,
warn: colorPrimary,
background: 'white'
})
Vue.material.setCurrentTheme('default')
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})

How to import and use bootstrap-vue with Webpack

I started a project using vuejs-templates and webpack.
Then I added bootstrap-vue to the project.
Now, I am not sure how to add a bootstrap button.
In main.js I am importing BootstrapVue:
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import App from './App'
Vue.use(BootstrapVue)
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
However, I when I try and use the <b-button> element in App.vue:
<template>
<div id="app">
<img src="./assets/logo.png">
<b-button :size="size" :variant="variant" #click="clicked">
Click Me!
</b-button>
<hello></hello>
</div>
</template>
Errors are thrown about all the property attributes associated with the <b-button> element.
How do I use this?
You should define at your app Vue instance following:
data:{
size: 0, //needed size
variant: 'success' // needed variant
},
methods:{
clicked(){
console.log('im clicked')
}
}

Unknown custom element: <router-link> in VueJS

I have attempted to extract my navigation logic in to a sub component, the structure is as follows:
App.vue -- Header.vue --- Navigation.vue
I am attempting to use the attribute in Navigation.vue but am recieving the following error:
Unknown custom element: <router-link> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Here is my app so far, pretty simple an basic.
main.js
require('bootstrap-sass/assets/stylesheets/_bootstrap.scss')
// require('bootstrap-sass/assets/javascripts/bootstrap.js')
require('./assets/sass/app.scss')
import Vue from 'vue'
import VueRouter from 'vue-router'
import VueMoment from 'vue-moment'
import VueResource from 'vue-resource'
import { configRouter } from './routes'
import App from './App'
// Debug mode
Vue.config.debug = true
// Devtools enabled
Vue.config.devtools = true
// Silence logs and warnings
Vue.config.silent = false
// install router
Vue.use(VueRouter)
// install vue-moment filter
Vue.use(VueMoment)
// install resource
Vue.use(VueResource)
// create router
var router = new VueRouter({
history: true,
saveScrollPosition: true
})
// configure router
configRouter(router)
/* eslint-disable no-new */
// new Vue({
// el: 'body',
// components: { App, router }
// })
router.start(App, '#app')
App.vue
<template>
<div>
<site-header></site-header>
<router-view></router-view>
</div>
</template>
<script>
import SiteHeader from './components/Header'
export default {
components: {
SiteHeader
}
}
</script>
Header.vue
<template>
<header class="masthead container-fluid">
<div class="row">
<!-- Branding -->
<div class="col-md-3"> </div>
<!-- / Branding -->
<!-- Primary Navigation -->
<navigation></navigation>
<!-- / Primary Navigation -->
<!-- Actions -->
<div class="col-md-3"> </div>
<!-- / Actions -->
</div>
</header>
</template>
<script>
import Navigation from './Navigation'
export default {
components: {
Navigation
},
data () {
return {
msg: 'Hello World!'
}
}
}
</script>
Navigation.vue
<template>
<div class="col-md-6">
<ul class="primary-navigation list-inline list-unstyled">
<li> <router-link to="/about">About</router-link> </li>
<li> TEST </li>
<li> TEST </li>
<li> TEST </li>
</ul>
</div>
</template>
<script>
import VueRouter from 'vue-router'
export default { components: { VueRouter } }
</script>
What am I doing wrong?
Versions: vue 1.0.28 & vue-router 0.7.13
From vue-router docs: http://router.vuejs.org/en/essentials/getting-started.html
// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = new VueRouter({
routes // short for routes: routes
})
I believe the routes need to be passed when you are creating the router instance. I don't really know what your configRouter(router) does, but you can keep things simple till it starts working. After that, you can start modularizing your components and configs.
Also, I am not sure about router.start, it is not specified anywhere in the docs that I can find. The router docs recommend this simple method to create the root instance of your app:
// 4. Create and mount the root instance.
// Make sure to inject the router with the router option to make the
// whole app router-aware.
const app = new Vue({
router
}).$mount('#app')
Probably your app is not router-aware yet, as mentioned in the comments above (from docs, not from me!). This could be a reason for getting that router-link error. Can you try the simpler methods as recommended by the docs?
By the way, which versions of Vue and Vue-Router are you using? If it is not the current versions (vue 2.0.3 and vue-router 2.0.1), then please ignore my answer above.

Creating a child component within a parent component in Vue.JS

I am trying to figure out how to make one component inside of another one in VueJS. For instance, something like this, which unfortunately does not work (the child component appears to do nothing):
http://www.webpackbin.com/NyI0PzaL-
I am equally interested in doing this using inline-templates as much as by using the .vue file extension method as shown above.
Here is the code from the non-working example above:
main.js
import Vue from 'vue'
import App from './App.vue'
import Child from './Child.vue'
new Vue({
el: 'body',
components: { App, Child }
})
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<app></app>
<script src="main.js"></script>
</body>
</html>
App.vue
<template>
<div>
<h1>{{ parent_msg }}</h1>
<child></child>
</div>
</template>
<script>
export default {
data () {
return {
parent_msg: 'Hello From the Parent!'
}
}
}
</script>
Child.vue
<template>
<h1>{{ child_msg }}</h1>
</template>
<script>
export default {
data () {
return {
child_msg: 'Hello From the Child!'
}
}
}
</script>
Even though this above example is hosted on webpackbin.com, in the two projects where I would like to use this, I am using Laravel in one along with Laravel Spark in the other. In the plain Laravel app, I'm primarily using .vue files, and in the Laravel Spark app, I'm primarily using inline-templates. I'd be especially grateful for any working samples. Thanks!
UPDATE
Thanks to Linus for his answer below. It appears I need these changes to register the child component globally in my main.js file:
import Vue from 'vue'
import App from './App.vue'
import Child from './Child.vue'
Vue.component('child', Child);
new Vue({
el: 'body',
components: { App, Child }
})
Alternatively, in order to keep the child component local to be used within the parent, I could change the parent component (App.vue) as follows:
<template>
<h1>{{ parent_msg }}</h1>
<div>
<child></child>
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {Child},
data () {
return {
parent_msg: 'Hello from the parent component!'
}
}
}
</script>
You registered the Child component locally in the main instance, so it is not available in App.vue
Remove it form the main instance and add it to App.vue:
App.vue
<template>
<div>
<h1>{{ parent_msg }}</h1>
<child></child>
</div>
</template>
<script>
import Child from './child.vue'
export default {
data () {
return {
parent_msg: 'Hello From the Parent!'
}
},
components: {child: Child}
}
</script>
..or register it globally with Vue.component('child', Child) in your main.js file. Then it's available everywhere.

Categories

Resources