質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

Q&A

解決済

1回答

1635閲覧

【Vue.js】selectで選択した内容を別のページに表示したい

退会済みユーザー

退会済みユーザー

総合スコア0

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

0グッド

0クリップ

投稿2021/11/23 00:07

編集2021/11/24 04:05

前提・実現したいこと

生年月日をselectで選択し、選択内容をstorestateに保存し、それを2ページ目で表示したいです。

発生している問題・エラーメッセージ

error Duplicated key 'year' error Duplicated key 'month' error Duplicated key 'day'

該当のソースコード

src/router/index.js

javascript

1import Vue from 'vue' 2import VueRouter from 'vue-router' 3import page1 from '../pages/page1.vue' 4 5Vue.use(VueRouter) 6 7const routes = [ 8 { 9 path: '/', 10 name: 'page1', 11 component: page1 12 }, 13 { 14 path: '/page2', 15 name: 'page2', 16 // route level code-splitting 17 // this generates a separate chunk (about.[hash].js) for this route 18 // which is lazy-loaded when the route is visited. 19 component: () => import(/* webpackChunkName: "about" */ '../pages/page2.vue') 20 } 21] 22 23const router = new VueRouter({ 24 mode: 'history', 25 base: process.env.BASE_URL, 26 routes 27}) 28 29export default router 30

src/store/index.js

javascript

1import Vue from 'vue' 2import Vuex from 'vuex' 3 4Vue.use(Vuex) 5 6export default new Vuex.Store({ 7 state: { 8 year: '', 9 month: '', 10 day: '' 11 }, 12 mutations: { 13 setYear (state, year) { 14 state.year = year 15 }, 16 setMonth (state, month) { 17 state.month = month 18 }, 19 setDay (state, day) { 20 state.day = day 21 } 22 }, 23 actions: { 24 getYear: ({commit}, year) => { 25 commit('setYear', year) 26 }, 27 getMonth: ({commit}, month) => { 28 commit('setMonth', month) 29 }, 30 getDay: ({commit}, day) => { 31 commit('setDay', day) 32 } 33 }, 34 getters: { 35 currentYear: state => { 36 return state.year 37 }, 38 currentMonth: state => { 39 return state.month 40 }, 41 currentDay: state => { 42 return state.day 43 } 44 } 45}) 46

src/pages/page1.vue

javascript

1<template> 2 <div class="page1"> 3 <p>生年月日</p> 4 <form><!--年号も合わせて生年月日を選択します--> 5 <select v-model="year" @change="getDays"> 6 <option v-for="n in 100" v-bind:value="n + 1921" v-bind:key="n">{{(n + 1921) | era}}</option> 7 </select>8 <select v-model="month" @change="getDays"> 9 <option v-for="n in 12" v-bind:key="n">{{n}}</option> 10 </select>11 <select v-model="day" @change="getDays"> 12 <option v-for="n in daysMax" v-bind:key="n">{{n}}</option> 13 </select>14 </form> 15 <router-link to="/page2">次へ進む</router-link> 16 </div> 17</template> 18 19<script> 20export default { 21 data() { 22 return { 23 year: 2000, 24 month: 1, 25 day: 1, 26 daysMax: '' 27 } 28 }, 29 created() { 30 this.getDays() 31 }, 32 computed: { 33 year: { 34 get() { 35 return this.$store.getters.year 36 }, 37 set(value) { 38 this.$store.dispatch("getYear", value) 39 } 40 }, 41 month: { 42 get() { 43 return this.$store.getters.month 44 }, 45 set(value) { 46 this.$store.dispatch("getMonth", value) 47 } 48 }, 49 day: { 50 get() { 51 return this.$store.getters.day 52 }, 53 set(value) { 54 this.$store.dispatch("getDay", value) 55 } 56 }, 57 }, 58 methods: { 59 getDays: function() {//月末の日にちを計算します。例えば、2月であれば28日(うるう年以外)。 60 this.daysMax = new Date(this.year, this.month, 0).getDate(); 61 } 62 }, 63 filters: {//西暦に対する和暦を計算します。 64 era(y) { 65 let result; 66 if (y > 2018) { 67 result = `${y} (令和${y-2018})`; 68 } else if (y > 1988) { 69 result = `${y} (平成${y-1988})`; 70 } else if (y > 1925) { 71 result = `${y} (昭和${y-1925})`; 72 } else if (y > 1911) { 73 result = `${y} (大正${y-1911})`; 74 } 75 return result; 76 } 77 } 78}; 79</script> 80

src/pages/page2.vue

javascript

1<template> 2 <div class="page2"> 3 <p>生年月日</p> 4 <p>{{$store.getters.currentYear}}{{$store.getters.currentMonth}}{{$store.getters.currentDay}}</p> 5 </div> 6 <router-link to="/">前に戻る</router-link> 7 </div> 8</template> 9 10<script> 11export default { 12 computed: { 13 currentYear() { 14 return this.$store.getters.currentYear 15 }, 16 currentMonth() { 17 return this.$store.getters.currentMonth 18 }, 19 currentDay() { 20 return this.$store.getters.currentDay 21 } 22 } 23} 24</script>

試したこと

エラーの原因としては、すでにdatayear,month,dayが指定されているにも関わらず、computedにも同様に指定されているためと考えられます。year,month,dayをそれぞれひとまとめにできればエラーが解消されると推測していますが、うまくいきません。試しにdataの定数名とmethodの定数名を別の名前にしてみたところ、storestateから生年月日を参照でき、選択内容を2ページ目に表示できたのですが...

javascript

1data() { 2 return { 3 dataYear: 2000,//year → dataYearに変更 4 dataMonth: 1,//month → dataMonthに変更 5 dataDay: 1,//day → dataDayに変更 6 daysMax: '' 7 } 8//(中略) 9methods: { 10 getDays: function() {//year → dataYear, month → dataMonthにそれぞれ変更 11 this.daysMax = new Date(this.dataYear, this.dataMonth, 0).getDate(); 12 } 13} 14

今度はdataの初期値とv-modelとの関係がなくなってしまい、初期状態で2000(平成12)年1月1日が表示されず、月末の日にち計算がおかしくなってしまいました。(例えば、本来あり得ない2月31日が表示可能になってしまう)
selectの内容を別のページに表示しつつ、初期値の表示、月末の日にち計算する方法を教えてください。

追記1
v-modelをdateに合わせる、初期値を受け皿の変数date…に代入する
というコメントをいただきました。コメントに基づき、以下のように修正しました。

HTML

1<form> 2 <select v-model="date" @change="getDays"><!--dataYear → dateに変更--> 3 <option v-for="n in 100" v-bind:value="n + 1921" v-bind:key="n">{{(n + 1921) | era}}</option> 4 </select>年 5 <select v-model="date" @change="getDays"><!--dataMonth → dateに変更--> 6 <option v-for="n in 12" v-bind:key="n">{{n}}</option> 7 </select>月 8 <select v-model="date" @change="getDays"><!--dataDay → dateに変更--> 9 <option v-for="n in daysMax" v-bind:key="n">{{n}}</option> 10 </select>日 11</form>

javascript

1data() { 2 return { 3 date: moment("2000-01-01").toDate(),//dataYear,dataMonth,dataDayから変更 4 daysMax: '' 5 } 6//(中略) 7methods: { 8 getDays: function() {//合わせてdataYear → date.getFullYear(), dataMonth → date.getMonth()にそれぞれ変更 9 new Date(this.date.getFullYear(), this.date.getMonth(), 0).getDate(); 10 } 11}

しかし、初期値の表示、月末の日にち計算はできませんでした。エラー内容は以下の通りです。

v-on handler: "TypeError: this.date.getFullYear is not a function"

getFullYearとgetMonthを使用するにあたり、moment("2000-01-01").toDate()でdateをdateObjに合わせたので、問題ないように思うのですが...

補足情報(FW/ツールのバージョンなど)

Vue version: 2.6.14
Vue-CLI version: 4.5.14

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FKM

2021/11/24 01:13

v-modelの方をdate…に合わせてもだめですか? 他の方法としては初期値を受け皿の変数date…に代入するとか?
退会済みユーザー

退会済みユーザー

2021/11/24 04:11

コメントありがとうございます。 コメントに基づき修正してみましたが、追記1にあるようにエラーが出てしまい、dateをうまく活用できていません。 お手数ですが、ご意見いただけると幸いです。 初学者ゆえ、そもそも追記・修正依頼の意図を誤って理解しているかもしれませんので、その場合もご指摘お願いします。
FKM

2021/11/24 04:14

オブジェクトの内部のプロパティに入れるのではなく、移し替えるだけです。変数の流れを追ってみてください。たとえば dateYear = this.year このように代入していくわけです。
退会済みユーザー

退会済みユーザー

2021/11/24 05:31

早速のコメントありがとうございます。フォローさせていただきました。 大変申し訳ありませんが、私の理解力が乏しく具体的にどこをどのように修正するのかわかりませんでした。 このままですと、やりとりや質問の追記が長くなってしまいますので、修正する場所とコード内容を明記していただけると幸いです。以下に例を挙げます。(Markdown記法ができないので見づらいですが) 例) <select v-model="year" @change="getDays"><!--year → dateYearに変更--> (中略) data() { return { year: 2000, //dateYear: this.yearに変更 } } ご面倒をおかけして大変申し訳ありませんが、例に沿ってご指摘いただけると理解できると思いますので、よろしくお願いします。
guest

回答1

0

ベストアンサー

FKMさんのご意見が役に立ちました。ありがとうございます。
解決方法ですが、methodsのgetDaysの中に

this.year = this.dateYear; this.month = this.dateMonth; this.day = this.dateDay;

を追加することで、月末の日にち計算をさせつつ、2ページ目に生年月日を表示することができました。

修正したpage1.vueのコード全文を以下に記載します。それ以外のファイルは修正なしです。
src/pages/page1.vue

JavaScript

1<template> 2 <div class="page1"> 3 <p>生年月日</p> 4 <form> 5 <select v-model="dateYear" @change="getDays"> 6 <option v-for="n in 100" v-bind:value="n + 1921" v-bind:key="n">{{(n + 1921) | era}}</option> 7 </select>8 <select v-model="dateMonth" @change="getDays"> 9 <option v-for="n in 12" v-bind:key="n">{{n}}</option> 10 </select>11 <select v-model="dateDay" @change="getDays"> 12 <option v-for="n in daysMax" v-bind:key="n">{{n}}</option> 13 </select>14 </form> 15 <router-link to="/page2">次へ進む</router-link> 16 </div> 17</template> 18 19<script> 20export default { 21 data() { 22 return { 23 dateYear: 2000, 24 dateMonth: 1, 25 dateDay: 1, 26 daysMax: '' 27 } 28 }, 29 created() { 30 this.getDays() 31 }, 32 computed: { 33 year: { 34 get() { 35 return this.$store.getters.year 36 }, 37 set(value) { 38 this.$store.dispatch("getYear", value) 39 } 40 }, 41 month: { 42 get() { 43 return this.$store.getters.month 44 }, 45 set(value) { 46 this.$store.dispatch("getMonth", value) 47 } 48 }, 49 day: { 50 get() { 51 return this.$store.getters.day 52 }, 53 set(value) { 54 this.$store.dispatch("getDay", value) 55 } 56 }, 57 }, 58 methods: { 59 getDays: function() { 60 this.year = this.dateYear;//追加修正箇所です。 61 this.month = this.dateMonth;//追加修正箇所です。 62 this.day = this.dateDay;//追加修正箇所です。 63 this.daysMax = new Date(this.year, this.month, 0).getDate(); 64 } 65 }, 66 filters: { 67 era(y) { 68 let result; 69 if (y > 2018) { 70 result = `${y} (令和${y-2018})`; 71 } else if (y > 1988) { 72 result = `${y} (平成${y-1988})`; 73 } else if (y > 1925) { 74 result = `${y} (昭和${y-1925})`; 75 } else if (y > 1911) { 76 result = `${y} (大正${y-1911})`; 77 } 78 return result; 79 } 80 } 81}; 82</script>

投稿2021/11/25 08:11

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問