how to send object to child component in Vue elementui - javascript

I am new to vue.
so here is my vue template
<template>
<div class="app-container">
<el-dialog :visible="dialogVisible"
title="View order"
:before-close="() => dialogVisible = false">
<order-form :oneorder="oneorderdata" #success="handleAdd" #cancel="dialogVisible = false" />
</el-dialog>
<el-table v-loading="loading" :data="orders" border>
<el-table-column prop="order.id" label="Id" />
<el-table-column prop="order.fullName" label="Full Name" />
<el-table-column prop="order.address.name" label="Address" />
<el-table-column prop="order.status" label="Status" />
<el-table-column label="View" prop="order.id" min-width="150">
<template slot-scope="{row}">
<el-col style="flex: 0">
<el-button icon="el-icon-plus" type="primary" #click="senddata(row.order)">
View Order
</el-button>
</el-col>
</template>
</el-table-column>
</el-table>
</div>
</template>
when i click the button the dialog is true so i call the order-form component
and i want to pass data to it. component is opening normally but error said that oneorderview is not found although i am showing it in console normally in senddata method.
i tried
v-bind:oneorder="oneorderview"
but it didn't work , it it shows no error.
thanks in advance.
this is my script
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { getOrders } from "#/api/store";
import dataStore from "#/store/modules/data";
import { OrderView } from "../../../models";
import { OrderInput } from "#/models";
import DataModule from "#/store/modules/data";
import OrderForm from "./form.vue";
type _OrderInput = OrderInput;
interface TableRowData {
editMode: boolean;
order: OrderView;
editedOrder: _OrderInput;
}
#Component({
components: {
OrderForm,
},
})
export default class Orders extends Vue {
orders: TableRowData[] = [];
oneorderview: any;
loading = false;
dialogVisible = false;
searchKey = "";
async created() {
await DataModule.ensureLoaded();
this.fetchData();
}
async fetchData() {
this.loading = true;
await dataStore.loadorders();
if (dataStore.orders.hasLoaded) {
this.orders = dataStore.orders.data.map(order => ({
editMode: false,
order,
editedOrder: { ...order }
}));
}
this.loading = false;
}
handleAdd() {
this.dialogVisible = false;
}
senddata(selectedorder: any) {
this.oneorderview = selectedorder;
this.dialogVisible = true;
console.log('hahahaha', this.oneorderview);
}
}
</script>
and how to handle data in child component.

You're using class components in Vue typescript. To pass props you need to either use the classic Vue properties or by annotating your class members:
import { Component, Prop } from 'vue-property-decorator'
#Component
export default class App extends Vue {
// Makes a "exampleProperty" a component prop with the default value of 'Example'
#Prop({default: 'Example'})
exampleProperty: string
}

Related

Access data property of child component from parent vue 3 typescript and composition api

I have setup two components parent and child:
App.vue //Parent
<template>
<div class="common-layout">
<Container>
<Header><center>Vue JS 3 (Composition API and )</center></Header>
<Main>
<BookForm ref="bookRef" />
<p v-if="bookRef">{{ bookRef }}</p>
</Main>
</Container>
</div>
</template>
<script setup lang="ts">
import BookForm from "./components/organism/bookForm/index.vue"
import { ref } from "vue"
import {
ElContainer as Container,
ElHeader as Header,
ElMain as Main,
} from "element-plus"
const bookRef = ref<InstanceType<typeof BookForm>>()
</script>
BookForm.vue //child
<template>
<Row span="20">
<Column :span="12" :offset="6">
<!-- <HelloWorld /> -->
<Form label-position="top">
<Input label="Title" v-model="title" />
<Input label="Price" v-model="price" />
<Button label="Add" type="success" :onClick="addBook" />
</Form>
</Column>
</Row>
</template>
<script setup lang="ts">
import { ElRow as Row, ElCol as Column, ElForm as Form } from "element-plus"
import HelloWorld from "#/components/HelloWorld.vue"
import Input from "#/components/atom/input/index.vue"
import Button from "#/components/atom/button/index.vue"
import { reactive, ref } from "vue"
interface IBook {
title: string
price: string | number
}
const books = reactive<IBook[]>([])
const title = ref<string>("")
const price = ref<string | number>("")
const addBook = () => {
books.push({ title: title.value, price: price.value })
title.value = ""
price.value = ""
}
</script>
I've followed this thread from vue forum for the solution but I cannot retrieve data from child component into parent component.
When I console log console.log(bookRef.value) I get undefined. What is the correct way to get child component's data with typescript and composition api setup tag ?
Try to use defineexpose to expose the child component properties to the parent one :
<script setup lang="ts">
import { ElRow as Row, ElCol as Column, ElForm as Form } from "element-plus"
import HelloWorld from "#/components/HelloWorld.vue"
import Input from "#/components/atom/input/index.vue"
import Button from "#/components/atom/button/index.vue"
import { reactive, ref,defineExpose } from "vue"
interface IBook {
title: string
price: string | number
}
const books = reactive<IBook[]>([])
const title = ref<string>("")
const price = ref<string | number>("")
const addBook = () => {
books.push({ title: title.value, price: price.value })
title.value = ""
price.value = ""
}
defineExpose({
books, title, price, addBook
})
</script>

Vue3 v-model remove spaces on input paste

Consider the following example Vue component:
Template:
<template>
<input
id="pin"
v-model="pin"
type="password"
name="pin"
placeholder="Pin"
#input="removeSpace($event.target)"
/>
</template>
Script:
<script>
import { ref } from 'vue'
const pin = ref('')
const removeSpace = (target) => {
pin.value = target.value.replace(/\s/g, '')
}
</script>
How would I go about moving the removeSpace function in this component to VueX4 store? So I can use it in multiple components? Can't seem to get it to work, the input field doesn't update.
I have tried something as follows:
Template:
<template>
<input
id="test"
v-model="store.state.testPin"
type="text"
name="test"
placeholder="test"
#input="store.dispatch('removeSpace', $event.target)"
/>
</template>
VueX store:
import { createStore } from 'vuex'
const store = createStore({
state: {
testPin: ''
},
actions: {
removeSpace(state, target) {
state.testPin = target.value.replace(/\s/g, '')
}
}
})
export default store

How to change element hint dynamically with Vuetify 3?

This is my component.vue:
<template>
<v-text-field
name="Foo"
:label="$t('foo')"
type="text"
hint="This is a hint"
persistent-hint
></v-text-field>
<v-btn color="primary" #click="onButtonClick()">Press</v-btn>
</template>
And this is component.ts
import { defineComponent, reactive, ref, Ref} from 'vue';
export default defineComponent({
setup() {
function onButtonClick() {
}
return { onButtonClick }
}
});
I want to change hint on button click, for example to This is a new hint. Could anyone say how to do in Vuetify 3 using Composition API?
Just create a ref property called hint inside the setup hook then bind it to the hint prop and update it when you click on the button:
import { defineComponent, reactive, ref, Ref} from 'vue';
export default defineComponent({
setup() {
const hint=ref('This is a hint')
function onButtonClick() {
hint.value="new hint"
}
return { onButtonClick, hint }
}
});
in template :
<template>
<v-text-field
name="Foo"
:label="$t('foo')"
type="text"
:hint="hint"
persistent-hint
></v-text-field>
<v-btn color="primary" #click="onButtonClick()">Press</v-btn>
</template>

Vue's Mutations and Actions are not working

Index.js from the Store Folder
import Vue from "vue";
import Vuex from "vuex";
import state from "../store/state";
import mutations from "../store/mutations";
import actions from "../store/actions";
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
actions,
});
State.js
/* eslint-disable */
import cats from "../data/cats.js";
import dogs from "../data/dogs.js";
export default {
cats,
dogs,
};
Actions.js
// method add pet -> dispatch action -> mutate -> state changes
export default {
addPet: ({ commit }, payload) => {
console.log("payload iss", payload);
commit("appendPet", payload);
},
};
Mutations.js
export default {
appendPet: (state, { specie, pet }) => {
console.log("specie and pet are", specie, pet);
state[specie].append(pet);
},
};
Home.vue
<template>
<div class="home">
<h1>Adopt a New Best Friend</h1>
<button #click="formShow" class="btn btn-primary">Add New Pet</button>
<b-form #submit.prevent="handleSubmit" v-if="showForm === true">
<b-form-group id="input-group-2" label="Pet's Name:" label-for="input-2">
<b-form-input
id="input-2"
v-model="formData.name"
type="text"
placeholder="Enter name"
required
></b-form-input>
</b-form-group>
<b-form-group id="input-group-3" label="Specie:" label-for="input-3">
<b-form-select
id="input-3"
v-model="formData.specie"
:options="['cats', 'dogs']"
required
></b-form-select>
</b-form-group>
<b-form-group id="input-group-2" label="Pet's Age:" label-for="input-2">
<b-form-input
id="input-2"
v-model="formData.age"
type="number"
placeholder="Enter Age"
required
></b-form-input>
</b-form-group>
<b-button type="submit" variant="primary">Submit</b-button>
<b-button type="reset" variant="danger">Reset</b-button>
</b-form>
<!-- <b-card class="mt-3" header="Form Data Result">
<pre class="m-0">{{ formData }}</pre>
</b-card> -->
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
name: "Home",
data() {
return {
showForm: false,
formData: {
age: 0,
specie: null,
name: "",
},
};
},
methods: {
...mapActions["appendPet"],
formShow() {
this.showForm = !this.showForm;
},
// mapActions and appendPet do not show on console
handleSubmit() {
console.log("hello this is the handle submit method");
// console.log("mapActions", ...mapActions);
// console.log("appendPet gnnn.................", this.appendPet);
const { specie, age, name } = this.formData;
console.log("specie , age and name are", specie, age, name);
const payload = { specie, pet: { name, age } };
this.appendPet(payload);
},
},
};
</script>
The template part of my home.vue is working fine but I am not being able to mutate my state. I am getting nothing when I console.out the mapActions, I think that the appendPet method that mutates the state is not being called as the payload is not reaching the Action.js , not reaching the actions of my store. May be the mapActions is not being executed as through it, I am calling the appendPet.
mapActions is a function and you are using it as an Object:
You have: ...mapActions["appendPet"]
And you need: ...mapActions(["appendPet"])
Check the docs for further info:
You are using mapActions on mutate function.

List isn't dynamically displayed in vue.js

I'm new to vue.js and learning on my own with the vue doc, youtube videos and such. I've been searching for a while and looking at youtube tutorials and haven't found an answer so far, hope you guys will be able to help me.
So here's my issue, I'm building a web app and I need to display a list of objects dynamically but it doesn't show the first time I'm loading that page. I have to go to some other route and come back to see it, so I guess I'm misunderstanding some life cycle or something from that field of expertise...
I'm using the vuex to store and retrieve my data as seen below :
import Vue from 'vue';
const state = {
journees: {},
};
const getters = {
getJourneeList(state) {
return state.journees;
}
};
const mutations = {
GET_LIST(state, journees) {
state.journees = journees;
}
};
const actions = {
getJourneesUser({commit}) {
Vue.axios.get('/journee/')
.then( res => {
commit('GET_LIST', res.data)
})
.catch((err) => console.log(err))
}
};
export default {
state,
getters,
mutations,
actions
};
And then I'm getting it in my vue like this:
<template>
<v-container>
<v-card v-for="heure in heures" :key="heure._id">
<v-card-title>{{ heure }}</v-card-title>
</v-card>
</v-container>
</template>
<script>
export default {
name: "TimeList",
data() {
return {
heures: this.$store.getters.getJourneeList,
}
},
created() {
this.$store.dispatch('getJourneesUser');
}
}
</script>
You need to use mapState and use it inside computed value because then computed value will response to change in state. You do not need getter but if you want here is the version with getter. It should be like this if your store module called journees:
without getter
<template>
<v-container>
<v-card v-for="heure in journees" :key="heure._id">
<v-card-title>{{ heure }}</v-card-title>
</v-card>
</v-container>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "TimeList",
computed: {
...mapState(["journees"])
},
created() {
this.$store.dispatch("getJourneesUser");
},
};
</script>
with getter
<template>
<v-container>
<v-card v-for="heure in getJourneeList" :key="heure._id">
<v-card-title>{{ heure }}</v-card-title>
</v-card>
</v-container>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "TimeList",
computed: {
...mapGetters(["getJourneeList"])
},
created() {
this.$store.dispatch("getJourneesUser");
},
};
</script>

Categories

Resources