1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
   | <template>     <div>         <form @submit.prevent="onSubmit">             <fieldset>                 <legend class="text-center">GuestBook</legend>
                  <div class="form-group">                     <label for="name">名字</label>                     <div>                         <input type="text"                             minlength="3"                             maxlength="30"                             id="name"                             :class="[                                 'form-control', {                                     'is-valid': nameIsValid,                                     'is-invalid': nameIsInvalid                                 }                             ]"                             v-model="signature.name"                             required>                         <span class="invalid-feedback" v-if="nameIsInvalid">{{ errors.name[0] }}</span>                     </div>                 </div>
                  <div class="form-group">                     <label for="email">信箱</label>                     <div>                         <input type="email"                             minlength="3"                             maxlength="30"                             id="email"                             :class="[                                 'form-control', {                                     'is-valid': emailIsValid,                                     'is-invalid': emailIsInvalid                                 }                             ]"                             v-model="signature.email"                             required>                         <span class="invalid-feedback" v-if="emailIsInvalid">{{ errors.email[0] }}</span>                     </div>                 </div>
                  <div class="form-group">                     <label for="content">訊息</label>                     <div>                         <textarea id="content"                             :class="[                                 'form-control', {                                     'is-valid': contentIsValid,                                     'is-invalid': contentIsInvalid                                 }                             ]"                             v-model="signature.content"                             required></textarea>                         <span class="invalid-feedback" v-if="contentIsInvalid">{{ errors.content[0] }}</span>                     </div>                 </div>
                  <div class="form-group">                     <div class="text-center">                         <button type="submit" class="btn btn-primary">Submit</button>                     </div>                 </div>             </fieldset>         </form>
          <div class="alert alert-success alert-dismissible fade show" role="alert" v-if="saved">             <strong>成功!表單已送出!</strong>             <button type="button" class="close" data-dismiss="alert" aria-label="Close">                 <span aria-hidden="true">×</span>             </button>         </div>     </div> </template>
  <script>     export default {         data() {             return {                 url: '/api/signatures',                 signature: {                     name: '',                     email: '',                     content: ''                 },                 validation: {                     name: /^[a-zA-Z0-9\u4e00-\u9fa5]{3,30}$/,                     email: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$/,                     content: /^.{3,30}$/                 },                 saved: false,                 errors: []             };         },         computed: {             nameIsValid: function() {                 return this.validation.name.test(this.signature.name.trim());             },             nameIsInvalid: function() {                 return (!this.validation.name.test(this.signature.name.trim()) && this.errors.name);             },             emailIsValid: function() {                 return this.validation.email.test(this.signature.email.trim());             },             emailIsInvalid: function() {                 return (!this.validation.email.test(this.signature.email.trim()) && this.errors.email);             },             contentIsValid: function() {                 return this.validation.content.test(this.signature.content.trim());             },             contentIsInvalid: function() {                 return (!this.validation.content.test(this.signature.content.trim()) && this.errors.content);             }         },         methods: {             onSubmit() {                 this.saved = false;                 axios.post(this.url, this.signature)                     .then(({data}) => {                         this.success()                     })                     .catch(({response}) => {                         this.error(response.data)                     });             },             success() {                 this.saved = true;                 this.reset();             },             error(data) {                 this.errors = data;             },             reset() {                 this.errors = [];                 this.signature = {                     name: '',                     email: '',                     content: ''                 };             }         }     } </script>
   |