Vue js applications code throws error (Js Expected) - visual-studio

I am trying to build vue js applications but I am getting following errors .
Severity Code Description Project File Line Suppression State
Warning TS1005 (JS) ':' expected. VuejsApp JavaScript Content Files C:\Users\Khundokar Nirjor\Documents\Visual Studio 2017\Projects\VuejsApp\VuejsApp\src\App.vue 19 Active
This is Home.vue code
<template>
<div id="databinding">
<div id="counter-event-example">
<p style="font-size:25px;">Language displayed : <b>{{ languageclicked }}</b></p>
<button-counter v-for="(item, index) in languages"
v-bind:item="item"
v-bind:index="index"
v-on:showlanguage="languagedisp"></button-counter>
</div>
</div>
</template>
<script>
// import Home from './components/Home.vue';
// import component1 from './components/component1.vue';
export default {
name: 'app',
Vue.components('button-counter', {
template: '<button v-on:click = "displayLanguage(item)"><span style = "font-size:25px;">{{ item }}</span></button>',
data: function () {
return {
counter: 0
}
},
props: ['item'],
methods: {
displayLanguage: function (lng) {
console.log(lng);
this.$emit('showlanguage', lng);
}
},
});
new Vue({
el: '#databinding',
data: {
languageclicked: "",
languages: ["Java", "PHP", "C++", "C", "Javascript", "C#", "Python", "HTML"]
},
methods: {
languagedisp: function (a) {
this.languageclicked = a;
}
}
})
};
</script>
<style>
</style>
I want to display list of buttons and when i clicked the any of them button , I want to display the message that button is clicked.

I believe your error is related to the component. First, the function name is wrong. The correct name is Vue.component and it is Vue.components. Second, your component declaration is not correct.
I created this codepen where you can see how to declare the component globally and locally.
const buttonCounter = {
template:
`<button #click="displayLanguage(item)">
<span style="font-size:25px;">{{ item }}</span>
</button>`,
props: ["item"],
methods: {
displayLanguage: function(lng) {
this.$emit("show-language", lng);
}
}
}
// Declare your component globally, will be able to access it in any another component in the application
Vue.component("button-counter", buttonCounter );
new Vue({
el: "#databinding",
// declarete your component locally, it only will be available inside this context
components:{
'button-counter-2' : buttonCounter
},
data: function() {
return {
languageclicked: "",
languages: ["Java", "PHP", "C++", "C", "Javascript", "C#", "Python", "HTML"]
};
},
methods: {
languageDisp: function(a) {
this.languageclicked = a;
}
}
});
body {
margin: 20px;
}
.btn-wrapper {
display: flex;
margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="databinding">
<div id="counter-event-example">
<p style="font-size:25px;">Language displayed : <b>{{ languageclicked }}</b></p>
<div class="btn-wrapper">
<button-counter v-for="(item, index) in languages" :item="item" :key="item" #show-language="languageDisp"/>
</div>
<button-counter-2 v-for="(item, index) in languages" :item="item" :key="item" #show-language="languageDisp"/>
</div>
</div>

Related

Search functionality with rest api prevent DDOSing the server

The Problem
I have a search component and component which implements the search component. When I type something in the search bar after 1/2 second of not typing (debounce) the server should be hit and the results should be returned.
The solution i am trying to implement comes from this post on Stackoverflow
The code
This leads me to the following code.
I have search.vue
<template>
<label for="search">
<input
id="search"
class="w-full py-2 px-1 border-gray-900 border"
type="text"
name=":searchTitle"
v-model="searchFilter"
:placeholder="searchPlaceholder"
autocomplete="off"
v-on:keydown="filteredDataset"
/>
</label>
</template>
<script>
import {debounce} from 'lodash';
export default {
props: {
searchPlaceholder: {
type: String,
required: false,
default: ''
},
searchName: {
type: String,
required: false,
default: 'search'
}
},
data() {
return {
searchFilter: '',
}
},
methods: {
filteredDataset() {
console.log('event fired');
this.$emit('searchValue', this.searchFilter);
}
},
}
</script>
And product.vue
<template>
<div>
<div class="my-4">
<search
search-placeholder=""
search-name=""
v-on:searchValue="filterValue = $event"
v-model="productsFiltered"
>
</search>
<div class="flex w-full py-1 border px-2 my-2" v-for="product in productsFiltered"> (...)
</div>
</div>
</div>
</div>
</template>
<script>
import {debounce} from 'lodash';
export default {
data() {
return {
products: [],
filterValue: '',
filteredProducts: ''
}
},
computed: {
productsFiltered: {
get(){
console.log('getter called');
return this.filteredProducts;
},
set: _.debounce(function(){
console.log('setter called');
if (this.filterValue.length < 1) {
this.filteredProducts = [];
}
axios.get(`${apiUrl}search/` + this.filterValue)
.then(response => {
this.products = response.data.products;
const filtered = [];
const regOption = new RegExp(this.filterValue, 'ig');
for (const product of this.products) {
if (this.filterValue.length < 1 || product.productname.match(regOption)) {
filtered.push(product);
}
}
this.filteredProducts = filtered;
});
}, 500)
}
},
}
</script>
The result
The result is that the setter in the computed property in product.vue does not get called and no data is fetched from the server. Any ideas on how to solve this?
Your first code block imports debounce but does not use it. It also declares a prop, searchName, that isn't used. These aren't central issues, but clutter makes it harder to figure out what's going on.
Your second code block uses v-model but does not follow the required conventions for getting v-model to work with components:
the component must take a prop named value
the component must emit input events to signal changes to value
You have the component emit searchValue events, and handle them with a v-on that sets a data item. You seem to expect the v-model to call the setter, but as I noted, you haven't hooked it up to do so.
From what's here, you don't even really need to store the input value. You just want to emit it when it changes. Here's a demo:
const searchComponent = {
template: '#search-template',
props: {
searchPlaceholder: {
type: String,
required: false,
default: ''
}
},
methods: {
filteredDataset(searchFilter) {
console.log('event fired');
this.$emit('input', searchFilter);
}
}
};
new Vue({
el: '#app',
data() {
return {
products: [],
filterValue: '',
filteredProducts: ''
}
},
components: {
searchComponent
},
computed: {
productsFiltered: {
get() {
console.log('getter called');
return this.filteredProducts;
},
set: _.debounce(function() {
console.log('setter called');
if (this.filterValue.length < 1) {
this.filteredProducts = [];
}
setTimeout(() => {
console.log("This is the axios call");
this.filteredProducts = ['one','two','three'];
}, 200);
}, 500)
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<template id="search-template">
<label for="search">
<input
id="search"
class="w-full py-2 px-1 border-gray-900 border"
type="text"
name=":searchTitle"
:placeholder="searchPlaceholder"
autocomplete="off"
#input="filteredDataset"
/>
</label>
</template>
<div id="app">
<div class="my-4">
<search-component search-placeholder="enter something" v-model="productsFiltered">
</search-component>
<div class="flex w-full py-1 border px-2 my-2" v-for="product in productsFiltered"> (...)
</div>
</div>
</div>

Vue.Js | Components isn't working. | Unknown custom element: <image-upload>

I have this error :
[Vue warn]: Unknown custom element: <image-upload> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
In myApp.js i added :
Vue.component('image-upload',require('./components/ImageUpload.vue').default);
In ImageUpload.Vue i have this code:
<script>
import Croppie from 'croppie'
export default {
props: ['imgUrl'],
mounted() {
this.image = this.imgUrl
this.setupCroppie()
},
data() {
return {
croppie: null,
image: null
}
},
methods: {
setUpCroppie() {
let el = document.getElementById('croppie')
this.croppie = new Croppie(el, {
viewport: {width: 200, height: 200, type: 'circle'},
boundary: {width: 220, height: 220},
showZoomer: true,
enableOrientation: true
})
this.croppie.bind({
url: this.image
})
},
}
}
</script>
<template>
<div class="image-upload-wrapper image-upload">
<p>this is my component</p>
<div id="croppie"></div>
</div>
</template>
In blade:
<image-upload img-url="{{url('img/user.png')}}"></image-upload>
I'm following the doc here to use CroppieJs
https://foliotek.github.io/Croppie/
Thanks..
Have you tried to add a : to your vue component.
<image-upload :img-url="{{url('img/user.png')}}"></image-upload>
Does the Vue component appear in the Vue.js inspecter?
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd

Property or method not defined on instance

I'm trying to create a watcher to bind the value from an input run it through a method and display that value on the page. Its a fairly straightforward sample of code I'm working with but I believe I have a scoping issue but I don't see anything wrong.
I tried changing a few things such as the convertTitle function scoping. e.g. But I got the same error
convertTitle() {
return Slug(this.title)
}
My Vue Component -
<template>
<div class="slug-widget">
<span class="root-url">{{url}}</span>
<span class="slug" v-if="slug !== nil">{{slug}}</span>
</div>
</template>
<script>
export default {
props: {
url: {
type: String,
required: true
},
title: {
type: String,
required: true
}
},
data: function() {
return {
slug: this.convertTitle()
}
},
methods: {
convertTitle: function() {
return Slug(this.title)
}
},
watch: {
title: function(val) {
this.slug = this.convertTitle();
}
}
}
</script>
My Blade Partial with input -
#extends('admin.admin')
#section('content')
<div class="row">
<div class="col-md-9">
<div class="row">
<h1>Create new page</h1>
</div>
<div class="row">
<div class="pcard">
<form action="" method="POST" class="">
{{ csrf_field() }}
<label>Title</label>
<input type="text" name="page-title" placeholder="" v-model="title">
<slug-widget url="{{url('/')}}" :title="title"></slug-widget>
</form>
</div>
</div>
</div>
</div>
#endsection
#section('scripts')
<script>
var app = new Vue({
el: '#app',
data: {
title: ''
}
});
</script>
#endsection
Full error Trace -
[Vue warn]: Property or method "title" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
(found in <Root>)
Updated with compute -
export default {
props: {
url: {
type: String,
required: true
},
title: {
type: String,
required: true
}
},
computed: {
slug() {
return Slug(this.title)
}
}
}
The error was resolved by removing the following snippet from app.js
const app = new Vue({
el: '#app'
});
You shouldn't have, and shouldn't ever need, a function call to supply the value of something in your data.
It sounds like you just need to put convertTitle() into a computed and away you go?

Vue Object is Empty

I'm using Vuejs to display data from an API to a template. I'm trying to figure out why I am not returning data for the team so I can display in for the template. Right now when I use the VueJS Chrome Extention it shows that the team is an empty object.
<div v-if="team">
<div class="row">
<div class="col-12 col-sm-12">
<div class="fw-700 pb3 mb5" style="border-bottom: 1px solid #333;">Name:</div>
<div class="mb10" style="font-size: 20px;">{{ team.name }}</div>
</div>
</div>
<script>
module.exports = {
http: {
headers: {
'X-CSRF-TOKEN': window.Laravel.csrfToken
}
},
props: [ 'id', 'editable' ],
data: function(){
return {
modalName: 'additionalInfo',
team:{
}
}
};
},
methods: {
fetchInfo: function(){
this.$http.get('/api/teams/info', { params: { id: this.id } }).then((response) => {
this.team = response.data;
});
},
},
}
}
</script>
It is empty because your method fetchInfo isn't being called, so you need to do something like this:
created () {
this.fetchInfo()
}
This will call the function fetchInfo which in turn will fetch and fill this.team

Vue & Laravel: Access and use eventHub

In resources/assets/js/app.js I have created eventHub Vue instance:
require('./bootstrap');
var eventHub = new Vue();
Vue.component('todos-list', require('./components/todos/TodoList.vue'));
Vue.component('todos-add', require('./components/todos/TodoAdd.vue'));
const app = new Vue({
el: '#app'
});
How can I use it in components that are created in separate .vue files?
For example, I also have two components:
todos-list located in /components/todos/TodoList.vue, which is used to fetch the data from server-side using vue-resource:
<template id="todos-list-template">
<div>
<ul v-if="todos.length > 0">
<li v-for="todo in todos">
{{ todo.title }}
</li>
</ul>
<p v-else>You don't hanve any Todos.</p>
</div>
</template>
<script>
export default {
template: '#todos-list-template',
data() {
return {
todos: {}
}
},
mounted() {
this.$http.get('api/vue/todos').then(function(response) {
this.todos = response.data;
});
},
methods: {
handleAddedTodo: function(new_todo) {
this.todos.push(new_todo);
}
},
created: function() {
eventHub.$on('add', this.handleAddedTodo);
},
destroyed: function() {
eventHub.$off('add', this.handleAddedTodo);
}
}
</script>
todos-add located in /components/todos/TodoAdd.vue which is used to add (save) the new 'todo' using vue-resource:
<template id="todos-add-template">
<div>
<form v-on:submit.prevent="addNewTodo()">
<div class="form-group">
<input v-model="newTodo.title" class="form-control" placeholder="Add a new Todo">
</div>
<div class="form-group">
<button>Add Todo</button>
</div>
</form>
</div>
</template>
<script>
export default {
template: '#todos-add-template',
data() {
return {
newTodo: { id: null, title: this.title, completed: false }
}
},
methods: {
addNewTodo() {
this.$http.post('api/vue/todos', { title: this.newTodo.title }).then(function(response) {
if (response.status == 201) {
eventHub.$emit('add', response.data);
this.newTodo = { id: null, title: this.title, completed: false }
}
}, function(response) {
console.log(response.status + ' - '+ response.statusText);
})
}
}
}
</script>
When I add (save) new 'todo' using the todos-add component (TodoAdd.vue) - I want to update data in todos-list component. If I understood well the documentation - for component communication we need to use centralized event hub. And that's what I tried - but I am getting the following error:
eventHub is not defined
I guess because it is defined in app.js, but how can I use in components that are created in separate .vue files?
You are getting this error because eventHub is actually not defined where you are using it. You have to export this from app.js and import in TodoAdd.vue.
in app.js:
var eventHub = new Vue()
exports.eventHub = eventHub
Add this code in TodoAdd.vue:
<script>
import eventHub from '/path/of/app'
export default {
template: '#todos-list-template',
This should make eventHub availble in TodoAdd.vue.
Edited
As the comment suggests, you may consider using vuex, as you have data whcih is being used across components, and going forward I see chances of getting it more complex, more event handlers and event listerners, which can quickly become a nightmare to manage.
var eventHub = new Vue()
You are getting this error because eventHub is actually not defined where you are using it. You have to export this from app.js file. Use this one
window.eventHub = new Vue()

Resources