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

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

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

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

JavaScript

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

Q&A

解決済

2回答

2811閲覧

Vue.js ToDoリスト タスクの表示の切り替え

Junkichi89

総合スコア8

Vue.js

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

JavaScript

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

0グッド

1クリップ

投稿2020/07/22 22:21

編集2020/07/23 20:55

ラジオボタンの表示ごとにタスクの表示を切り替えをしたい Vue.js

前提・実現したいこと

Vue.jsでToDoリストを作成しています。
ラジオをボタンの選択を切り替えた際に表示も変更するようにしたいです。

<ここに質問の内容を詳しく書いてください。>

Vue.jsでTodoリストを作成しているのですが、
ラジオボタンを変更したあと、うまく作動しなくなってしまいます。
ラジオボタンを切り替えても、どのタスクを選択しても、完了、作業中が切り替わり。
完了のラジオボタンを選択している場合は、完了と表示されているタスクのみ表示され、
作業中のラジオボタンを選択している際は、作業中と表示されているタスクのみ表示したいです。
また、完了中に新しいタスクを入力しても表示されずに、タスクとしては、追加されているようにしたいです。

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

ラジオボタンを変更したあと、うまく作動しなくなってしまいます。
「すべて」のラジオを選択しているときは、作業中と完了のボタンは、うまく作動している。
しかし、作業中や完了のラジオを選択しているとインデックスの逆から押さなければ、
全ての項目を正しく切り替えることができない。

例)
○すべて ●作業中 ○完了
1.A 作業中
2.B 作業中
3.C 作業中
→A→B→Cと押すとAが完了に切り替わったあと、Bを完了に変えようとすると再び、作業中のAが表示されてしまう。
しかし、CからB、Aと押すと問題なく変更される。

エラーメッセージ

該当のソースコード

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <title>ToDo List Vue-version</title> 7 8 <link rel="stylesheet" href="css/styles.css"> 9</head> 10 11<body> 12 <h2>ToDoリスト</h2> 13 <div id="app"> 14 <label><input type="radio" name="list" value="all" v-model="filter">すべて</label> 15 <label><input type="radio" name="list" value="active" v-model="filter">作業中</label> 16 <label><input type="radio" name="list" value="completed" v-model="filter">完了</label> 17 <p>ID コメント 状態</p> 18 <table> 19 <tr v-for="(todo, index) in filteredTodos"> 20 <td>{{ index }}</td> 21 <td>{{ todo.title }}</td> 22 <td><button @click="statusChange(index)"> 23 <span>{{ todo.statusBtn }}</span> 24 </button></td> 25 <td><button @click="deleteTask(index)">{{ todo.delBtn }}</button></td> 26 </tr> 27 </table> 28 <h2>新規タスクの追加</h2> 29 <form @submit.prevent="addTask"> 30 <input type="text" v-model="newTask"> 31 <input type="submit" value="追加" class="button"> 32 </form> 33 </div> 34 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 35 <script> 36 'use strict'; 37 38 new Vue({ 39 el: '#app', 40 data: { 41 statusBtn: '', newTask: '', todos: [], filter: 'all' 42 }, 43 computed: { 44 filteredTodos() { 45 if (this.filter === 'all') { 46 return this.todos 47 } else if (this.filter === 'completed') { 48 return this.todos.filter((todo) => { 49 return todo.statusBtn === '完了' 50 }) 51 } else if (this.filter === 'active') { 52 return this.todos.filter((todo) => { 53 return todo.statusBtn === '作業中' 54 }) 55 } 56 } 57 }, 58 methods: { 59 addTask: function () { 60 let item = { 61 title: this.newTask, statusBtn: '作業中', delBtn: '削除' 62 } 63 this.todos.push(item); 64 this.newTask = ''; 65 }, 66 statusChange: function (data) { 67 if (this.todos[data].statusBtn === '作業中') { 68 this.todos[data].statusBtn = '完了' 69 } else { 70 this.todos[data].statusBtn = '作業中' 71 } 72 }, 73 deleteTask: function (index) { 74 this.todos.splice(index, 1); 75 } 76 } 77 }); 78 </script> 79</body> 80 81</html>

試したこと

ここに問題に対して試したことを記載してください。
https://cr-vue.mio3io.com/tutorials/todo.html#step2-%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8-api-%E3%81%AE%E4%BD%BF%E7%94%A8

上記のサイトのコードを参考にして、ラジオボタンを含め、フィルター部分から修正しようとしたのですが、
下記のようなエラーが出てしまいました。そして、dataの中にstate:0を追加したのですが、改善されませんでした。

**********
[Vue warn]: Property or method "item" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

[Vue warn]: Error in render: "TypeError: Cannot read property 'state' of undefined"

(found in <Root>)
・・・・

**********

HTMLVue

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <title>ToDo List Vue-version</title> 7 8 <link rel="stylesheet" href="css/styles.css"> 9</head> 10 11<body> 12 <h2>ToDoリスト</h2> 13 <div id="app"> 14 <label v-for="label in options"><input type="radio" v-bind:value="label.value" v-model="current" 15 name="label">{{ label.label }}</label> 16 <p>ID コメント 状態</p> 17 <table> 18 <tr v-for="(todo, index) in filteredTodos" v-bind:key="index"> 19 <td>{{ index }}</td> 20 <td>{{ todo.title }}</td> 21 <td><button @click="statusChange(item)">{{ labels[item.state] }}</button></td> 22 <td><button @click="deleteTask(index)">削除</button></td> 23 </tr> 24 </table> 25 <h2>新規タスクの追加</h2> 26 <form @submit.prevent="addTask"> 27 <input type="text" v-model="newTask"> 28 <input type="submit" value="追加" class="button"> 29 </form> 30 </div> 31 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 32 <script> 33 'use strict'; 34 35 new Vue({ 36 el: '#app', 37 data: { 38 options: [ 39 { value: -1, label: 'すべて' }, 40 { value: 0, label: '作業中' }, 41 { value: 1, label: '完了' } 42 ], 43 newTask: '', 44 todos: [], 45 current: -1, 46 }, 47 computed: { 48 filteredTodos() { 49 return this.todos.filter(function (todo) { 50 return this.current < 0 ? true : this.current === todo.state 51 }, this) 52 }, 53 labels() { 54 return this.options.reduce(function (a, b) { 55 return Object.assign(a, { [b.value]: b.label }) 56 }, {}) 57 } 58 }, 59 methods: { 60 addTask: function () { 61 let item = { 62 title: this.newTask, 63 state: 0 64 } 65 this.todos.push(item); 66 this.newTask = ''; 67 }, 68 statusChange: function (item) { 69 item.state = item.state ? 0 : 1 70 }, 71 deleteTask: function (index) { 72 this.todos.splice(index, 1); 73 } 74 } 75 }); 76 </script> 77</body> 78 79</html>

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

ここにより詳細な情報を記載してください。
残りタスクが1つになった後、削除ボタンが作動しなってしまいました。
削除ボタンを押すとすべてのタスクを削除できるようにし、連番も再び初めからふりなおすにしたいのですが、
これは、新たに質問をした方が良いでしょうか?

HTMLVue

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <title>ToDo List Vue-version</title> 7 8 <link rel="stylesheet" href="css/styles.css"> 9</head> 10 11<body> 12 <h2>ToDoリスト</h2> 13 <div id="app"> 14 <label><input type="radio" name="list" value="all" v-model="filter">すべて</label> 15 <label><input type="radio" name="list" value="active" v-model="filter">作業中</label> 16 <label><input type="radio" name="list" value="completed" v-model="filter">完了</label> 17 <p>ID コメント 状態</p> 18 19 <table> 20 <tr v-for="todo in filteredTodos"> 21 <td>{{ todo.id }}</td> 22 <td>{{ todo.title }}</td> 23 <td><button @click="statusChange(todo.id)">{{ todo.statusBtn }}</button></td> 24 <td><button @click="deleteTask(todo.id)">{{ todo.delBtn }}</button></td> 25 </tr> 26 </table> 27 <h2>新規タスクの追加</h2> 28 <form @submit.prevent="addTask"> 29 <input type="text" v-model="newTask"> 30 <input type="submit" value="追加" class="button"> 31 </form> 32 </div> 33 34 35 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 36 <script> 37 'use strict'; 38 39 new Vue({ 40 el: '#app', 41 data: { 42 id: 0, statusBtn: '', newTask: '', todos: [], filter: 'all' 43 }, 44 computed: { 45 filteredTodos() { 46 if (this.filter === 'all') { 47 return this.todos 48 } else if (this.filter === 'completed') { 49 return this.todos.filter((todo) => { 50 return todo.statusBtn === '完了' 51 }) 52 } else if (this.filter === 'active') { 53 return this.todos.filter((todo) => { 54 return todo.statusBtn === '作業中' 55 }) 56 } 57 } 58 }, 59 methods: { 60 addTask: function () { 61 let item = { 62 id: this.id++, title: this.newTask, statusBtn: '作業中', delBtn: '削除' 63 } 64 this.todos.push(item); 65 this.newTask = ''; 66 }, 67 statusChange: function (id) { 68 for (let todo of this.todos) { 69 if (todo.id === id) { 70 if (todo.statusBtn === '作業中') { 71 return todo.statusBtn = '完了' 72 } else { 73 return todo.statusBtn = '作業中' 74 } 75 break 76 } 77 } 78 }, 79 deleteTask: function (id) { 80 for (let todo of this.todos) { 81 if (todo.id === id) { 82 this.todos.splice(todo.id, 1); 83 break 84 } 85 } 86 } 87 } 88 }); 89 </script> 90</body> 91 92</html>

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

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

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

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

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

guest

回答2

0

自己解決

削除ボタンの実装ですが、
こちらのサイトを参考に修正できました。
STEP10 状態の変更と削除の処理
まだ、連番の動きが期待通りになっていませんが、今回の質問の内容は解決しましたので、解決済とし、
新たに質問を挙げさせていただきます。
回答ありがとうございました。

HTMLVue

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <title>ToDo List Vue-version</title> 7 8 <link rel="stylesheet" href="css/styles.css"> 9</head> 10 11<body> 12 <h2>ToDoリスト</h2> 13 <div id="app"> 14 <label><input type="radio" name="list" value="all" v-model="filter">すべて</label> 15 <label><input type="radio" name="list" value="active" v-model="filter">作業中</label> 16 <label><input type="radio" name="list" value="completed" v-model="filter">完了</label> 17 <p>ID コメント 状態</p> 18 19 <table> 20 <tr v-for="(todo in filteredTodos"> 21 <td>{{ todo.id }}</td> 22 <td>{{ todo.title }}</td> 23 <td><button @click="statusChange(todo.id)">{{ todo.statusBtn }}</button></td> 24 <td><button @click="deleteTask(todo.id)">{{ todo.delBtn }}</button></td> 25 </tr> 26 </table> 27 <h2>新規タスクの追加</h2> 28 <form @submit.prevent="addTask"> 29 <input type="text" v-model="newTask"> 30 <input type="submit" value="追加" class="button"> 31 </form> 32 </div> 33 34 35 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 36 <script> 37 'use strict'; 38 39 new Vue({ 40 el: '#app', 41 data: { 42 id: 0, statusBtn: '', newTask: '', todos: [], filter: 'all' 43 }, 44 computed: { 45 filteredTodos() { 46 if (this.filter === 'all') { 47 return this.todos 48 } else if (this.filter === 'completed') { 49 return this.todos.filter((todo) => { 50 return todo.statusBtn === '完了' 51 }) 52 } else if (this.filter === 'active') { 53 return this.todos.filter((todo) => { 54 return todo.statusBtn === '作業中' 55 }) 56 } 57 } 58 }, 59 methods: { 60 addTask: function () { 61 let item = { 62 id: this.id++, title: this.newTask, statusBtn: '作業中', delBtn: '削除' 63 } 64 this.todos.push(item); 65 this.newTask = ''; 66 }, 67 statusChange: function (id) { 68 for (let todo of this.todos) { 69 if (todo.id === id) { 70 if (todo.statusBtn === '作業中') { 71 return todo.statusBtn = '完了' 72 } else { 73 return todo.statusBtn = '作業中' 74 } 75 break 76 } 77 } 78 }, 79 deleteTask: function (smt) { 80 let index = this.todos.indexOf(smt) 81 this.todos.splice(index, 1); 82 } 83 } 84 }); 85 </script> 86</body> 87 88</html>

投稿2020/07/24 00:12

Junkichi89

総合スコア8

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

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

0

v-forのindexを利用してtodosオブジェクトに対して操作している事が原因です。
indexの値はボタンを押すたびに変化するので期待する動作にはなりません。

todosオブジェクトの中に一意となるidパラメータを作成する事で解決するサンプルプログラムを以下に貼り付けます。

<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ToDo List Vue-version</title> <link rel="stylesheet" href="css/styles.css"> </head> <body> <h2>ToDoリスト</h2> <div id="app"> <label><input type="radio" name="list" value="all" v-model="filter">すべて</label> <label><input type="radio" name="list" value="active" v-model="filter">作業中</label> <label><input type="radio" name="list" value="completed" v-model="filter">完了</label> <p>ID コメント 状態</p> <table> <tr v-for="todo in filteredTodos"> <td>{{ todo.id }}</td> <td>{{ todo.title }}</td> <td><button @click="statusChange(todo.id)"> <span>{{ todo.statusBtn }}</span> </button></td> <td><button @click="deleteTask(todo.id)">{{ todo.delBtn }}</button></td> </tr> </table> <h2>新規タスクの追加</h2> <form @submit.prevent="addTask"> <input type="text" v-model="newTask"> <input type="submit" value="追加" class="button"> </form> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> 'use strict'; new Vue({ el: '#app', data: { id: 0, statusBtn: '', newTask: '', todos: [], filter: 'all' }, computed: { filteredTodos() { if (this.filter === 'all') { return this.todos } else if (this.filter === 'completed') { return this.todos.filter((todo) => { return todo.statusBtn === '完了' }) } else if (this.filter === 'active') { return this.todos.filter((todo) => { return todo.statusBtn === '作業中' }) } } }, methods: { addTask: function () { let item = { id: this.id++, title: this.newTask, statusBtn: '作業中', delBtn: '削除' } this.todos.push(item); this.newTask = ''; }, statusChange: function (id) { for (let todo of this.todos) { if (todo.id === id) { if (todo.statusBtn === '作業中') { todo.statusBtn = '完了' } else { todo.statusBtn = '作業中' } break } } }, deleteTask: function (id) { for (let todo of this.todos) { if (todo.id === id) { todo.splice(index, 1); break } } } } }); </script> </body> </html>

diff
イメージ説明

投稿2020/07/22 23:25

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Junkichi89

2020/07/23 20:58

回答ありがとうございました。 v-forのindexとtodosのオブジェクトの関連が問題だと指摘いただき、ありがとうございました。 サンプルコードも参考にさせていただきました。 しかし、削除ボタンが上手く作動させれなくなったの追記させていただきました。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問