How to show newly data added? - javascript

I want to ask why the newly added data does not display in the template, but it does show the newly added data in using console.log (see the ViewPost.vue).
This is the result after I add new post: result.png. Someone knows how to achieve this?
Here is my parent component:
<template>
<section>
//more codes here
<ViewPost v-for="data in postData" :key="data.post_id" :data="data" />
</section>
</template>
<script>
import { mapState } from 'vuex';
export default {
components: {ViewPost},
computed: {
...mapState({
postData: state => state.post.datas,
}),
}
//more codes here
};
</script>
And below is the ViewPost.vue
<template>
<span>
<div class="card mb-10">
<h1>body</h1>
{{ data.post_body }}
</div>
</span>
</template>
<script>
export default {
props: {
data: {},
},
created() {
console.log(this.data);
},
};

index as a key may work fine.
<template>
<section>
//more codes here
<ViewPost v-for="(data,index) in postData" :key="index" :data="data" />
</section>
</template>
<script>
import { mapState } from 'vuex';
export default {
components: {ViewPost},
computed: {
...mapState({
postData: state => state.post.datas,
}),
}
//more codes here
};
</script>
ViewPost.vue
<template>
<span>
<div class="card mb-10">
<h1>body</h1>
{{ data.post_body || data.body }}
</div>
</span>
</template>
<script>
export default {
props: ['data']
created() {
console.log(this.data);
},
};

Related

Trying to extend a Vuetify component

I would like to make ready to use components with my classes/stylish, I'm using mixins for the thing, but it seams the properties are not passed. I get the style but not the "items" i.e.
This is the code:
<template>
<span>
<p
class="text-left text-secondary text-caption ml-2 pb-0 pt-0 mb-0 mt-0"
v-if="label"
>
{{ label }}
</p>
<v-autocomplete
:class="getClass"
outlined
single-line
hide-details
v-bind="$props"
/>
</span>
</template>
<script>
import { VAutocomplete } from "vuetify/lib";
export default {
mixins: [VAutocomplete],
data() {
return {};
},
mounted() {
console.log(this.$props);
},
watch: {},
computed: {
getClass() {
return "input-style font-size-input text-light-input placeholder-light border-radius-md select-style mt-0 mb-2";
},
},
methods: {},
};
</script>

What causes the duplicated key error in this Vue.js application?

I am working on a small Todo App with Vue 3.
In App.vue I have the 3 child components and the methods:
<template>
<div id="app">
<Header/>
<List/>
<Footer/>
</div>
</template>
<script>
import axios from 'axios'
import Header from './components/Header.vue'
import List from './components/List.vue'
import Footer from './components/Footer.vue'
export default {
name: 'App',
components: {
Header,
List,
Footer
},
props: ['todos'],
data() {
return {
url: "https://jsonplaceholder.typicode.com/todos?&_limit=5",
dataIsLoaded: false,
isValidInput: true,
todos: [],
unsolvedTodos: [],
newTitle: "",
}
}
}
</script>
In List.vue I have:
<template>
<div>
<h1>List</h1>
<ul class="todo-list" v-if="dataIsLoaded">
<TodoItem v-for="todo in todos.slice().reverse()" :key="todo.id" v-bind:class="{done: todo.completed}" :todo="todo" />
</ul>
</div>
</template>
<script>
import TodoItem from "./TodoItem.vue";
export default {
name: 'List',
components: { TodoItem },
props: ['todos']
}
</script>
In TodoItem.vue:
<template>
<li>
<input type="checkbox" :checked="todo.completed" #change="toggleTodo(todo)" />
<span class="title">{{todo.title}}</span>
<button #click="deleteTodo(todo.id)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</li>
</template>
<script>
export default {
name: 'TodoItem',
props: ['todo']
}
</script>
The todo list's <h1> heading is displayed, but the unordered list of todos is not.
Introducing props: ['todos'] in App.vue throws the error Duplicated key 'todos'.
What am I missing?
On your App.vue you defined props['todos'] and at the same time todos is defined in your data(). That might be the one causing the error.
Looks like you forgot to define dataIsLoaded in List.vue. It either needs to be defined in data or be a computed property.

Popup does not open in App.vue when clicking on a search result

My goal is when clicking on any search item to open the Popup.
Why does not work — this.$emit('openPopup', bookId); in the method selectBook(bookId)
There is a component of Results.vue, which displays search results by using Google Books API:
<template>
<div class="results">
<ul class="results-items">
<li
class="book"
#click="selectBook(result.id)"
>
<img
:src="'http://books.google.com/books/content?id=' + result.id + '&printsec=frontcover&img=1&zoom=1&source=gbs_api'"
class="cover"
>
<div class="item-info">
<div class="bTitle">{{ result.volumeInfo.title }}</div>
<div
class="bAutors"
v-if="result.volumeInfo.authors"
>
{{ result.volumeInfo.authors[0] }}
</div>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
props: ['result'],
data() {
return {
bookId: '',
};
},
methods: {
selectBook(bookId) {
this.$router.push(`bookId${bookId}`);
this.$store.dispatch('selectBook', bookId);
this.$emit('hideElements', bookId);
this.$emit('openPopup', bookId);
},
},
};
</script>
Rusults screenshot
Is the main App.vue, which I want to display Popup:
<template>
<div id="app">
<div class="container">
<Header />
<popup
v-if="isOpenPopup"
#closePopup="closeInfoPopup"
#openPopup="showModal"
/>
<router-view/>
</div>
</div>
</template>
<script>
import Header from '#/components/Header.vue';
import Popup from '#/components/Popup.vue';
import 'bootstrap/dist/css/bootstrap.css';
export default {
components: {
Header,
Popup,
},
data() {
return {
isOpenPopup: false,
};
},
methods: {
showModal() {
console.log('click');
this.isOpenPopup = true;
},
closeInfoPopup() {
this.isOpenPopup = false;
},
},
};
</script>
The component Popup.vue
<template>
<div class="popup">
<div class="popup_header">
<span>Popup name</span>
</div>
<div class="popup_content">
<h1>Hi</h1>
<slot></slot>
<button #click="closePopup">Close</button>
</div>
</div>
</template>
<script>
export default {
name: 'popup',
props: {},
data() {
return {};
},
methods: {
closePopup() {
this.$emit('closePopup');
},
},
};
</script>
You are listening on popup component but triggering events on Result
Don't remember that events are bound to component.
You have several options how to handle it
Add event listeners (like #openPopup) only on Result component and use portal-vue library to render popup on top level
use global events, this.$root.emit and listen also on this.$root. In this case you add event listener in mount() hook and don't forget unregister it in beforeDestroy() hook
you can use Vuex and popup visibility and related data in global application store provided by Vuex

Vue Scoped Slots two way data binding between component and slot [duplicate]

This question already has an answer here:
update data in slot vuejs
(1 answer)
Closed 2 years ago.
I have a scoped slot. I need the content that am passing to the slot to be able to affect the parent template.
This is what i have so far:
Parent.vue
<template>
<div>
<slot :text="text" :msg="msg"/>
<p>{{text}}</p>
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
name: "Parent",
data() {
return {
text: "",
msg: ""
};
}
};
</script>
App.vue
<template>
<parent>
<template #default="{ text, msg }">
<input type="text" v-model="text"/>
<input type="text" v-model="msg"/>
</template>
</parent>
</template>
<script>
import Parent from "./components/Parent";
export default {
name: "App",
components: {
Toolbar
},
}
This does'nt work. How can i do something of the sort?
This is not possible. You can't change props (in this case slot props) given to your component(App.vue), but you can do something like this, with a "handler" method.
Parent.vue
<template>
<div>
<slot :text="text" :msg="msg" :setValue="setValue" />
<p>{{ text }}</p>
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
name: 'Parent',
data() {
return {
text: '',
msg: ''
};
},
methods: {
// set the current value with a function
setValue(e) {
this[e.target.name] = e.target.value;
}
}
};
</script>
App.vue
<template>
<parent>
<template #default="{ text, msg, setValue }">
Text: {{ text }}<br />
Msg: {{ msg }}<br /><br />
<!-- I have named the input fields after the variables in your data object and have the "setValue" method triggered by #input. -->
<input type="text" name="text" #input="setValue" />
<input type="text" name="msg" #input="setValue" />
</template>
</parent>
</template>
<script>
import Parent from './components/Parent';
export default {
name: 'App',
components: {
Parent
}
};
</script>

vuex creating a product details page

This is my first time using vuex so I am looking for some help. I have a products component and I would like to create a product component which will display the active products details. I think that I am nearly there but I am now stuck.
in my store I am setting
activeProduct: null, in the state and I have a mutation
mutations: {
setActiveProduct(state, product) {
state.activeProduct = product
}
}
then my products page (results.vue)
<template>
<div class="results">
<h1>Results</h1>
<ul>
<li v-for="product in products" :key="product.Vehicle.id">
<img v-bind:src="product.Vehicle.Url">
<div>
<h3>
{{ product.Vehicle.Manufacturer }}
{{ product.Vehicle.Model }}
</h3>
<h3>
<router-link
:to="'./Vehicle/'+product.Vehicle.id"
#input="setActiveProduct"
:value="$store.state.activeProduct"
><button>More</button></router-link>
</h3>
</div>
</li>
</ul>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
export default {
name: 'Results',
data() {
return {};
},
computed: {
...mapState([
'products',
'activeProduct'
])
},
methods: {
...mapMutations([
'setActiveProduct'
]),
setActiveProduct(val) {
this.$store.commit('setActiveProduct', val)
}
}
};
</script>
<style scoped lang="scss">
ul {
list-style-type: none;
padding: 0;
}
</style>
and my product page (vehicle.vue)
<template>
<div class="Vehicle">
<h1>Vehicle</h1>
<pre>store.$state.activeProduct: {{ $store.state.activeProduct }}</pre>
<!-- {{ activeProduct.Vehicle.Manufacturer }}
{{ activeProduct.Vehicle.Model }} -->
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'Vehicle',
data() {
return {
product: this.$store.getters.productById(this.$route.params['id'])
}
},
computed: {
...mapState([
'products',
'activeProduct'
]),
store() {
return this.$store.state
}
}
}
</script>
Any help getting this to work would be great! Thank you
i used a getter instead of a mutation to solve this problem

Categories