I created a dynamic form that calculates 2 values and displays the result card only after all values are filled and submitted, utilizing the v-if
directive.
Vuetify is my chosen UI framework for this project.
This is the approach I took:
<template>
<v-container>
<v-row class="mt-2" justify="center">
<v-col cols="12" sm="8" md="6">
<v-form ref="form" @submit.prevent="onSubmit">
<v-row class="mb-1">
<v-col cols="6">
<v-select
v-model="fighter1"
:items="fighters"
item-text="name"
item-value="id"
return-object
label="Player 1"
:rules="[(v) => !!v || 'Required.']"
/>
</v-col>
<v-col cols="6">
<v-select
v-model="fighter2"
:items="fighters"
item-text="name"
item-value="id"
return-object
label="Player 2"
:rules="[(v) => !!v || 'Required.']"
/>
</v-col>
</v-row>
<!-- This is the submit button -->
<ReadyToFight />
</v-form>
</v-col>
</v-row>
<v-row>
<v-col>
<!-- This is the result card -->
<v-card v-if="result" id="result" class="pb-2">
<h1 class="text-center text-uppercase result-score">{{ result }}</h1>
<h2 class="text-center text-uppercase result-text">
{{ resultText }}
</h2>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script lang="ts">
import { Fighter, fighters } from '@/data/fighters'
import matchupsChart from '@/data/matchups'
import Vue from 'vue'
import { MatchupTypes, toResult } from '~/data/matchupTypes'
type IndexPageType = {
fighters: Fighter[]
fighter1: Fighter | undefined
fighter2: Fighter | undefined
result: MatchupTypes | undefined
}
export default Vue.extend({
name: 'IndexPage',
data(): IndexPageType {
return {
fighters,
fighter1: undefined,
fighter2: undefined,
result: undefined
}
},
computed: {
resultText(): string {
if (this.result) return toResult(this.result)
return `Can't get result`
}
},
// Attempted to watch the result changing
// to scroll into view when it happens
watch: {
result(newResult) {
if (newResult) document.querySelector('#result')?.scrollIntoView()
}
},
methods: {
onSubmit() {
;(this.$refs.form as any).validate()
if (this.fighter1 && this.fighter2) {
this.result = matchupsChart
.get(this.fighter1.id)
?.get(this.fighter2.id) as MatchupTypes
}
}
}
})
</script>
The main idea behind my approach was:
Monitor the result
, and if it becomes truthy, execute scrollIntoView()
Unfortunately, this approach did not work due to the result
changing before the rendering of the element.
If anyone has suggestions on how to tackle this issue, please share your ideas!