🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Vue.js

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

Vue CLI

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

ラジオボタン

ラジオボタンはフォームに使われる要素のひとつであり、ユーザに限られた選択肢からひとつの答えを選んでもらうというものです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

2218閲覧

Vue.jsでTodoアプリ作成。完了のラジオボタンを選択中に新規タスクを追加しても作業中のタスクが表示されないようにしたい。

F_Yohei

総合スコア14

Vue.js

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

Vue CLI

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

ラジオボタン

ラジオボタンはフォームに使われる要素のひとつであり、ユーザに限られた選択肢からひとつの答えを選んでもらうというものです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2021/01/13 01:06

前提・実現したいこと

完了のラジオボタンを選択中に新規タスク追加した際に、作業中のタスクが表示されないようにしたい。
反対に作業中のラジオボタン選択中に「作業中」のボタンを押して「完了」に変わった瞬間に状態が完了になったものは表示されないようにしたい。

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

イメージ説明

このように完了のラジオボタンを選択している時にタスクを追加すると作業中のタスクまで表示されてしまいます。
特にエラーは出ていません。

該当のソースコード

HTML

1<template> 2 <div> 3 <h1>ToDoリスト</h1> 4 <form> 5 <input type="radio" name="state" id="allTodo" checked v-on:change="allTodo" /> 6 <label for="allTodo">すべて</label> 7 <input type="radio" name="state" id="workingTodo" v-on:change="workingTodo" /> 8 <label for="workingTodo">作業中</label> 9 <input type="radio" name="state" id="doneTodo" v-on:change="doneTodo" /> 10 <label for="doneTodo">完了</label> 11 </form> 12 13 <div> 14 <table> 15 <thead> 16 <tr> 17 <th>ID</th> 18 <th>コメント</th> 19 <th>状態</th> 20 </tr> 21 </thead> 22 23 <tbody id="todoList"> 24 <tr 25 v-for="(todo, index) in todos" 26 :key="todo.state" 27 v-bind:class="{ hide: todo.viewChange}" 28 > 29 <td>{{ index }}</td> 30 <td>{{ todo.task }}</td> 31 <td> 32 <button class="state-management-button" @click="changeState(index)">{{ todo.state }}</button> 33 </td> 34 <td> 35 <button @click="deleteTask(index)">削除</button> 36 </td> 37 </tr> 38 </tbody> 39 </table> 40 </div> 41 42 <h2>新規タスクの追加</h2> 43 <form> 44 <input type="text" class="todoInput" v-model="newTask" /> 45 <button type="submit" value="追加" @click="addNewTask">追加</button> 46 </form> 47 </div> 48</template>

javascript

1<script> 2export default { 3 data() { 4 return { 5 newTask: "", 6 todos: [] 7 }; 8 }, 9 methods: { 10 addNewTask(e) { 11 e.preventDefault(); 12 if (this.newTask.match(/\S/g)) { 13 this.todos.push({ 14 task: this.newTask, 15 state: "作業中", 16 viewChange: false 17 }); 18 } 19 this.newTask = ""; 20 }, 21 deleteTask(id) { 22 if (id > -1) { 23 this.todos.splice(id, 1); 24 } 25 }, 26 changeState(id) { 27 if (this.todos[id].state === "作業中") { 28 this.todos[id].state = "完了"; 29 } else if (this.todos[id].state === "完了") { 30 this.todos[id].state = "作業中"; 31 } 32 }, 33 workingTodo(e) { 34 if (e.target.checked) { 35 this.todos.forEach(todo => { 36 if (todo.state === "完了") { 37 todo.viewChange = true; 38 } else { 39 todo.viewChange = false; 40 } 41 }); 42 } 43 }, 44 doneTodo(e) { 45 if (e.target.checked) { 46 this.todos.forEach(todo => { 47 if (todo.state === "作業中") { 48 todo.viewChange = true; 49 } else { 50 todo.viewChange = false; 51 } 52 }); 53 } 54 console.log(e.target.checked); 55 }, 56 allTodo(e) { 57 if (e.target.checked) { 58 this.todos.forEach(todo => { 59 todo.viewChange = false; 60 }); 61 } 62 } 63 } 64}; 65</script>

css

1<style scoped> 2.state-management-button { 3 margin-right: 10px; 4} 5 6.todoInput { 7 margin-right: 10px; 8} 9 10.hide { 11 display: none; 12} 13</style>

Vue.jsでコードを書いています。

今は、作業中、完了のそれぞれのラジオボタンが選択をした時に
それぞれのタスクが保持しているstateの状態によってCSSの.hideを
付けたり外したりして表示・非表示を制御してます

試したこと

当初は各メソッドでe.target.checkedを付けずに実装しておりそれでも表示・非表示はできる状態です。

試しにe.target.checkedを付けて実装してみたのですが状況変わらずでした。

何かいい方法があればご教授いただければと思い質問させていただきました????‍♂️

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

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

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

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

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

guest

回答1

0

ベストアンサー

算出プロパティ(computed)を利用してTODOリストを表示用に加工して画面に表示するのはいかがでしょうか?
ご参考になれば幸いです。

HTML

1 <tbody id="todoList"> 2 <tr v-for="(todo, index) in viewTodos" :key="index"> // todos → viewTodos に変更 3 <td>{{ todo.id}}</td> // 修正箇所:index→todo.idに変更 4 <td>{{ todo.task }}</td> 5 <td> 6 <button 7 class="state-management-button" 8 @click="changeState(todo.id)" // 修正箇所:index→todo.idに変更 9 > 10 {{ todo.state }} 11 </button> 12 </td> 13 <td> 14 <button @click="deleteTask(todo.id)">削除</button> // 修正箇所:index→todo.idに変更 15 </td> 16 </tr> 17 </tbody>

JavaScript

1  <script> 2 { 3 data() { 4 return { 5 newTask: "", 6 todos: [], 7 displayState: "" 8 }; 9 }, 10 computed: { // 算出プロパティを追加 11 viewTodos() { 12 return this.displayState 13 ? this.todos.filter((i) => i.state === this.displayState) 14 : this.todos; 15 } 16 }, 17 methods: { 18 addNewTask(e) { 19 e.preventDefault(); 20 if (this.newTask.match(/\S/g)) { 21 this.todos.push({ 22 id: this.todos.length, // 修正箇所:タスク追加時にidを付与 23 task: this.newTask, 24 state: "作業中" // 利用しないため、viewChangeを削除 25 }); 26 } 27 this.newTask = ""; 28 }, 29 deleteTask(id) { 30 if (id > -1) { 31 this.todos.splice(id, 1); 32 this.todos.forEach((todo, index) => { // 修正箇所: idの振り直し 33 todo.id = index; 34 }); 35 } 36 }, 37 changeState(id) { 38 const todo = this.todos[id]; // 修正箇所: idの検索 39 if (todo.state === "作業中") { 40 todo.state = "完了"; 41 } else if (todo.state === "完了") { 42 todo.state = "作業中"; 43 } 44 }, 45 workingTodo() { // 変更 46 this.displayState = "作業中"; 47 }, 48 doneTodo() { // 変更 49 this.displayState = "完了"; 50 }, 51 allTodo() { // 変更 52 this.displayState = ""; 53 } 54 } 55 }); 56 </script>

投稿2021/01/13 03:25

編集2021/01/16 04:47
Twoshi

総合スコア354

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

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

F_Yohei

2021/01/13 05:49

ありがとうございます????‍♂️ こちらのコードで試してみたところ、完了のラジオボタン選択中にタスクを追加したところ作業中のタスクは表示されなくなりましたが、その後に作業中のラジオボタンを選択し、作業中のボタンをクリックしたところ、タスクが増えたり減ったりするような挙動になってしまいました。汗
Twoshi

2021/01/13 06:07

ご確認いただきありがとうございます! ラジオボタン「作業中」を選択中で「作業中」ボタンをクリックした場合、状態が「完了」になるため、作業中タスクが減ると思いますが、想定した挙動ではないでしょうか? 作業中タスクを選択中に「作業中」ボタンをクリックした場合、状態が「完了」になるが、表示はそのまましたいということでよろしいでしょうか?
Twoshi

2021/01/13 07:22

失礼いたしました。 動作確認しコメントいただいた内容理解いたしました。 原因として変更対象のtodoのIDがindexのままとなっていたためでした。 上記回答を修正いたします。
F_Yohei

2021/01/14 05:43

想像していた通りの挙動になりました! ありがとうございます????‍♂️ ちなみになんですけど、どこを修正したのか教えていただけますでしょうか? 修正前のコードがあると助かります????
F_Yohei

2021/01/14 06:11

他に問題がないか確かめたところ削除ボタンを押した時に削除されないタスクが出てきました。
Twoshi

2021/01/14 06:12

ご確認いただきありがとうございます! 修正箇所にコメントを追加いたしました! > 修正前のコードがあると助かります???? 修正前のコードは、ご質問で記載いただいているコードとなりますm(_ _)m
Twoshi

2021/01/14 06:29

削除ボタン押下処理のご確認をいただきありがとうございます! 削除処理の修正が漏れておりました。 修正いたしましたので、ご確認お願いいたします。
F_Yohei

2021/01/14 07:39

修正していただきありがとうございます???? 求めていた挙動になりました????‍♂️ 表示させる時はcomputedプロパティを使うといいんですね????
Twoshi

2021/01/14 08:03

ご確認いただきありがとうございます! 求められていた挙動になりよかったです! 少しでもお役に立てたのであれば、幸いですm(_ _)m
F_Yohei

2021/01/16 02:17

何度もすみません。 なぜこのように処理を記載するのか教えていただけると助かります????‍♂️ const oldId = this.todos.length ? this.todos[this.todos.length - 1].id : 0; 単純に const oldId = this.todos.lengthではダメなのでしょうか?
Twoshi

2021/01/16 02:48 編集

ご質問いただきありがとうございます! IDの重複を防ぐため、上記のような記述といたしました。 現在のソースはIDを登録時に生成するようにしています。 例えば タスクを登録し、IDが[1, 2, 3] あったとします。 途中で2を削除した場合、[1, 3] のIDが残ります。 そこにタスクを追加した場合、それぞれ以下となります。 1.const oldId = this.todos.length; の場合、length = 2 となるためIDが[1, 3, 3] 2.const oldId = this.todos.length ? this.todos[this.todos.length - 1].id : 0; の場合、  配列の最後のタスクのID = 3を取得するためIDが[1, 3, 4]となります。 そのため、2のようなIDの重複を防ぐ記述といたしました。 わかりにくい説明かもしれませんが、よろしくお願いいたします。 ご不明点あればお気軽にご質問いただければと思います。
F_Yohei

2021/01/16 03:05

ありがとうございます????‍♂️ とてもわかりやすいです。 例えばなのですが、削除ボタンを押した時にIDの番号が振り直される処理も今の状態から可能でしょうか?
Twoshi

2021/01/16 04:30

はい、可能です! その場合、以下の処理は不要になります。 const oldId = this.todos.length ? this.todos[this.todos.length - 1].id : 0; 回答のソースを修正いたします。
F_Yohei

2021/01/16 06:23

すごいです!! ありがとうございます????‍♂️ 削除ボタンをクリック時に、配列からオブジェクトを1つ削除した後forEachで配列の中身をひとつずつ回しidを書き換えることができるんですね!! forEachのなかでtodos配列にpushするのかと思っていたのですが、それをしなくてもidが振り直されるのが不思議だなと思いました???? どのような原理で振り直しされてるのか、もしよければ教えていただけますでしょうか? 何度も何度も申し訳ないです????‍♂️
Twoshi

2021/01/16 06:59

ご質問いただきありがとうございます! forEachは配列の要素を一つずつ取り出し参照しているだけです。 そのため、参照している値を書き換えれば値が変わります。 F_Yohei様も元々同じことをされています。 changeState()関数で記述されていた以下の箇所です。 > this.todos[id].state = "完了"; こちらもthis.todosの一つの要素を参照され参照された要素のstateに"完了"を上書きされています。 今回のforEachでは 配列をループさせ、一つずつ要素を取り出しidを上書きしています。 ご参考になれば、幸いです^^
F_Yohei

2021/01/16 09:06

かなりわかりやすいです???? オブジェクトの中のプロパティの値はロックされていないので、書き換えが可能でしたね!! 納得しました。 何度もありがとうございます????‍♂️ ようやく完成しました????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問