Repeated data in vue - vue.js

i`m having a problem with my vue, the problem is im trying to print 2 words, that is 'A.2' and 'B.3', but when im printing it, it just show 'B.3' and 'B.3'. here is my code
this is a simple quiz project, so everytime a user choose option a with true status it should be adding 1 point to the score, i haven`t made that yet.
<template>
<div class="hello">
<h1 v-if="show">hai</h1>
<h1 v-else>hehe</h1>
<p>{{ nama}}</p>
<input type="text" v-model="nama">
<button type="button" v-on:click="hideTitle">Click Me</button>
<h3> 1.Yang Dipakai Di sepatu adalah </h3>
<p>{{ nama}}</p>
<h3 v-for="j in jawaban">
<input type="radio">
{{j}}
</h3>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data : function() {
return{
nama: 'Luthfi',
show: true
},
{
jawaban: 'A.2',
correct: true
},
{
jawaban: 'B.3',
correct: false
},
{
jawaban: 'C.4',
correct: false
}
},
methods: {
hideTitle() {
this.show = !this.show
}
},
mounted: function () {
this.nama = 'Fitra'
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
i expect there is 4 output from option A to D, but it kept showing me same option

In your code, data() returns only one object that contains
{
nama: 'Luthfi',
show: true
}
You must change this like:
data : function() {
return{
nama: 'Luthfi',
show: true,
jawaban: 'A.22',
correct: true,
jawabann: 'B.3'
}
}

Related

How to fix this error: "v-model cannot be used on a prop, because local prop bindings are not writable?"

I'm trying to make a dropdown sort and I get this error:
VueCompilerError: v-model cannot be used on a prop, because local prop bindings are not writable. Use a v-bind binding combined with a v-on listener that emits update:x event instead.
Here are 2 components App and MySelect:
<template>
<!-- App Component -->
<div class="app">
<h1>Страница с постами</h1>
<div class="app__btns">
<my-button #click="showDialog">Cоздать пост</my-button>
<my-select v-model="selectedSort" :options="sortOptions" />
</div>
<my-dialog v-model:show="dialogVisible">
<post-form #create="createPost" />
</my-dialog>
<post-list :posts="posts" #remove="removePost" v-if="!isPostsLoading" />
<div v-else>Идет загрузка...</div>
</div>
</template>
<script>
import axios from 'axios'
import PostForm from './components/PostForm.vue'
import PostList from './components/PostList.vue'
export default {
components: { PostList, PostForm },
data() {
return {
posts: [],
dialogVisible: false,
isPostsLoading: false,
selectedSort: '',
sortOptions: [
{ value: 'title', name: 'По названию' },
{ value: 'body', name: 'По содержанию' },
],
}
},
methods: {
createPost(post) {
this.posts.push(post)
this.dialogVisible = false
},
removePost(post) {
this.posts = this.posts.filter((p) => p.id !== post.id)
},
showDialog() {
this.dialogVisible = true
},
async fetchPosts() {
try {
this.isPostsLoading = true
const res = await axios.get(
'https://jsonplaceholder.typicode.com/posts?_limit=10'
)
this.posts = res.data
} catch (error) {
alert('ошибка')
} finally {
this.isPostsLoading = false
}
},
},
mounted() {
this.fetchPosts()
},
}
</script>
<!-- флаг scoped - значит, что стили будут применяться только к этому комопненту -->
<style>
.app {
padding: 20px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.app__btns {
margin: 15px 0;
display: flex;
justify-content: space-between;
}
</style>
<template>
<!-- MySelect component -->
<select v-model="modelValue" #change="changeOption">
<option disabled value="">Выберите из списка</option>
<option v-for="option in options" :key="option.value" :value="option.value">
{{ option.name }}
</option>
</select>
</template>
<script>
export default {
name: 'my-select',
props: {
modelValue: {
type: String,
},
options: {
type: Array,
default: () => [],
},
},
methods: {
changeOption(event) {
this.$emit('update:modelValue', event.target.value)
},
},
}
</script>
<style lang="scss" scoped></style>
I need to update modelValue, so I tried to add
:value="modelValue"
instead of
v-model="modelValue"
and it works, but I'm not sure if this is the correct solution.
If anyone else is encountering this issue when updating their vue version. Please note that this error started to appear on version 3.2.45.
For the implementation pattern, as noted on the documentation, props should be considered readonly within the component. Vue did not enforce it enough prior to version 3.2.45.
Documentation with links to good implementation patterns : https://vuejs.org/guide/components/props.html#one-way-data-flow

nuxtjs add and remove class on click on elements

I am new in vue and nuxt and here is my code I need to update
<template>
<div class="dashContent">
<div class="dashContent_item dashContent_item--active">
<p class="dashContent_text">123</p>
</div>
<div class="dashContent_item">
<p class="dashContent_text">456</p>
</div>
<div class="dashContent_item">
<p class="dashContent_text">789</p>
</div>
</div>
</template>
<style lang="scss">
.dashContent {
&_item {
display: flex;
align-items: center;
}
&_text {
color: #8e8f93;
font-size: 14px;
}
}
.dashContent_item--active {
.dashContent_text{
color:#fff;
font-size: 14px;
}
}
</style>
I tried something like this:
<div #click="onClick">
methods: {
onClick () {
document.body.classList.toggle('dashContent_item--active');
},
},
but it changed all elements and I need style change only on element I clicked and remove when click on another
also this code add active class to body not to element I clicked
This is how to get a togglable list of fruits, with a specific class tied to each one of them.
<template>
<section>
<div v-for="(fruit, index) in fruits" :key="fruit.id" #click="toggleEat(index)">
<span :class="{ 'was-eaten': fruit.eaten }">{{ fruit.name }}</span>
</div>
</section>
</template>
<script>
export default {
name: 'ToggleFruits',
data() {
return {
fruits: [
{ id: 1, name: 'banana', eaten: false },
{ id: 2, name: 'apple', eaten: true },
{ id: 3, name: 'watermelon', eaten: false },
],
}
},
methods: {
toggleEat(clickedFruitIndex) {
this.fruits = this.fruits.map((fruit) => ({
...fruit,
eaten: false,
}))
return this.$set(this.fruits, clickedFruitIndex, {
...this.fruits[clickedFruitIndex],
eaten: true,
})
},
},
}
</script>
<style scoped>
.was-eaten {
color: hsl(24, 81.7%, 49.2%);
}
</style>
In Vue2, we need to use this.$set otherwise, the changed element in a specific position of the array will not be detected. More info available in the official documentation.

Why does my class not show in vue but my conditional class does?

I want to show two classes in my button. One that is conditional on a Boolean data value like "hideLeftArrow" and another class that shows up as the default like arrowBtn. The conditional class shows but the default class doesn't. What is wrong with my syntax in the following:
:class="[{ hideArrow: hideLeftArrow }, arrowBtn]"
My full code for reference
<template>
<div class="showcase-container">
<button
#click="showRightArrow"
:class="[{ hideArrow: hideLeftArrow }, arrowBtn]"
>
<img alt="left arrow" src="../assets/leftArrow.svg" class="arrow" />
</button>
<a
v-for="game in games"
:key="game.id"
:class="{ hideGame: game.hide }"
:href="game.link"
target="_blank"
>{{ game.name }}</a
>
<button
#click="showLeftArrow"
:class="[{ hideArrow: hideRightArrow }, arrowBtn]"
>
<img alt="right arrow" src="../assets/rightArrow.svg" class="arrow" />
</button>
</div>
</template>
<script>
export default {
data() {
return {
games: [
{
name: "Tryangle",
link: "https://google.com",
id: 1,
hide: false,
},
{
name: "BagRPG",
link: "https://youtube.com",
id: 2,
hide: true,
},
],
hideLeftArrow: true,
hideRightArrow: false,
};
},
methods: {
showLeftArrow() {
this.hideLeftArrow = !this.hideLeftArrow;
this.hideRightArrow = !this.hideRightArrow;
this.games[0].hide = true;
this.games[1].hide = false;
},
showRightArrow() {
this.hideLeftArrow = !this.hideLeftArrow;
this.hideRightArrow = !this.hideRightArrow;
this.games[0].hide = false;
this.games[1].hide = true;
},
},
};
</script>
<style lang="scss">
#import "../styles.scss";
.showcase-container {
.hideArrow {
visibility: hidden;
}
.arrowBtn {
background: none;
border: 0;
}
.hideGame {
display: none;
}
}
</style>
I think you're aiming for this, with quotes around arrowBtn:
:class="[{ hideArrow: hideLeftArrow }, 'arrowBtn']"
Otherwise arrowBtn will be treated as a property name and not a string..
That said, I'd probably do it this way instead:
class="arrowBtn"
:class="{ hideArrow: hideLeftArrow }"
class allows you to have both a static and a bound version on the same element.

Can I execute a method when an input box gets to a certain length?

I have an input box that takes a string. Can I execute a method (in vue.js) when the length of the string gets to a certain number?
something like
<input v-if="inputBox.length == 6 THEN runme()"...>
You can use watch option, you'll be able to react to data changes :
new Vue({
el: '#root',
data: {
message: '',
inputLength : undefined
},
methods : {
doSomething(){
console.log('I did it !')
}
},
watch :{
message : function(val) {
if(val.length>=5){
this.inputLength = val.length
this.doSomething();
}
}
}
})
.container {
padding-top: 2em;
}
.intro {
font-size: 1.5em;
margin-bottom: 1.5em;
}
.input-value {
margin-top: 1em;
font-size: 1.25em;
}
.highlight {
color: #00d1b2;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
<h1 class="intro">Binding with Vue</h1>
<div id='root' class="box">
<label class="label">Enter text here</label>
<input class="input is-medium" type='text' id='input' v-model='message'>
<p class="input-value">The value of the input is: <span class="highlight">{{ inputLength }}</span></p>
</div>
</div>
In this example, if input length is >= 5 then it will change the inputLenght value in data and execute a method.
For more informations about this, go see :
https://v2.vuejs.org/v2/guide/computed.html#Watchers
You can use a watcher to trigger a method when the string exceeds the length:
new Vue({
data () {
return {
model: ''
}
},
watch: {
model: {
handler: function (value) {
if (value.length >= 6) {
this.trigger()
}
}
}
},
el: '#app',
methods: {
trigger () {
alert('hi there')
}
},
template: `<input v-model="model">`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

How to make the props binding reactive when using 'createElement' function

Vue.config.devtools = false
Vue.config.productionTip = false
let modal = Vue.extend({
template: `
<div class="modal">
<p>Balance: {{ balance }}</p>
<input #input="$emit('input', $event.target.value)" :value="value">
<button #click="$emit('input', balance)">ALL</button>
</div>
`,
props: ['balance', 'value']
})
function makeComponent(data) {
return { render(h) { return h(modal, data) } }
}
Vue.component('app', {
template: `
<div>
<p>Balance: {{ balance }}</p>
<p>To withdraw: {{ withdrawAmount }}</p>
<p>Will remain: {{ balance - withdrawAmount }}</p>
<button #click="onClick">Withdraw</button>
<modal-container ref="container"/>
</div>`,
data () {
return {
withdrawAmount: 0,
balance: 123
}
},
methods: {
onClick () {
this.$refs.container.show(makeComponent({
props: {
balance: String(this.balance),
value: String(this.withdrawAmount)
},
on: {
input: (value) => {
this.withdrawAmount = Number(value)
}
}
}))
}
}
})
Vue.component('modal-container', {
template: `
<div>
<component v-if="canShow" :is="modal"/>
</div>
`,
data () {
return { modal: undefined, canShow: false }
},
methods: {
show (modal) {
this.modal = modal
this.canShow = true
},
hide () {
this.canShow = false
this.modal = undefined
}
}
})
new Vue({
el: '#app'
})
.modal {
background-color: gray;
width: 300px;
height: 100px;
margin: 10px;
padding: 10px;
}
* {
font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;
color: #2c3e50;
line-height: 25px;
font-size: 14px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.js"></script>
<div id="app">
<app></app>
</div>
This is a simplified version of our application using vue-js-modal. The basic Idea is that we pass a component declaration along with required VNodeData to the plugin function and it would append that component to a pre-defined DOM point with proper data bindings.
And our usecase is that:
User clicks 'Withdraw'
Modal pops up with an input field and static field displaying user's balance
User enters the amount he/she wants to withdraw and that amount and resulting balance are displayed in the callee component.
There is a 'ALL' button besides the input field for user to easily enter a number equal to his/her balance
Problem: When user clicks 'ALL', the 'modal' component fires an 'input' event with value of the balance and the callee component receives that event and updates its 'withdrawAmount'. But the 'withdrawAmount' is supposed to be passed back to the 'modal' as 'value' prop and further updates the input field, which doesn't happen.