VueJS props issue something missing - vue.js

I have a tabbed view and I need to pass a value from a select field to the tabs but I don't get props right. This is the parent:
<template>
<div>
<b-form-group id="memberListing" label-for="memberListing" class="mr-sm-2">
<b-form-select
v-model="memberSelection"
:title="memberSelection"
#change="getUserID"
aria-describedby="memberListing"
>
<option disabled value="" selected>Mitglied auswählen</option>
<option
v-for="member in memberList"
v-bind:key="member"
:value="member.cb_userid"
lazy
>
{{member.user_name}}
</option>
</b-form-select>
</b-form-group>
<Biometrics :title="memberSelection"></Biometrics>
<b-card title="Card Title" no-body>
<b-card-header header-tag="nav">
<b-nav card-header tabs>
<b-nav-item to="/users/profile" exact exact-active-class="active"
>Profil</b-nav-item
>
<b-nav-item
to="/users/trainingsplans"
exact
exact-active-class="active"
>Trainingspläne</b-nav-item
>
<b-nav-item to="/users/biometrics" exact exact-active-class="active"
>Biometrie</b-nav-item
>
</b-nav>
</b-card-header>
<b-card-body>
<router-view></router-view>
</b-card-body>
</b-card>
</div>
</template>
<script>
import axios from 'axios'
import Biometrics from "#/components/users/biometrics.vue";
export default {
data: () => {
return {
profileList: 'http://localhost:8000/userProfiles/profileList',
memberList: [],
memberSelection: null,
}
},
props: {
},
components: {
Biometrics
},
async mounted() {
try {
let memberListData = await axios.get(this.profileList)
this.memberList = memberListData.data
console.log(this.memberList)
} catch (e) {
this.errors.push(e)
}
},
methods: {
getUserID: function () {
// this.childMemberSelect = this.memberSelection
// console.log(this.childMemberSelect)
},
},
}
</script>
What am I missing? I'm trying for hours now but I cant get the value to show up in the specified tab when I select the value.

this is the child :
<pre>
<template>
<div>
{{title}}
</div>
</template>
<script>
export default {
created () {
console.log(this.title)
},
methods: {},
props: {
title: Number,
},
data() {
return {
}
},
components:{},
}
</script>
</pre>

Related

function not updating vue property

I have this component:
<template>
<div class="hello">
<div>
My prop: {{ myprop }}?
</div>
<div>
<button class="fas fa-lock-open lock" #click="changeText()">Click</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'StartPage',
props: {
myprop: {
type: String
}
},
model: {
prop: 'myprop',
event: 'click'
},
methods: {
changeText () {
this.$emit('click', 'sometext')
console.log('this.myprop', this.myprop)
}
}
})
</script>
Im using vue v3. Everytime I click on the button, I still see the text "My prop: ?" in the browser.
And in the console I can see: "this.myprop undefined" every time I click on the button.
What am I doing wrong?
As per my understanding, You are trying to update the prop text on click of button from the child component. If Yes, you can achieve it simply by emitting a new text and updating that in the parent component.
Live Demo :
const ShowPropText = {
template: `<div class="hello">
<div>
My prop: {{ myprop }}
</div>
<div>
<button class="fas fa-lock-open lock" #click="changeText()">Click</button>
</div>
</div>`,
props: ['myprop'],
methods: {
changeText() {
this.$emit('click-event', 'sometext')
}
}
}
const app = Vue.createApp({
components: {
'show-prop-text': ShowPropText
},
data() {
return {
text: 'This is default text'
}
},
methods: {
methodCall(e) {
this.text = e;
}
}
})
app.mount('#app')
<script src="https://cdn.jsdelivr.net/npm/vue#next"></script>
<div id="app">
<show-prop-text :myprop="text" #click-event="methodCall"></show-prop-text>
</div>

Why is component shown just for a fraction of a second?

As a beginner in Vue, I am struggling with a problem that - even this should not be too hard - I can't solve. The principle is as follows:
I want to create a survey that consists of different topics. The user should be able to choose between these topics (component A and component B). This works fine.
But: When I click on the button "Show Component C", this component is only displayed for a fraction of a second. Why is this, what mistake have I made and how can I solve the problem?
Thanks a lot for your help!
App.vue
<button #click="setSelectedComponent('ComponentA')">Component A</button>
<button #click="setSelectedComponent('ComponentB')">Component B</button>
<component-b
v-if="selectedComponent === 'ComponentB'"
> </component-b>
<component-a
v-if="selectedComponent === 'ComponentA'"
></component-a>
<start
v-if="selectedComponent === 'form-empty'"
></start>
</template>
<script>
import ComponentB from './components/ComponentB.vue';
import ComponentA from './components/ComponentA.vue';
import Start from './components/Start.vue';
export default {
components: {
ComponentB,
ComponentA,
Start,
},
data() {
return {
selectedComponent: 'form-empty',
}
},
methods: {
setSelectedComponent(cmp) {
this.selectedComponent = cmp;
},
}
}
</script>
Start.vue
<template>
<form>
<div>
<h1>Which Component Do You Want To Select?</h1>
</div>
</form>
</template>
**
Component A
<template>
<form>
<h1>Component A</h1>
<div class="form-control">
<input type="range" min ="0" max="100" v-model=value>
</div>
<div>
<button #click="evaluateForm">Save Data</button>
</div>
<h4>Value: {{value}}</h4>
</form>
<component-c v-if="varia === 'yes'"></component-c>
</template>
<script>
import ComponentC from './ComponentC.vue';
export default {
components: {
ComponentC
},
methods: {
evaluateForm() {
this.varia='yes'
}
},
computed: {
result() {
return parseInt(this.abc) + parseInt(this.cde)
}
},
data() {
return {
value: '',
varia: ''
}
}
}
</script>
Component B
<template>
<form>
<h1>Component B</h1>
<div>
<input type="range" min ="0" max="100" v-model=value>
</div>
<div>
<button #click="evaluateForm">Save Data</button>
</div>
<h4>Value: {{value}}</h4>
</form>
<component-c v-if="varia === 'yes'"></component-c>
</template>
<script>
import ComponentC from './ComponentC.vue';
export default {
components: {
ComponentC
},
methods: {
evaluateForm() {
this.varia='yes'
}
},
computed: {
result() {
return parseInt(this.abc) + parseInt(this.cde)
}
},
data() {
return {
value: '',
varia: ''
}
}
}
</script>
Component C
<template>
<form>
<div class="form-control">
<h1>The value is: </h1>
</div>
</form>
</template>
I tested this out locally and the problem comes from the fact that you are using <form> in ComponentA and ComponentB. If you switch those to <div> or <form #submit.prevent> you'll see that it works as you expected.
Here is some documentation on the <form> element to learn more about how it works: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
Component A
<template>
<div>
<h1>Component A</h1>
<div>
<input type="range" min ="0" max="100" v-model=value>
</div>
<div>
<button #click="evaluateForm">Save Data</button>
</div>
<h4>Value: {{value}}</h4>
</div>
</template>
<script>
export default {
methods: {
evaluateForm() {
this.$emit('xxx');
}
},
computed: {
result() {
return parseInt(this.abc) + parseInt(this.cde)
}
},
data() {
return {
value: '',
}
}
}
</script>
App.Vue
<template>
<button #click="setSelectedComponent('ComponentA')">Component A</button>
<button #click="setSelectedComponent('ComponentB')">Component B</button>
<component
:is="selectedComponent"
></component>
<component-a
#xxx="startComponentC"
v-if="varia === 'yes'"
></component-a>
<component-c
v-if="varia === 'yes'"
></component-c>
</template>
<script>
import ComponentB from "./components/ComponentB.vue";
import ComponentA from "./components/ComponentA.vue";
import Start from "./components/Start.vue";
export default {
components: {
ComponentB,
ComponentA,
Start,
},
data() {
return {
selectedComponent: "start",
varia:""
};
},
methods: {
setSelectedComponent(cmp) {
this.selectedComponent = cmp;
},
startComponentC() {
this.varia="yes"
this.selectedComponent="stopConditionforComponentAandB"
}
},
};
</script>

Vue component is not getting re-rendered/refreshed

I have a page header (Navbar) which has a [LOG IN] link and clicking it navigates to /login route. 'login' component shows a modal form and authenticates/login()s the user and after which route is set to Home page again. At this time the header's [LOG IN] should change to ["loggedinUser"], but it does not. Here is the code
(uses bootstrap-vue for css)
./App.vue
<template>
<component :is="layout">
<router-view :layout.sync="layout"/>
</component>
</template>
<script>
export default {
name: 'App',
data () {
return {
layout: 'div'
}
}
}
</script>
./components/BaseLayout.vue
<template>
<div>
<Header/>
<slot />
<Footer/>
</div>
</template>
<script>
import Header from './Header'
import Footer from './Footer'
export default {
name: 'BaseLayout',
props: [],
components: { Header, Footer },
methods: {}
}
</script>
The Navbar is rendered via this component.
./components/Header.vue
<template>
<b-navbar
type="dark"
variant="dark"
fixed="top"
class="text-monospace text-white"
>
<b-navbar-brand to="/">MyWebapp</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<b-nav-item href="#" disabled>DISABLED</b-nav-item>
</b-navbar-nav>
<!-- Right aligned nav items -->
<b-navbar-nav class="ml-auto">
<b-nav-item to="/about">ABOUT</b-nav-item>
<header-user></header-user>
</b-navbar-nav>
</b-collapse>
</b-navbar>
</template>
<script>
import HeaderUser from '#/components/HeaderUser.vue'
export default {
components: { HeaderUser }
}
</script>
"header-user" was earlier part of Header, but I made it a separate component.
./HeaderUser.vue
<template>
<div>
<b-nav-item
v-show="!isAuthenticated"
#click="signin"
>&lbbrk;LOG IN&rbbrk;
</b-nav-item>
<b-nav-item-dropdown
v-show="isAuthenticated"
>
<template slot="button-content">&lbbrk;{{ loggedinUser }}&rbbrk;</template>
<b-dropdown-item href="#" disabled>profile</b-dropdown-item>
<b-dropdown-item #click="signout">log off</b-dropdown-item>
</b-nav-item-dropdown>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
name: 'HeaderUser',
data () {
return {
authenticated: false
}
},
methods: {
...mapActions('user', ['logout']),
signin () {
this.$router.push('/login')
},
signout () {
// this.$store.dispatch('logout')
this.logout()
this.authenticated = false
this.$router.push('/landingpage')
}
},
computed: {
...mapGetters('user', ['isAuthenticated', 'getCurrentUser']),
loggedinUser: function () {
if (this.getCurrentUser) {
return this.getCurrentUser['name'].toUpperCase()
} else {
return null
}
}
}
}
</script>
Here is the login component
./pages/Login.vue
<template>
<div>
<b-modal
size="lg"
id="loginModal"
title="Credentials"
hide-footer
centered
no-close-on-backdrop
>
<b-form inline>
<b-input
class="mb-2 mr-sm-2 mb-sm-0"
id="usernameInput"
placeholder="Lab user id"
v-model="loginForm.user"
/>
<b-input
type="password"
id="passwordInput"
placeholder="Unikix domain password"
v-model="loginForm.password"
/>
<b-button #click="authenticate">Submit</b-button>
</b-form>
</b-modal>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
name: 'Login',
data () {
return {
loginForm: {
user: '',
password: '',
rememberChecked: ''
}
}
},
methods: {
...mapActions('user', ['login']),
authenticate () {
this.login(this.loginForm)
.then(() => {
this.$emit('authenticated', true) // But who's catching?
this.$router.push('/landingpage')
})
.catch(e => {
this.$router.push('/404')
})
},
},
mounted () {
this.$bvModal.show('loginModal')
}
}
</script>
Since Header and Login are separate components (no relationship), I am unable to communicate between them. After login is successful, and state has changed, Header is not aware of it and not reacting to it. the [LOG IN] remains unchanged.
How can I solve this?
(after log in is successful, if I reload the page in browser, Header is rendered with "loggedinUser" correctly.
Your store is there to share information between components.
Getters should be reactive by default, so your getter isAuthenticated should be reflected in all components when it changes, however it depends how you're writing your getters.
If you're adding properties to objects on the fly in your state, you need to use
Vue.Set/this.$set
Try and take a look at this example, it might help you out.
https://codesandbox.io/s/vuex-store-yhyj4

VueJS + VueRouter + Bootstrap-vue (modal from modal) = <failed to convert exception to string>

I'll try display modal from modal (I'll create separate components for each modal). When second modal is closed I want to return to first modal. But after I'm display first modal second time I got error 'failed to convert exception to string' from administration.js. I'm using VueRouter too.
administration.js (main entry with router-view) -> partner.vue (with partnerEditor.vue component)
partnerEditor.vue
<template>
<div>
<b-modal ref="partnerEditor" title="Partner" :busy="isBusy" cancel-title="cancel" ok-variant="info" ok-title="save" v-on:ok="onCreate">
<div class="form-group">
<div class="input-group mb-3">
<select class="form-control">
<option v-for="contact in contacts">{{ contact.name }}</option>
</select>
<div class="input-group-append">
<b-btn v-on:click="$refs.contactEditor.show()"></b-btn>
</div>
</div>
</div>
</b-modal>
<contactEditor ref="contactEditor" v-on:hide="$refs.partnerEditor.show()"></contactEditor>
</div>
</template>
<script>
export default {
data() {
return {
contacts: [],
isBusy: false
}
},
methods: {
show() {
this.$refs.partnerEditor.show();
}
},
components: {
contactEditor: () => import('./contactEditor.vue'),
},
}
</script>
contactEditor.vue
<template>
<b-modal ref="contactEditor" title="Contact" :busy="isBusy" cancel-title="cancel" ok-variant="info" ok-title="save" v-on:ok="onCreate" v-on:hide="$emit('hide')">
<div class="form-group">
<label>name</label>
<input type="text" class="form-control" placeholder="" />
</div>
</b-modal>
</template>
<style></style>
<script>
export default {
model: {
event: 'hide'
},
data() {
return {
isBusy: false
}
},
methods: {
show() {
this.$refs.contactEditor.show();
},
}
}
</script>
routes
const router = new VueRouter({
routes: [
{
name: 'configuration', path: '/configuration', component: () => import('./administrator/configuration/index.vue'),
children: [
{ name: 'configuration-partner', path: '/configuration/partner', component: () => import('./administrator/configuration/partner.vue') }
]
}
]
});

how to hide sidebar in vue

guys, I m new to Vue and taken a coreui admin panel to develop some font vue but now I got stuck in this problem this is nav.js file
export default {
items: [
{
name: 'Product',
url: '/product',
icon: 'fa fa-cart-arrow-down',
children: [
{
name: 'Addproduct',
url: '/product/Addproduct',
},
{
name: 'Listproduct',
url: '/product/Listproduct',
}
]
},
]
}
main container
<template>
<div class="app">
<div class="app-body">
<Sidebar :navItems="nav"/>
<main class="main">
<div class="container-fluid">
<router-view></router-view>
</div>
</main>
<AppAside/>
</div>
</div>
</template>
<script>
import nav from '../_nav'
export default {
name: 'full',
components: {
Sidebar,
},
data () {
return {
nav: nav.items
}
},
computed: {
name () {
return this.$route.name
},
list () {
return this.$route.matched
}
}
}
</script>
here is my sidebar
<template v-for="(item, index) in navItems">
<template v-if="item.title">
<SidebarNavTitle :name="item.name" :classes="item.class" :wrapper="item.wrapper"/>
</template>
<template v-else>
<template v-if="item.children">
</template>
<template v-else>
<SidebarNavItem :classes="item.class">
<SidebarNavLink :name="item.name" :url="item.url" :icon="item.icon" :badge="item.badge" :variant="item.variant"/>
</SidebarNavItem>
</template>
</template>
</template>
i m stroing addproduct in my browser local storage now if when user login and go to dashboard then my i watch which url name is present in browser application or not if present show that else ignore now my problem is that how i can apply if condition like addproduct=addprodcut this this visible else hide
You could have a method in mounted hook, which can fetch data from localstorage and check if it's present in the url or not. Then assign it to a variable in main component which toggles the sidebar. Something like below should work:
<template>
<div class="app">
<div class="app-body">
<Sidebar :navItems="nav" v-if="showSidebar" />
<main class="main">
<div class="container-fluid">
<router-view></router-view>
</div>
</main>
<AppAside/>
</div>
</div>
</template>
<script>
import nav from '../_nav'
export default {
name: 'full',
components: {
Sidebar,
},
data () {
return {
nav: nav.items,
showSidebar: false
}
},
mounted () {
this.checkSidebarVisibility()
},
methods: {
checkSidebarVisibility: function() {
const inLocal = window.localStorage.getItems('your_item');
const inUrl = window.location.toString();
// check if inurl inside inLocal
if (inUrl is in inLocal) {
this.showSidebar = true;
} else {
this.showSidebar = false;
}
}
},
computed: {
name () {
return this.$route.name
},
list () {
return this.$route.matched
}
}
}
</script>