VueJs component using CDN link without npm - vuejs2

Want to use Laravel Vue Pagination
HTML
<ul>
<li v-for="user in users.data" :key="user.id">{{ user.name }}</li>
</ul>
<pagination :data="users" #pagination-change-page="getUsers"></pagination>
Vue/Js
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/laravel-vue-pagination#2.3.1/dist/laravel-vue-pagination.umd.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
users: [],
},
mounted() {
this.getUsers();
},
methods: {
getThoughts(page = 1) {
axios.get('/api/users?page=' + page)
.then(response => {
this.users = response.data;
});
}
}
});
</script>
Problem:
Loop is working fine when using the pagination component gives me the following error.
Error
[Vue warn]: Unknown custom element: <pagination> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Tried
Vue.component('pagination', require('laravel-vue-pagination'));
Gives me following error
Uncaught ReferenceError: require is not defined

You are loading a component using UMD modules. When loading a UMD module through script tag, the module gets added to the window object. You can access it using window['module-name']. Then you need to register the component in Vue object just like u would do it normally.
In your case you need to add:
components: {
pagination: window['laravel-vue-pagination']
},
to your Vue component so umd module laravel-vue-pagination will be registered and ready to use inside template.

Related

How to display stub component when component is not found in vue

I am trying to catch situation, when component is not found, ie:
{
template: '<some-unknown-component></some-unknown-component>'
}
At that moment, Vue warns us with unknown custom element: <some-unknown-component>...
I would like to step in when some-unknown-component is not found and then use another component instead, like stub-component:
{
name: 'stub-component',
props: ['componentName'],
template: '<p>component ${componentName} does not exists, click here to create...</p>'
}
UPDATE: I am looking for solution without changing the template itself, so no v-if and component added.
Vue exposes a global error and warning handler. I managed to get a working solution by using the global warnHandler. I don't know if it is exactly what you are looking for, but it may be a good starting point. See the working snippet (I think it is quite self explanatory).
Vue.config.warnHandler = function (err, vm, info) {
if (err.includes("Unknown custom element:")) {
let componentName = err.match(/<.*>/g)[0].slice(1, -1)
vm.$options.components[componentName] = Vue.component('stub-component', {
props: ['componentName'],
template: `<p>component "${componentName}" does not exists, click here to create...</p>`,
});
vm.$forceUpdate()
} else {
console.warn(err)
}
};
new Vue({
el: '#app',
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<unknown-component></unknown-component>
</div>
Vue stores the details of all the registered components in the $options.component property of the Vue instance.
So, you can check for the component availability using this.$options.component and if the component is present then load the component otherwise load the other component.
In the below example, suppose you have two different components and you want to load them on the availability, then you can create a computed property on the basis of it, load the component as needed.
var CustomComponent = Vue.extend({ template: '<h2>A custom Component</h2>' });
var AnotherComponent = Vue.extend({ template: '<h2>Custom component does not exist.</h2>' });
new Vue({
el: "#app",
components: {
CustomComponent,
AnotherComponent
},
computed: {
componentAvailable () {
return this.$options.components.CustomComponent
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-if="componentAvailable">
<custom-component />
</div>
<div v-else>
<another-component />
</div>
</div>

How to conditionally mount root vue instance?

Is there a way, using vue, to check if the element where vue instance should be mounted actually exists? I have cases where this element would not exist and would like to avoid getting errors like these:
[Vue warn]: Cannot find element: #app
[Vue warn]: Error in created hook: "TypeError: Cannot convert undefined or null to object"
TypeError: this.$store.getters[(this.namespace...
The case is: I want to be able to check if the element actually exist before mounting vue. Don't try to mount if there is no element.
Just use vanilla JS to check for existing tag.
const storeMounted = new Vuex.Store({
state: {
string: "Store mounted"
}
})
if (document.getElementById('app')) {
new Vue({
el: "#app",
store: storeMounted,
computed: {
string() {
return this.$store.state.string
}
},
mounted() {
console.log('Mounted to #app')
}
})
}
const storeNotMounted = new Vuex.Store({
state: {
string: "Store not mounted"
}
})
if (document.getElementById('noApp')) {
new Vue({
el: "noApp",
store: storeNotMounted,
mounted() {
console.log('Mounted to #noApp')
}
})
}
<script src="https://cdn.jsdelivr.net/npm/es6-promise#4/dist/es6-promise.auto.js"></script>
<script src="https://unpkg.com/vuex#3.1.2/dist/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">{{string}}</div>
In the snippet above you can see that no errors are in the console, a Vue instance is mounted in a <div> that has an appropriate ID, and the other one is not mounted.
Vue is very useful - but it's "only" JavaScript :D
EDIT
I added Vuex, so you can see that it doesn't cause any problems.

Vue - Add CDN component without webpack

I want to add this component to my Vue.js project without using webpack.
I've tried adding this to the head:
<script src="https://cdn.jsdelivr.net/npm/vuejs-auto-complete#0.9.0/dist/build.js"></script>
And this to the body:
<autocomplete :source="[{id:1,name:'abc'},{id:2,name:'def'}]"></autocomplete>
But the following error happens:
[Vue warn]: Unknown custom element: autocomplete - did you register the component correctly? For recursive components, make sure to provide the "name" option.
What should I do?
Here's the link to the component on Github.
You need to register that component first like below
components: {
Autocomplete: window["vuejs-autocomplete"]
}
Example
new Vue({
el: '#app',
components: {
Autocomplete: window["vuejs-autocomplete"]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuejs-auto-complete#0.9.0/dist/build.js"></script>
<div id="app">
<autocomplete :source="[{id:1,name:'abc'},{id:2,name:'def'}]"></autocomplete>
</div>
Have you registered it in Vue.components(); in your main.js ?

mixin method is undefined in created hook of component

<template>
<section>
Top
</section>
</template>
<script>
import api from '../../server/api.ts';
export default {
name: 'Questions',
mixins: [api],
data() {
return {
templates : getTemplates(),
};
},
created() {
// **[Vue warn]: Error in created hook: "ReferenceError: getTemplates is not defined"**
this.templates = getTemplates();
},
};
</script>
getTemplates function is working fine if i click on link but getting error in all life hooks of Vue js component.
Thanks for help in advance !
You forgot this for the function. Loading mixins has the same effect as if the content in it would be in your actual component. You need to call the methods the same way as you would call a local function. Always with this.
So change it to:
created() {
this.templates = this.getTemplates();
},

vue-resource $http not Work

I'm trying to use vue with vue-resource without success. what am I doing wrong? Follow the code
I'm using CDN
I'm starting with the vuejs and I appreciate the help.
<div id="beerApp">
<ul>
<li v-for="cervejaria in cervejarias">{{cervejaria.name}}</li>
</ul>
</div>
<script src="https://unpkg.com/vue#2.1.1/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.0.3/vue-resource.min.js"></script>
<script>
// vue js codes will be here
new Vue({
el:'#beerApp',
data:{
cervejarias: []
},
ready:function ()
{
this.$http.get('https://gist.githubusercontent.com/vedovelli/3a83755e576778088c93/raw/204ced0602760829597f5caa2680e5f7cb29bade/cervejarias.json').then((response) => {
this.$set('cervejarias',response.json())
}, (error) => {
consoel.log(error)
});
}
});
It's because there are no longer ready() lifecycle hook into Vue 2.
Instead you can go with mounted() or created() lifecycle hooks.