Vuejs call other component's method with parameter - javascript

I have two components, the first one is for uploading a file and the second one to Show a file. Inside my Upload Component I would like to call the Preview Component and add a Parameter so that a method inside the Preview Component uses a value which is created inside the Upload Component.
So far I have done this:
UploadComponent.vue
<template>
…
<button #click="upload"></button>
<preview-component :url="this.location"></preview-component>
</template >
<script>
import PreviewComponent from '#/js/components/PreviewComponent';
export default {
components: {
'preview-component': PreviewComponent
},
props: ['url'],
data () {
return {
// ...
location: ''
}
},
methods: {
upload() {
// ... upload stuff then update the global var location
this.location = response.data.location;
},
}
}
</script>
This is my Preview Component:
<template>
<div id="body">
///...
</div>
</template>
<script>
export default {
props: ['url'],
methods: {
loadPdf (url) {
//
},
}
}
</script>
So far I am getting the error that url is not defined, so it actually does not sent the url from the UploadCOmponent to the PreviewComponent, how do I manage to sent it?

You got a ninja this in your UploadComponent's template.
It should be <preview-component :url="location"></preview-component>

Related

How to add multiple components dynamically at run time not globally but locally

Hi i have a situation where i need to register multiple components at run time within a file.
Display.vue
<template>
<div>
<component v-if="currentComponent" :is="currentComponent">
</component>
</div>
</template>
<script>
import Vue from 'vue';
export default {
data(){
return{
currentComponent:null,
}
},
methods:{
load(e){
for(let key in e.components){
Vue.component(key,e.components[key]);
}
this.$nextTick(() =>{
this.currentComponent = e.components.container;
});
},
},
created(){
document.body.addEventListener('component-ready',this.load, false);
},
}
</script>
in my above file how i want my components to be loaded something like shown below:
components:{
container: component Object{},
header: component Object{},
body: component Object {},
footer: component Object {},
}
here is how i'm dispatching event to above file Display.vue
const event = new Event('component-ready');
event.components = {
container: component Object{},
header: component Object{},
body: component Object {},
footer: component Object {},
};
document.body.dispatchEvent(event);
Execution sequence:
event dispatch component-ready
eventlisterner in created of file Display.vue will call load method
Problem: in my current approach components are registered globally, that i want to avoid. i want to register all components to Display.vue file only
To locally register the components on the fly, you can copy the component definitions into this.$options.components:
export default {
methods: {
load(e) {
this.$options.components = e.components 👈
this.$nextTick(() => {
this.currentComponent = e.components.container
})
},
},
}
demo

TypeError: Cannot read property '_wrapper' of undefined

I am trying to update the props data sent to a component on a button click to a single component in vue.
Button click triggers an action loads the data from a config. But this throws the error and the error message was not clear. Find the error here https://imgur.com/a/0psUWKr
If I pass the data directly without the button actions, it works fine.
My Main component
<template>
<div>
<MyList v-if="listItems" :elements="listItems"/>
<button #click="showSlider">Show Slider</button>
</div>
</template>
<script>
// imports the components and config files
export default {
name: "ListView",
data() {
return {
listItems: []
};
},
components: {
MyList
},
methods: {
showSlider: function() {
this.listItems.push(configs['elements'])
},
</script>
NOTE: If i provide the data to listItems by default it works
And MyList file
<template>
<ul>
<li v-for="each in elements" :key="each.id">
{{each.name}}
</li>
</ul>
<template>
<script>
// imports the components and config files
export default {
name: "MyList",
props: {
elements: {
type: Array
}
}
</script>
It should work, in general. But in my case, the issue is with push in the following function.
showSlider: function() {
this.listItems.push(configs['elements'])
},
Storing the same from Vuex and using dispatcher to update the same works like a charm. And I use computed property to load the state from the vueX and pass it to MyList

Nuxt.js – Nuxt generate does not pass onclick parameter to component on 404 page

I have a strange issue with my 404/index.vue which after $ nuxt generate generates my 404.html file.
I am using a Btn component in my vue file which works on index.vue file but not on my 404/index.vue.
It seems that it does not pass the onclick parameter to the component.
I think the following makes it more understandable:
404/index.vue
<script>
import { mapGetters } from 'vuex'
import Heading from '~/components/Heading/Heading.vue'
import Btn from '~/components/Btn/Btn.vue'
export default {
components: {
Heading,
Btn
},
computed: {
...mapGetters(['defaultLang', 'currentLang']),
...mapGetters('data', ['getPageBySlug']),
page () {
return this.getPageBySlug('404')
}
},
data: () => ({
externalRoute: false
}),
beforeRouteEnter (to, from, next) {
// check before route entering if we came from external or already from our app
next(vm => {
if (from.path === '/') {
vm.externalRoute = true
} else {
vm.externalRoute = false
}
})
},
methods: {
getBackPath () {
return `/${this.currentLang !== this.defaultLang ? this.currentLang : ''}`
},
goBack () {
// if we came externally we go to our root, else we go one route back in history
if (this.externalRoute) {
this.$router.push('/')
} else {
this.$router.go(-1)
}
}
}
}
</script>
<template>
<div class="Page">
<Heading :level="1">{{ page.title }}</Heading>
<Btn :click="goBack">{{ $t('error.link') }}</Btn>
</div>
</template>
As you can see the goBack function should be passed to the Btn component.
After generation of the static pages the button is there (with the correct language error.link) but it would not do anything on click.
My button component looks like this: (I simplified it a bit to reduce to the important stuff here:
<script>
export default {
name: 'Btn',
props: {
click: {
type: Function,
default: () => {},
required: false
}
}
}
</script>
<style src='./Btn.scss' lang='scss'></style>
<template>
<component
class="Btn"
v-on:click="click"
<slot />
</component>
</template>
I am using the same button component in my index.vue, which is rendered on the starting page. The Btn works nicely there (also after $ yarn generate and I cannot figure out what the difference would be. Somehow the Btn does not receive the onclick function on the 404 template.
If I add /404 to the router and I run the app locally, the Btn works.
It's really just isolated in the case when I generate the static pages that the Btn does not work on the 404 vue template anymore.
Any idea what the reason could be for this?

Change variable in component using vue.js

I have navbar blade, component with text and another components with page.
It works like I have component with text in navbar, and another component after navbar. That's three another components. How to change text from for example index.vue in text.vue?
That's what I have:
Text.vue:
<template>
<p class="title">{{msg}}</p>
</template>
<script>
export default {
props: [
'msg',
],
data() {
return {
}
},
mounted() {
},
methods: {
}
}
</script>
Component in navbar.blade.php:
<navbar-title></navbar-title>
And I try to change it in index.vue, that should work when we are on this page:
data() {
return {
msg: 'text',
}
But it doesn't work. How to do it correctly?
EDIT:
Vue.component('title', require('./components/Title.vue'));
To pass the message variable from your index.vue through navbar.vue to title.vue each needs to pass the property to the child and each child must pass the property on again all throughout the tree.
Something like this should work for your case: <title :msg="msg"></title>

How do I make an axios request in a Vue component from a route made using an Adonis controller

I have a WidgetController.js file that performs CRUD operations on the database. This controller has a * create (request, response) method/generator that basically returns a response containing the widget attributes and also adds a row to the database widgets table. The route is defined as Route.any('widgets/create', 'WidgetController.create').as('widgets.create').middleware('auth');. I want create to be triggered by a click of a button on the frontend, and I tried the normal import in Vue:
<template>
<div>
<button #click="createWidget">Click me</button>
</div>
</template>
<style></style>
<script type="text/javascript">
import WidgetController from '/path/to/WidgetController.js';
export default{
name: 'widget',
data () {
return{
WidgetCtrl: WidgetController
}
},
methods: {
createWidget () {
return this.WidgetCtrl.create();
}
}
}
</script>
but it doesn't work probably because of dependencies and functions that are exclusive to Adonis and not defined in Vue. I learned that axios may be able to do what I want. How so?
You can't import or access server side's js file from the client side.
As you're trying to import adonis's WidgetController.js from vue.js
You've to make HTTP request in 'createWidget' function and point it to WidgetController.create method.
Vue's component file:
<template>
<div>
<button #click="createWidget">Click me</button>
</div>
</template>
<script type="text/javascript">
export default{
name: 'widget',
data () {
return{
WidgetCtrl: WidgetController
}
},
methods: {
createWidget () {
axios.get('/url-point-to-WidgetController.create')
.then(response => {
// do other stuff
});
}
}
}
</script>
Adonis's WidgetController.js:
'use strict'
class WidgetController {
* create(request, response) {
// save widget...
}
}
module.exports = WidgetController

Categories