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

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

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

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

JavaScript

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

HTML

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

Q&A

解決済

2回答

1310閲覧

先頭のチェックボックスをチェック時、全選択するようにするとチェック対象の集計が行えなくなる

firstLast1012

総合スコア4

Vue.js

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

JavaScript

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

HTML

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

0グッド

0クリップ

投稿2021/10/20 04:06

編集2021/10/20 05:16

前提・実現したいこと

現在、下図のようにチェックをいれた明細行の金額を集計する機能を作成しています。
イメージ説明

先頭行のチェックボックスにチェックを入れたときに全選択したいのですが、
全選択をできるようにすると下図のように集計が行えなくなります。
イメージ説明

全選択の機能とチェック済みの明細の金額を集計する機能を共存したいのですが、うまく行えません。

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

ソースコード上でコメントアウトしていますが、
チェックボックスのv-modelが上手にできていないため、
機能が両方動かすことができていないのものと思います。

該当のソースコード

javascript

1<!DOCTYPE html> 2<html lang='ja'> 3<head> 4 <meta charset='UTF-8'> 5 <title>sample1</title> 6</head> 7<body> 8<div id='app'> 9 <div> 10 <h1>sample</h1> 11 <table class='table'> 12 <thead> 13 <tr> 14 <th><input type='checkbox' v-model="details.isAllSelected" @click="selectAll"></input></th> 15 <th>商品名</th> 16 <th>単価</th> 17 <th>数量</th> 18 <th>消費税率</th> 19 <th>税抜金額計</th> 20 <th>消費税額</th> 21 <th>合計金額</th> 22 </tr> 23 </thead> 24 <tbody> 25 <tr v-for='(detail,index) in details' v-bind:key='detail.id'> 26 <!-- detail.isChecked → details.isCheckedで全選択できるようになるが、computedのチェック済みのみを計算する機能が働かなくなる 27 <th><input type='checkbox' v-model='detail.isChecked'></input></th> 28 --> 29 <th><input type='checkbox' v-model='details.isChecked'></input></th> 30 <th><input type='text'></th> 31 <th><input type='number' v-model.number='detail.unitPrice' style="text-align:right"></th> 32 <th><input type='number' v-model.number='detail.num' style="text-align:right" ></th> 33 <th><input type='number' v-model.number='detail.rate' style="text-align:right"></th> 34 <th>{{ (detail.unitPrice * detail.num).toLocaleString()}} </th> 35 <th>{{ (detail.unitPrice * detail.num * detail.rate/100).toLocaleString()}} </th> 36 <th>{{ ((detail.unitPrice * detail.num ) + (detail.unitPrice * detail.num * detail.rate/100)).toLocaleString() }} </th> 37 <th><button @click='deleteRow(index)'>削除</button></th> 38 </tr> 39 </tbody> 40 </table> 41 <button @click='addRow'>行を追加</button> 42 <p>税抜金額計{{ totalPrice.toLocaleString() }}</p> 43 <p>消費税額計{{ totalTax.toLocaleString() }}</p> 44 <p>税込金額計{{ totalPriceWithTax.toLocaleString() }}</p> 45 </div> 46</div> 47<script src='https://unpkg.com/vue'></script> 48</body> 49 50<script> 51 let app = new Vue({ 52 el: '#app', 53 data() { 54 return{ 55 details:[{ 56 isAllSelected:false, 57 isChecked:'', 58 unitPrice:'', 59 num:'', 60 rate:10 61 }] 62 } 63 }, 64 computed:{ 65 //税抜金額計 66 totalPrice:function(){ 67 return this.details.filter(x => x.isChecked).reduce((sum, detail) => sum + detail.unitPrice * detail.num, 0); 68 }, 69 //消費税計 70 totalTax:function(){ 71 return this.details.filter(x => x.isChecked).reduce((sum, detail) => sum + detail.unitPrice * detail.num * detail.rate/100, 0); 72 }, 73 //税込額計 74 totalPriceWithTax:function(){ 75 return this.details.filter(x => x.isChecked).reduce((sum, detail) => sum + (detail.unitPrice * detail.num ) + (detail.unitPrice * detail.num * detail.rate/100), 0); 76 } 77 }, 78 methods:{ 79 //全選択 80 selectAll () { 81 if (this.details.isAllSelected) { 82 this.details.isChecked = false 83 } 84 else { 85 this.details.isChecked = true 86 } 87 }, 88 //行追加 89 addRow:function(){ 90 this.details.push({ 91 unitPrice:'', 92 num:'', 93 rate:10 94 }) 95 }, 96 //行削除 97 deleteRow:function(index){ 98 this.details.splice(index,1) 99 } 100 } 101}) 102</script> 103 104<style> 105.table { 106 border: 1px solid #eee; 107 border-collapse: collapse; 108} 109.table th, 110.table td { 111 border: 1px solid #dedede; 112 padding: .5em; 113 text-align: center; 114} 115 116</style> 117</html>

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

Vueのバージョンは2.6.14を使用しています。

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

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

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

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

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

Lhankor_Mhy

2021/10/20 04:33

「全選択をできるようにすると下図のように集計が行えなくなります」とのことですが、ご提示のコードを試してみましたが、全選択ができませんでした。
firstLast1012

2021/10/20 05:18

大変失礼いたしました。 全選択機能を試していた時のコードを記載してしまいました。 コードを修正いたしましたので、大変恐縮ではございますがご確認いただけますと幸いです。
guest

回答2

0

ベストアンサー

各行のチェックボックスは、details配列の要素ごとにバインドすべきかと思います。
details は配列なので、details.isCheckedとしてもdetails[i].isCheckedを参照することはできません。
details.isAllSelectedも同様ですが、これについては状態がひとつあればいいので、ひとまず動くと思います。

解決方法ですが、details配列すべての要素にアクセスしてisCheckedを変更するのがいいでしょう。


セッタを使う方がスマートかも。

js

1 isAllSelected: { 2 get: function () { 3 return !this.details.some(x => !x.isChecked) 4 }, 5 set: function (bool) { 6 if (bool) { 7 this.details.forEach(x => x.isChecked = true); 8 } else { 9 this.details.forEach(x => x.isChecked = false); 10 } 11 } 12 }

算出 Setter 関数 | 算出プロパティとウォッチャ — Vue.js


コメントを受けて追記

html

1<body> 2 <div id='app'> 3 <div> 4 <h1>sample</h1> 5 <table class='table'> 6 <thead> 7 <tr> 8 <th><input type='checkbox' v-model="isAllSelected"></input></th> 9 <th>商品名</th> 10 <th>単価</th> 11 <th>数量</th> 12 <th>消費税率</th> 13 <th>税抜金額計</th> 14 <th>消費税額</th> 15 <th>合計金額</th> 16 </tr> 17 </thead> 18 <tbody> 19 <tr v-for='(detail,index) in details' v-bind:key='detail.id'> 20 <th><input type='checkbox' v-model='detail.isChecked'></input></th> 21 <th><input type='text'></th> 22 <th><input type='number' v-model.number='detail.unitPrice' style="text-align:right"></th> 23 <th><input type='number' v-model.number='detail.num' style="text-align:right"></th> 24 <th><input type='number' v-model.number='detail.rate' style="text-align:right"></th> 25 <th>{{ (detail.unitPrice * detail.num).toLocaleString()}} </th> 26 <th>{{ (detail.unitPrice * detail.num * detail.rate/100).toLocaleString()}} </th> 27 <th>{{ ((detail.unitPrice * detail.num ) + (detail.unitPrice * detail.num * 28 detail.rate/100)).toLocaleString() }} </th> 29 <th><button @click='deleteRow(index)'>削除</button></th> 30 </tr> 31 </tbody> 32 </table> 33 <button @click='addRow'>行を追加</button> 34 <p>税抜金額計{{ totalPrice.toLocaleString() }}円</p> 35 <p>消費税額計{{ totalTax.toLocaleString() }}円</p> 36 <p>税込金額計{{ totalPriceWithTax.toLocaleString() }}円</p> 37 </div> 38 </div> 39 <script src='https://unpkg.com/vue'></script> 40</body> 41 42<script> 43 let app = new Vue({ 44 el: '#app', 45 data() { 46 return { 47 details: [{ 48 isChecked: false, 49 unitPrice: '', 50 num: '', 51 rate: 10 52 }] 53 } 54 }, 55 computed: { 56 //税抜金額計 57 totalPrice: function () { 58 return this.details.filter(x => x.isChecked).reduce((sum, detail) => sum + detail.unitPrice * detail.num, 0); 59 }, 60 //消費税計 61 totalTax: function () { 62 return this.details.filter(x => x.isChecked).reduce((sum, detail) => sum + detail.unitPrice * detail.num * detail.rate / 100, 0); 63 }, 64 //税込額計 65 totalPriceWithTax: function () { 66 return this.details.filter(x => x.isChecked).reduce((sum, detail) => sum + (detail.unitPrice * detail.num) + (detail.unitPrice * detail.num * detail.rate / 100), 0); 67 }, 68 isAllSelected: { 69 get: function () { 70 return !this.details.some(x => !x.isChecked) 71 }, 72 set: function (bool) { 73 if (bool) { 74 this.details.forEach(x => x.isChecked = true); 75 } else { 76 this.details.forEach(x => x.isChecked = false); 77 } 78 } 79 } 80 }, 81 methods: { 82 //行追加 83 addRow: function () { 84 this.details.push({ 85 isChecked: false, 86 unitPrice: '', 87 num: '', 88 rate: 10 89 }) 90 }, 91 //行削除 92 deleteRow: function (index) { 93 this.details.splice(index, 1) 94 } 95 } 96 }) 97</script>

投稿2021/10/20 05:35

編集2021/10/20 07:41
Lhankor_Mhy

総合スコア36960

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

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

firstLast1012

2021/10/20 07:29

ご教示ありがとうございます。 ご記載いただいたソースをdetailsのisAllSelectedに記載しましたが、思うような挙動(チェック済みの明細行の金額を集計)ができませんでした。 私の勉強不足もあり、先にご教示いただいた、 各行のチェックボックスを、details配列の要素ごとにバインドする方法も、具体的なやり方がわからないため、ネットや書籍で方法を探しつつ試していきます。
Lhankor_Mhy

2021/10/20 07:34

> detailsのisAllSelectedに記載しました いえ、computedプロパティです。 提示いたしましたリンク先を見るとわかりやすいと思います。
firstLast1012

2021/10/20 08:41

ご丁寧にありがとうございます。思った通りの挙動になりました。 記載いただいたソースを確認しつつ、自分のソースのどこがよくなかったを勉強していきます。 ありがとうございました。
FKM

2021/10/20 08:56

算出プロパティの活用法、こちらも参考になりました。 ただ、自分の方もそうなんですが、ソース読み込み直後にデータを追加して全選択、追加分だけのチェックボックスを外すと追加外した分の集計が減算されないという現象が起きますけど、これの解決法がありますでしょうか。
Lhankor_Mhy

2021/10/20 09:14 編集

> FKMさん たぶん、ここじゃないでしょうか。 addRow: function () { this.details.push({ isChecked: false, // これが必要かもです。 私も十分に理解していないのですが、値の更新があるまでゲッタセッタがうまくセットされないようです。
FKM

2021/10/20 09:12

ありがとうございます。そこで間違いないです。 そこも追記されてたんですね。
guest

0

全選択のチェックフラグと商品用の集計用フラグを同じに考えず、全選択は全選択のフラグを制御して、trueの場合はオブジェクトのisChekcedも全部true、そうでない場合は全部falseとすれば、後は算出プロパティによって自動集計してくれます。

vue

1<th><input type='checkbox' @click="selectAll(isAllSelected)"></input></th> 2//中略 3 return{ 4   isAllSelected: false, 5 details:[{ 6 isChecked:'', 7 unitPrice:'', 8 num:'', 9 rate:10 10 }] 11 } 12//中略 13 methods:{ 14 //全選択 15 selectAll (chk_flg) { 16 let details = this.details 17 if (chk_flg === false) { 18 chk_flg = true 19 details.map((d)=>{d.isChecked = true }) //全部true 20 } 21 else { 22 chk_flg = false 23 details.map((d)=>{d.isChecked = false }) //全部false 24 } 25   this.isAllSelected = chk_flg 26 },

isCheckedの取得方法はもっと簡潔な方法がありそうです。

投稿2021/10/20 05:54

FKM

総合スコア3647

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

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

firstLast1012

2021/10/20 07:01

ご教示ありがとうございます。 ご記載いただいたソースを試したところ、先頭行チェック時(全選択時)の集計が行えましたが、 明細行の個別チェックができなくなってしまっていた(チェックのオン/オフ時、全ての明細行のチェックが連動してしまう)ので、改善できることがあるか、確認してみます。
FKM

2021/10/20 07:47

こっちはちゃんと動いてますがdetailsからisAllSelectedを外してますか?
firstLast1012

2021/10/20 08:43

改めて動作のご確認いただきありがとうございます。 私の方のソースをもう一度確認いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問