自動見積フォーム (Vue.jsを使って)

下記の教本を参考に自動見積フォームを作りました。こちらです。興味のある方はチャレンジしてみてください。尚、フォームのデザインにはCSSフレームワークのBootstrapbootstrap@5.0.2を使用しています。

HTML

<div id=”app”>

        <div class=”container bg-dark text-white p-5″>

            <h2 class=”text-center border-bottom border-white pb-3 mb-5″>

                自動見積フォーム

            </h2>

            <form>

                <div class=”form-group row”>

                    <label class=”col-md-3 col-form-label pt-0″>制作したいムービ

                        <span class=”badge bg-danger”>必須</span>

                    </label>

                <div class=”col-md-9″>

                    <div class=”row”>

                        <!– ムービーの種類 –>

                        <!– 余興ムービー –>

                        <div class=”col-md-5″>

                            <div class=”form-check form-check-inline”>

                                <input class=”form-check-input” type=”radio” name=”movie_type” id=”type1″ value=”余興ムービー” v-model=”movieType“>

                                <label class=”form-check-label” for=”type1″>余興ムービー</label>

                            </div>

                        </div>

                            <!– サプライズムービー –>

                            <div class=”col-md-5″>

                            <div class=”form-check form-check-inline”>

                                <input class=”form-check-input” type=”radio” name=”movie_type” id=”type2″ value=”サプライズムービー” v-model=”movieType“>

                                <label class=”form-check-label” for=”type2″>サプライズムービー</label>

                            </div>

                        </div>

                        <!– 生い立ちムービー –>

                        <div class=”col-md-5″>

                            <div class=”form-check form-check-inline”>

                                <input class=”form-check-input” type=”radio” name=”movie_type” id=”type3″ value=”生い立ちムービー” v-model=”movieType”>

                                <label class=”form-check-label” for=”type2″>生い立ちムービー</label>

                            </div>

                        </div>

                        <!– オープニングムービー –>

                        <div class=”col-md-5″>

                            <div class=”form-check form-check-inline”>

                                <input class=”form-check-input” type=”radio” name=”movie_type” id=”type4″ value=”オープニングムービー” v-model=”movieType“>

                                <label class=”form-check-label” for=”type3″>オープニングムービー</label>

                            </div>

                        </div>

                    </div><!–row–>

                </div><!–class=”col-md-9–>

        </div><!–form-group row–>

         <!– 挙式日 –>

         <div class=”form-group row”>

            <label class=”col-md-3 col-form-label pt-0″ for=”wedding_date”>挙式日

            <span class=”badge bg-danger”>必須</span>

        </label>

        <div class=”col-md-9″>

            <input class=”form-control” type=”date” id=”wedding_date” placeholder=”日付をお選びください” v-model=”wedding_date“>

                <small class=”form-text”>結婚式のお日にちを選択してください</small>

        </div><!–col-md-9–>

          </div><!–form-group row–>

          <!–DVD仕上がり予定–>

          <div class=”form-group row”>

            <label class=”col-md-3 col-form-label pt-0″ for=”delivery_date”>DVD仕上がり予定日

            <span class=”badge bg-danger”>必須</span>

        </label>

        <div class=”col-md-9″>

            <input class=”form-control” type=”date” id=”delivery_date” v-bind:min=”tommorow”  placeholder=”日付をお選びください” v-model=”delivery_date“>

                <small class=”form-text”>挙式日の1週間前までにDVDが必要な場合が多いため、仕上がり予定を挙式日の1週間前に設定しております。</small>

        </div><!–col-md-9–>

          </div><!–form-group row–>

          <!– 小計;基本料金 –>

          <div class=”form-group row”>

            <label class=”col-md-3 col-form-label pt-0″ >基本料金(税込)</label>

        <div class=”col-md-9″>

           <input type=”text” class=”form-control text-right” id=”sum_base” v-bind:value=” taxBasePrice | number_format” readonly>

        </div><!–col-md-9–>

          </div><!–form-group row–>

          <!– オプションメニュー –>

          <div class=”form-group row”>

            <label class=”col-md-3 col-form-label pt-0″>オプションメニュー

                <span class=”badge bg-info”>任意</span>

            </label>

            <!– BGM手配 –>

            <div class=”col-md-9″>

                <div class=”form-check mb-3″>

                    <input class=”form-check-input” type=”checkbox” id=”opt1″ v-model=”opt1_use”>

                    <label class=”form-check-label” for=”opt1″>BGM手配 + {{taxOpt1 | number_format }}   円</label>

                    <small class=”form-text”>当社で曲を手配する場合は、1曲あたり{{taxOpt1 | number_format }}   円(税込み)がかかります。</small>

                </div>

            <!– 撮影手配 –>

            <div class=”form-check mb-3″>

                <input class=”form-check-input” type=”checkbox” id=”opt2″ v-model=”opt2_use“>

                <label class=”form-check-label” for=”opt2″>撮影 +{{taxOpt2 | number_format }} 円</label>

                <small class=”form-text”>当社に撮影を依頼する場合の料金です(税込み)</small>

            </div>

            <!– DVF盤面印刷 –>

            <div class=”form-check mb-3″>

                <input class=”form-check-input” type=”checkbox” id=”opt3″ v-model=”opt3_use”>

                <label class=”form-check-label” for=”opt3″>DVD盤面印刷 +{{taxOpt3 | number_format }} 円</label>

                <small class=”form-text”>DVD盤面をデザインさせて頂き場合は、 円(税込み)がかかります。</small>

            </div>

            <!– 写真スキャニング –>

            <div class=”form-row mb-3 align-items-center”>

                <div class=”col-auto”>

                    <label class=”form-check-label” for=”opt4″ >写真スキャニング +{{taxOpt4 | number_format }}円</label>

                </div>

                <div class=”col-auto”>

                    <div class=”input-group”>

                        <input class=”form-control” type=”number” id=”opt4″ v-model.number=”opt4_num”  min=”0″ max=”30″>

                        <div class=”input^group-append”>

                            <label class=”input-group-text” for=”opt4″>枚</label>

                        </div>

                    </div>

                </div>

                <small class=”form-text” >プリントアウトした写真のスキャニングをご希望の方は、1枚当たり{{taxOpt4 | number_format }}円にて承ります。</small>  

            </div><!–form-row mb-3 align-items-center–>

            </div><!–col-md-9–>

          </div><!–form-group row–>

          <!– 小計、オプション料金 –>

          <div class=”form-group row”>

            <label class=”col-md-3 col-form-label pt-0″>オプション料金(税込)</label>

            <div class=”col-md-9″>

                <div class=”input-group”>

                    <input type=”text” class=”form-control text-right” id=”sum_opt” v-bind:value=”taxOptPrice | number_format” readonly>

                    <div class=”input-group-append”>

                        <label class=”input-group-text”>円</label>

                    </div>

                </div><!–input-group–>

            </div><!–col-md-9–>

          </div><!–form-group row–>

          <!– 合計:基本料金+オプション料金 –>

          <div class=”form-group row”>

            <label class=”col-md-3 col-form-label pt-0″>合計(税込)</label>

            <div class=”col-md-9″>

                <div class=”input-group”>

                    <input type=”text” class=”form-control text-right ” id=”sum_total” v-bind:value=”taxedTotalPrice | number_format” readonly>

                    <div class=”input-group-append”>

                        <label class=”input-group-text “>円</label>

                    </div>

                </div><!–input-group–>

            </div><!–col-md-9–>

          </div><!–form-group row–>

            </form>

        </div><!–container–>

    </div><!–app–>

Vue.js

Vue.filter(‘number_format’, function(val){
            return val.toLocaleString();
        })
数値を通貨書式「#,###,###」に変換するフィルター
var app =new Vue({
        el:’#app’,
        data:{
 taxrate:0.1, 消費税率
 movieType:’余興ムービー’,  製作したいムービー
basePrice: 30000, 基本料金(税抜き)
addPrice1:5000,
            addPrice2:10000,
            addPrice3:15000,
            addPrice4:20000,
            addPrice5:40000,
            addPrice6:45000,
            addPrice7:50000,
割増料金 
DVD仕上がり予定日が短納期の場合の割増料金
一か月未満:5,000円、3週間未満:10000円、2週間未満:15,000円、1週間未満:20,000円、3日後、40,000円、2日後:45,000円、翌日:50,000円
optPrice:0,オプション料金
totalPrice:0,合計金額(税抜き)
 wedding_date:”, 挙式日
 delivery_date:”, DVD仕上がり予定日
opt1_use:false,  
opt1_price: 5000,
オプション「BGM」
opt2_use:false,  
opt2_price:5000,
オプション「撮影」
opt3_use:false,  
opt3_price:5000,
 オプション「DVD盤面印刷」
opt4_num:false,  
opt4_price:500,
 オプション「写真スキャニング」
 tommorow: null
        }, //data
 翌日の日付
 methods:{
incTax: function(unTaxed){
                return Math.floor(unTaxed * (1 + this.taxrate));
            },
 税抜き金額を税込みに変換するメソッド
getDateDiff: function(dateString1, dateString2){
var date1 = new Date(dateString1);
 var date2 = new Date(dateString2)
 var msDiff = date1.getTime() – date2.getTime();
return Math.ceil(msDiff / (1000 * 60 * 60 * 24));
 },
 日付の差を求めるメソッド
 日付を表す文字列から日付オブジェクトを生成
2つの日付の差分(ミリ秒)を計算
求めた差分を日付に変換
 formatDate: function(dt){
 var y = dt.getFullYear();
var m = (’00’ + (dt.getMonth()+ 1)).slice(-2);
 var d = (’00’+dt.getDate()).slice(-2);
return (y + ‘-‘ + m + ‘-‘ + d);
  }
},//methods
日付をYYYY-MM-DDの書式で返すメソッド
computed: {
taxOpt1: function(){
return this.incTax(this.opt1_price);
   },
 オプション「BGM手配」の税込み金額を返す算出プロパティ
taxOpt2: function(){
 return this.incTax(this.opt2_price);
  },
 オプション「撮影」の税込み金額を返す算出プロパティ
taxOpt3: function(){
return this.incTax(this.opt3_price);
  },
オプション「DVD盤面印刷」の税込み金額を返す算出プロパティ
taxOpt4: function(){
return this.incTax(this.opt4_price);
  },
オプション「写真スキャニング」の税込み金額を返す算出プロパティ
 taxBasePrice: function(){ 基本料金(税込み)を返す算出プロパティ
 var addPrice = 0; 割増料金
var dateDiff = this.getDateDiff(this.delivery_date,(new Date()).toLocaleString());納期までの残り日数を計算
 if(21 <=dateDiff && dateDiff < 30){
addPrice = this.addPrice1;
       }
割増料金を求める
                   // 納期1ヶ月未満の場合
else if (14 <= dateDiff && dateDiff < 21){
 addPrice = this.addPrice2;
          }
納期3週間未満の場合  
 else if (7 <= dateDiff && dateDiff < 14){
  addPrice = this.addPrice3;
          }
納期2週間未満の場合
else if (3 <= dateDiff && dateDiff < 7){
  addPrice = this.addPrice4;
       }
納期1週間未満の場合
 else if (dateDiff == 3){
  addPrice = this.addPrice5;
       }
納期が3日後の場合
else if (dateDiff == 2){
 addPrice = this.addPrice6;
         }
 納期が2日後の場合
else if (dateDiff == 1){
 addPrice = this.addPrice7;
        }
 納期が1日後の場合
  return this.incTax(this.basePrice + addPrice);
},
基本料金と割増料金を返す
 taxOptPrice: function(){ オプション料金
 var optPrice = 0;変数を設定
if(this.opt1_use) {optPrice += this.opt1_price;}BGM手配
if(this.opt2_use) {optPrice += this.opt2_price;}撮影
 if(this.opt3_use) {optPrice += this.opt3_price;} DVD盤面印刷
if(this.opt4_num == ”) {this.opt4_num = 0;}
 optPrice += this.opt4_num * this.opt4_price;
写真スキャニング
return this.incTax(optPrice);
 }, // taxOptPrice
オプション料金(税込み)を返す
taxedTotalPrice: function(){
 return (this.taxBasePrice + this.taxOptPrice)
    }
}, //computed
合計金額(税込み)を返す算出プロパティ
 基本料金とオプション料金の合計を返す
 created:function(){挙式日には本日から数えて2か月後の日付を、DVD仕上がり予定日は挙式日の1週間前の日付をそれぞれ初期値として設定するため、createdライフサイクルハックを利用します。コンポーネントのインスタンスが生成し終わり、DOMと結びつく前に設定します。
var dt = new Date();今日の日付を取得
 dt.setMonth(dt.getMonth() + 2);挙式日に2か月後の日付を設定
 this.wedding_date = this.formatDate(dt);formatDateメソッドでyyyy-mm-ddの書式にする
 dt.setDate(dt.getDate() – 7);DVD仕上がり予定日に、挙式日の1週間前の日付を設定
 this.delivery_date = this.formatDate(dt);formatDateメソッドでyyyy-mm-ddの書式にする
 dt = new Date();
   dt.setDate(dt.getDate() + 1);
  this.tommorow = this.formatDate(dt)
        } //created
DVD仕上がり予定日に翌日以降しか入力できないようにする
}) //app

この本を参考に学び、完成させることができました。しかし、プログラミング初心者の私が詳しく解説することは、おこがましく、難しく出来ません(ToT) その点、この本では丁寧な解説が載っていますので、解説とともにコードを書き、完成させればより深く学ぶことができます(^.^) 身に付けて消えないスキルがこの値段。買っておいてよかったです。

わからないことはプロフェッショナルから学ぶのが一番

キャリアアップに必要なスキルを取得しよう。

オンラインで受講ができるスクールですので、全国どこからでも。