Unknow error in vuejs2 - properties

I am new in vuejs2. I am getting below error. Could anyone say why this error is coming ? Could you please provide any sample solution for this ?
ModalBody.vue
<script>
import SemanticModal from 'vue-ya-semantic-modal'
export default {
components: { SemanticModal: SemanticModal() },
name: 'ModalBody',
props: {
active1: {
required: true
}
},
}
</script>
DataTable.vue
<script>
import ModalBody from './ModalBody'
export default {
components: { ModalBody },
data: function () {
return {
active1: false
}
},
props: {
columns: {
required: true
},
gdata: {
required: true
}
},
methods: {
show () {
this.active1 = true
}
},
}

Use computed Property(eg.isActive) for passing to children component
import ModalBody from './ModalBody'
export default {
components: { ModalBody },
data: function () {
return {
active1: false
}
},
props: {
columns: {
required: true
},
gdata: {
required: true
}
},
computed:{
isActive (){
return this.active1;
},
methods: {
show () {
this.active1 = true
}
},
}
And Pass this computed property to child component in template
<modal-body :active1='isActive'></modal-body>
By doing this it avoid mutation

Finally I got the solution. I added child component to parent component as like below
<modal-body :active1="active1" #sendValue="active1 = $event"></modal-body>
I added methods like below in Parent Component
methods: {
close() {
this.$emit('sendValue', false);
}
}

In vue prop mutating is anti pattern look here

Related

vuejs use data from parent, but parent data usually update

there are two .vue file and one is parent and another is child.
I am developing 'Sending file' function with Modal.
I will upload file data in parent.vue.
and when I click 'Send', child.vue will be popped up!
and I will choose, target who receive this file data.
and finally, I click 'Send' button, get connection to Backend server.
This is parent.vue
<<templete>>
<script>
export default {
name: 'BillingView',
components: {
EmailSender
},
data() {
return {
uploaded_file: '',
file_data: {},
is_uploaded: false,
popupVal: false
}
},
methods: {
sendEmail() {
if (this.is_uploaded == false) {
alert('Upload your file');
} else {
<< parsing file data>>
this.file_data = JSON.parse(JSON.stringify(this.parsed_uploaded_file));
this.popupVal = (this.popupVal) ? false : true
}
},
popupClose: function ( value ) {
this.popupVal = value
}
}
}
</script>
This is child.vue
<<templete>>
<script>
import axios from 'axios';
export default {
name: 'EmailSender',
props: {
popupVal: Boolean,
file_data: {
type: Object,
default: () => {
return {}
}
}
},
data: () => ({
}),
computed: {
popUp: {
get() {
return this.popupVal
},
}
},
created() {
},
methods: {
sendEmail() {
let req_data = {};
req_data ['file'] = file_data;
axios.post(process.env.VUE_APP_BASE_API + 'email/',
{
req_data ,
headers: {
'Content-Type': 'application/json;charset=UTF-8-sig'
}
}
).then(res => {
console.log('SEND EMAIL SUCCESS!!');
console.log('SEND EMAIL RESPONSE::', res, typeof (res));
})
.catch(function () {
console.log('SEND EMAIL FAILURE!!');
});
}
}
};
</script>
but here, "req_data ['file'] = file_data;" the file_data is empty, {}.
I expect when I update file_data in parent vue, child can know and use updated file data.
how can I do?
You have to make sure you send file_data as a prop to your component. e.g. Your component is 'myPopup' and you should use it as below to send file_data as a prop:
<myPopup :myData="file_data" >
In this case, you can get file_data as 'myData' in the child component as below
After changes, your props should be:
props: {
myData: {
type: Object,
default: () => {
return {}
}
}
},
Your function should be:
Also, don't forget to use 'this' keyword. this.myData instead of myData in function.
methods: {
sendEmail() {
let req_data = {};
req_data['file'] = this.myData;
// axios here
};
},

Vue 3 Composition API - How to specify a prop in setup()

I wrote a "loading state" mixin for Vue 2:
export default {
props: {
loading: {
type: Boolean,
default: false
},
},
data () {
return {
innerLoading: false,
}
},
mounted () {
this.innerLoading = !!this.loading
},
methods: {
startLoading () {
this.$emit('update:loading', this.innerLoading = true)
},
stopLoading () {
this.$emit('update:loading', this.innerLoading = false)
},
},
computed: {
isLoading () {
return !!this.innerLoading
},
isNotLoading () {
return !this.innerLoading
},
},
watch: {
loading (loading) {
this.innerLoading = !!loading
},
}
}
I use this mixin for other components to hold the loading state. For example for forms, buttons, tables etc.
Now, Im trying to rewrite this mixin to composition API style for Vue 3. Ideally, I would like to use my loading composable like this:
// components/Table.vue
import 'useLoading' from 'src/composables/loading'
export default defineComponent({
setup () {
const { startLoading, stopLoading, innerLoading } = useLoading()
// ...
return { startLoading, stopLoading, innerLoading, ... }
}
})
My question:
// How can I define the loading prop inside the setup() function?
props: {
loading: {
type: Boolean,
default: false
},
},
Of course I can define my component like this:
import 'useLoading' from 'src/composables/loading'
export default defineComponent({
props: {
loading: {
type: Boolean,
default: false
},
},
setup () {
const { startLoading, stopLoading, innerLoading } = useLoading();
}
})
But imagine, I have 20 components using this mixin/composable. So I want to define that loading prop only ONCE (like I did in mixin).
Is there a way how to do it with composition API?
you may be able to do something like this
import {withProps, useLoading} from "src/composables/loading";
export default defineComponent({
props: {
...withProps()
},
setup () {
const { startLoading, stopLoading, innerLoading } = useLoading();
}
})
where withProps is a function that would have your definitions
export const withProps = () => ({
loading: {
type: Boolean,
default: false
},
})
of course it doesn't need to be a function, but in some cases it may be helpful and preemptively making it a function can make api consistent.
Define an Object called loadingProps in separate file called makeLoadingProps:
export const loadingProps = {
loading: {
type: Boolean,
default: false
}
}
then import it inside your component defined using the script setup syntax:
<script setup lang="ts">
import {defineProps} from 'vue'
import { loadingProps } from 'src/composables/makeLoadingProps';
const props = defineProps({
...loadingProps,
//other props
})
const { startLoading, stopLoading, innerLoading } = useLoading(props)
</script>

How to use this data from Vuex inside the component?

What is the best way to use this data from the Vuex store's Action in the needed component?
import axios from 'axios'
export default {
namespaced: true,
state: {
items: []
},
actions: {
fetchCategories ({state, commit}) {
return axios.get('/api/v1/categories')
.then(res => {
const categories = res.data
commit('setItems', {resource: 'categories', items: categories}, {root: true})
return state.items
})
}
}
}
Component
export default {
components: {
ThreadCreateModal,
ThreadList
},
data () {
return {
...
}
},
computed: {
...
},
created () {
...
},
methods: {
...
}
</script>
Where and how should I use that action for binding the data in this component?
Use mapState by import it from vuex and call it in computed:
computed: {
...mapState(['items']), // if you dont use namespace
...mapState("your_module_name", ['items'] ) // if you use namespace
},
then you can access it by this.items.
However, you can access it directly this.$store.state.items

Vue: Functional component doesn't receive props

The component smart-list does it's job and is rendering the correct component.
It just doesn't pass on the props. I'd expect them to be in a context.data but it is undefined.
SmartList.vue
import EmptyList from "./EmptyList";
import FullList from "./FullList";
export default {
functional: true,
props: {
items: {
type: Array
}
},
render(h, { props, data, children }) {
if (props.items.length > 0) {
return h(FullList, data, children);
} else {
return h(EmptyList, data, children);
}
}
};
I have prepared a codesandbox example
What do I miss?
I have found the solution. In the smart-list component I've changed one line:
import EmptyList from "./EmptyList";
import FullList from "./FullList";
export default {
functional: true,
props: {
items: {
type: Array
}
},
render(h, { props, data, children }) {
if (props.items.length > 0) {
- return h(FullList, data, children);
+ return h(FullList, { attrs: props }, children);
} else {
return h(EmptyList, data, children);
}
}
};
Now it works.
Can someone point me why passing the full data object doesn't work? 🤔

VueJS - vue-charts.js

I am trying to pass data I fetch from API to vue-chartjs as props, I am doing as in the documentation but it does not work.
Main component
<monthly-price-chart :chartdata="chartdata"/>
import MonthlyPriceChart from './charts/MonthlyPriceChart'
export default {
data(){
return {
chartdata: {
labels: [],
datasets: [
{
label: 'Total price',
data: []
}
]
},
options: {
responsive: true,
maintainAspectRatio: false
}
}
},
components: {
MonthlyPriceChart
},
created() {
axios.get('/api/stats/monthly')
.then(response => {
let rides = response.data
forEach(rides, (ride) => {
this.chartdata.labels.push(ride.month)
this.chartdata.datasets[0].data.push(ride.total_price)
})
})
.catch(error => {
console.log(error)
})
}
}
In response I have an array of obejcts, each of which looks like this:
{
month: "2018-10",
total_distance: 40,
total_price: 119.95
}
Then I want to send the data somehow to the chart so I push the months to chartdata.labels and total_price to chartdata.datasets[0].data.
chart component
import { Bar } from 'vue-chartjs'
export default {
extends: Bar,
props: {
chartdata: {
type: Array | Object,
required: false
}
},
mounted () {
console.log(this.chartdata)
this.renderChart(this.chartdata, this.options)
}
}
console.log(this.chartdata) outputs my chartsdata object from my main component and the data is there so the data is passed correctly to chart but nothing is rendered on the chart.
The documentation says this:
<script>
import LineChart from './LineChart.vue'
export default {
name: 'LineChartContainer',
components: { LineChart },
data: () => ({
loaded: false,
chartdata: null
}),
async mounted () {
this.loaded = false
try {
const { userlist } = await fetch('/api/userlist')
this.chartData = userlist
this.loaded = true
} catch (e) {
console.error(e)
}
}
}
</script>
I find this documentation a bit vague because it does not explain what I need to pass in chartdatato the chart as props. Can you help me?
Your issue is that API requests are async. So it happens that your chart will be rendered, before your API request finishes. A common pattern is to use a loading state and v-if.
There is an example in the docs: https://vue-chartjs.org/guide/#chart-with-api-data