vue3 Transferring incoming data with props to another data - vuejs3

hello i am new among you,
I want to transfer the data from the props to the "items new" data, but it didn't work no matter what I did. is there a way to run this?
{{ itemsnew }}
</template>
<script>
export default {
name: 'ImageList',
props: ['items'],
data() {
return {
itemsnew: this.files(),
dragging: false,
}
},
computed: {
files() {
return this.items
},
},
}
</script>

Related

How to populate FormKit input fields with dynamic data fetched from a database

I'm making a fullstack app with vue3, axios using FormKit. For editing existing records I want to populate the input fields with the current data fetched from a mysql database. I stripped down the code to everything needed to display my problem, which in this code example is populating the FormKit input field with the lotnumber I fetched via the asynchronous function "getLotById". The lotnumber appears in the paragraph section but not in the input field. How can I properly delay the rendering of the FormKit element until the lotnumber has been fetched? Here's my code:
<script>
// import axios
import axios from "axios";
export default {
name: "LotEdit",
data() {
return {
lotnumber: this.lotnumber
}
},
props: {
lotid: Number
},
created: async function () {
await this.getLotById();
},
methods: {
// Get Lot By Id
async getLotById() {
try {
const response = await axios.get(`http://localhost:5000/lot/${this.$route.params.id}`);
this.lotnumber = response.data.lotnumber;
console.log(response.data);
}
catch (err) {
console.log(err);
}
},
}
};
</script>
<template>
<div>
<FormKit
type="text"
name="lotnumber"
label="lotnumber"
placeholder=""
validation="required"
:value="lotnumber"
/>
</div>
<div>
<p> Here the lotnumber appears: {{ lotnumber }}</p>
</div>
</template>
I suggest using a v-model on the FormKit input. Because it is two-way bound it means as soon as the async/await completes the data is populated on the template too. Something like...
<FormKit
v-model="lotnumber"
type="text"
name="lotnumber"
label="lotnumber"
placeholder=""
validation="required"
:value="lotnumber"
/>
Getting a little smarter I managed to solve the problem in the following way:
<script>
// import axios
import axios from "axios";
export default {
name: "LotEdit",
data() {
return {
lotnumber: this.lotnumber
}
},
props: {
lotid: Number
},
mounted: async function () {
const response = await this.getLotById();
const node = this.$formkit.get('lotnumber')
node.input(response.data.lotnumber, false)
},
methods: {
// Get Lot By Id
async getLotById() {
try {
const response = await axios.get(`http://localhost:5000/lot/${this.$route.params.id}`);
console.log(response.data);
return response;
}
catch (err) {
console.log(err);
}
},
}
};
</script>
<template>
<div>
<FormKit
type="text"
id="lotnumber"
name="lotnumber"
label="lotnumber"
placeholder=""
validation="required"
:value="lotnumber"
/>{{ lotnumber }}
</div>
</template>
Feel free to post any recommendations as I'm not a pro yet...
I'm also still figuring out how to handle controlled forms but I guess an alternative way to do it is with Form Generation
<script>
export default {
// ...
async setup() {
try {
const response = await axios.get(`http://localhost:5000/lot/${this.$route.params.id}`);
const schema = [
{
$formkit: "text",
label: "Lot Number",
value: response.data.lotnumber,
validation: "required",
},
];
} catch (err) {
console.log(err);
}
return { schema }
}
// ...
}
</script>
<template>
<FormKit type="form">
<FormKitSchema :schema="schema" />
</FormKit>
</template>

vue3 setup emit with function click

i want to run a method when emitting how can i get it?
When handleShow(depth is clicked), I want to run collapsed in the medhod in the setup.
or
I want to trigger the function I will write in setup
<MenuLink
:link="items"
:key="items.title"
#click.stop="handleShow(depth)"
/>
<script>
import {ref} from "vue"
import MenuLink from "./MenuLink";
export default {
name: 'MenuItems',
components: {MenuLink},
props: {
items: {type: Object, required: true},
depth: {Number},
selected: {Number},
},
data() {
return {
opensCollapsed: false
};
},
methods: {
collapsed(dep) {
console.log(dep)
}
},
setup(props, {emit}) {
const showDropdown = ref(false);
const handleShow = (depth) => {
emit('clicked', depth)
}
return {
showDropdown,
handleShow,
}
},
};
</script>
emit should only be used if you want to get an event out of your component to its parent (for example, if your component is a custom button and you want its parent to specify what would happen when clicking on it). Otherwise, you can write the code you want inside of handleShow instead of calling emit. You can also change the function name to whatever you want, just make sure it's the same inside the setup method and in the #click.stop property.
In your case (since you just console.log the result):
<MenuLink
:link="items"
:key="items.title"
#click.stop="handleShow(depth)"
/>
<script>
import {ref} from "vue"
import MenuLink from "./MenuLink";
export default {
name: 'MenuItems',
components: {MenuLink},
props: {
items: {type: Object, required: true},
depth: {Number},
selected: {Number},
},
data() {
return {
opensCollapsed: false
};
},
setup(props, {emit}) {
const showDropdown = ref(false);
const handleShow = (depth) => {
console.log(depth)
// do whatever you want here
}
return {
showDropdown,
handleShow,
}
},
};
</script>

Vue3 Props v-if sync

I'm making props with vue, but v-if doesn't work, and I'm wondering if the functions I've done are written correctly.
I want the data from props to work synchronously. What are my mistakes made?
What functions does vue props check at startup?
<my-alert type="warning" appearance="outline" showIcon="false">Hello</my-alert>
myAlert.vue
<template>
<div class="block" :class="[typeClass,appearanceClass]">
<div class="alert-icon" v-if="myIcon">
<i>ICON</i>
</div>
</div>
</template>
<script>
const types =
['primary','accent','warn','basic','info','success','warning','error',
];
const appearances =
['border','accent','fill','outline','soft'];
import {defineComponent} from "vue";
import {computed} from "vue";
export default {
props: {
type: {
type: String,
default: 'primary',
required: true,
validator: value => {
return ['primary', 'accent', 'warn', 'basic', 'info', 'success', 'warning', 'error'].includes(value)
}
},
appearance: {
type: String,
default: 'border',
required: true,
validator: value => {
return ['border', 'accent', 'fill', 'outline', 'soft'].includes(value)
}
},
showIcon: {
default: false
}
},
computed: {
typeClass() {
return 'alert-type-' + this.type
},
appearanceClass() {
return 'alert-appearance-' + this.appearance
},
myIcon() {
return this.showIcon;
}
}
}
</script>
From your code what I can see, that you are passing the props shwoIcon like this showIcon="false", which is static passing and eventually pass false value as a string "false" not as Boolean value. So use props like this :shwoIcon="false" I mean use colon before showIcon which make the props dynamic. link
And Also in your my-alert component for showIcon props declear type for the better practice
showIcon: {
type: Boolean,
default: false,
},
Another way is, just simply change your computed property myIcon() to check the string props value, like this below,
myIcon() {
return this.showIcon === "true";
}

Vuex, Vuexfire: How to get data from firestore into frontend?

I have some data in a firestore and want to display it in my vue app.
Firestore:
Test.vue
<template>
<p>{{ items }}</p>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: mapState(["items"]),
methods: {
getItems() {
this.$store.dispatch("bindItems");
},
},
mounted() {
this.getItems();
},
};
</script>
index.js
import { createStore } from "vuex";
import { firestoreAction } from "vuexfire";
import { vuexfireMutations } from "vuexfire";
import { db } from "./db";
const store = createStore({
state() {
return {
items: [],
};
},
actions: {
bindItems: firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef("items", db.collection("items"));
}),
},
mutations: {
...vuexfireMutations,
},
getters: {
items(state) {
return state.items;
},
},
});
store.subscribe((state) => console.log(state));
export default store;
To check my store, I added this line in index.js: store.subscribe((state) => console.log(state));. As it turns out, the data from firestore actually makes it to my store:
Why is it not rendered in the frontend? What do I have to change to make it appear?
Edit.
When I hardcode some data in my store and remove this.$store.dispatch("bisndItems"); from the monuted hook, the data gets rendered:
state() {
return {
items: {"name": "peter"},
};
},

Conditional navbar based on a user authentication status

I'm trying to conditionally display navbar elements of a navigation component based on the onAuthStateChanged Firebase function.
<template>
<navbar dark position="top" class="default-color" scrolling>
<mdb-navbar-brand href="#/" style="font-weight: bolder;">
Test
</mdb-navbar-brand>
<navbar-collapse>
<navbar-nav left>
<navbar-item href="#/" waves-fixed>Home</navbar-item>
<navbar-item href="#/css" waves-fixed>About</navbar-item>
<navbar-item href="#/jobs" waves-fixed>Jobs</navbar-item>
<navbar-item href="#/advanced" waves-fixed>Profile</navbar-item>
</navbar-nav>
<navbar-nav right>
<router-link to="/signup"><button v-if="!user" type="button" class="btn btn-primary">Signup</button></router-link>
<router-link to="/login"><button v-if="!user" type="button" class="btn btn-primary">Login</button></router-link>
<p><a v-if="user" #click="logout">Logout</a></p>
</navbar-nav>
</navbar-collapse>
</navbar>
</template>
<script>
import Navbar from '#/components/Navbar.vue';
import NavbarItem from '#/components/NavbarItem.vue';
import NavbarNav from '#/components/NavbarNav.vue';
import NavbarCollapse from '#/components/NavbarCollapse.vue';
import mdbNavbarBrand from '#/components/NavbarBrand.vue';
import firebase from 'firebase';
export default {
name: 'Navigation',
data() {
return {
user: null,
};
},
components: {
Navbar,
NavbarItem,
NavbarNav,
NavbarCollapse,
mdbNavbarBrand
},
methods: {
logout() {
firebase.auth().signOut()
.then(() => {
this.$router.push({path: '/'});
});
},
created() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.user = user;
} else {
this.user = null;
}
});
}
}
};
</script>
Unfortunately, for some reason, the onAuthStateChanged is not working. I also tried to simply display the user in the console from the component perspective, but it's not working as well:
console.log(firebase.auth().currentUser);
Thanks in advance for any hints.
I just wanted to point out another option. Renaud Tarnec's answer is correct but there is a second solution.
You can use the arrow function syntax. With arrow functions the context doesnt change so there is no need to set vm = this before the function since this will still work inside the function. I'm a huge fan of lambda/arrow functions and see no reason not to use them.
Renaud Tarnec's should be the accepted answer but just wanted to offer a second option :)
export default {
name: 'Navigation',
data() {
return {
user: null,
};
},
components: {
Navbar,
NavbarItem,
NavbarNav,
NavbarCollapse,
mdbNavbarBrand
},
methods: {
....
}
},
created: function () {
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.user = user;
} else {
this.user = null;
}
});
}
};
If you want to call firebase.auth().onAuthStateChanged() in the created lifecycle hook you should do as follows:
export default {
name: 'Navigation',
data() {
return {
user: null,
};
},
components: {
Navbar,
NavbarItem,
NavbarNav,
NavbarCollapse,
mdbNavbarBrand
},
methods: {
....
}
},
created: function () {
var vm = this;
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
vm.user = user;
} else {
vm.user = null;
}
});
}
};
The way you do it, you are declaring created as a "standard" component method.

Resources