Bài viết này mình sẽ biên tập các vấn đề liên quan tới vue js
– lưu ý quasar phải include ở footer (nếu không sẽ gây ra lỗi)
-Function phải đặt trong input không đặt trong label
đặt sai
1 2 |
<input :checked = "item.selected" type="checkbox" :id="item.id" :value="item.id" /> <label @click="selectLeagueItem(index)" :for="item.id" style="cursor: pointer;" >{{item.name}}</label> |
đặt đúng phải là
1 2 |
<input @click="selectLeagueItem(index)" :checked = "item.selected" type="checkbox" :id="item.id" :value="item.id" /> <label :for="item.id" style="cursor: pointer;" >{{item.name}}</label> |
Trong jquery chúng ta có phương thức là $(‘.abc’).trigger(‘click’). vậy trong vue js thì sao
Chúng ta sẽ sử dụng ref trong button
1 |
<button class="custom-btn" @click="sendToAPI" v-html="sendToAPIText" ref="btnSendToAPI" > |
Sau đó tại nơi muốn trigger
1 |
this.$refs.btnSendToAPI.click() |
https://github.com/nguyentantung/chili-scripts-css/tree/master
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 |
add_action( 'admin_print_styles-' . $settings, array($this, 'cssAdmin' ) ); add_action( 'admin_print_scripts-' . $settings, array($this, 'scriptsAdmin' ) ); function cssAdmin(){ wp_register_style( 'roboto', 'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons', array(), time(), false ); wp_register_style( 'quasar-1.15.7', CHECKSTOCKSCODE_ASSETS_URL.'[email protected]/quasar.min.css', array(), time(), false ); wp_register_style( 'sweetalert2', CHECKSTOCKSCODE_ASSETS_URL.'sweetalert2/sweetalert2.min.css', array(), time(), false ); wp_register_style( 'select2', CHECKSTOCKSCODE_ASSETS_URL.'select2/select2.min.css', array(), time(), false ); wp_register_style( 'font-awesome', CHECKSTOCKSCODE_ASSETS_URL.'font-awesome/font-awesome.min.css', array(), time(), false ); wp_register_style( 'vue-ctk-date-time-picker', CHECKSTOCKSCODE_ASSETS_URL.'vue-ctk-date-time-picker/vue-ctk-date-time-picker.min.css', array(), time(), false ); wp_register_style( 'manage-sites-users-general', CHECKSTOCKSCODE_ASSETS_URL.'css/general.css', array( 'roboto', 'quasar-1.15.7', 'sweetalert2', 'select2', 'font-awesome', 'vue-ctk-date-time-picker' ), time(), false ); wp_enqueue_style( 'manage-sites-users-general' ); } function scriptsAdmin(){ wp_register_script( 'check-stocks-code-vue', CHECKSTOCKSCODE_ASSETS_URL. 'js/vue.min.js', array(), time(), false ); wp_register_script( 'check-stocks-code-vue-router', CHECKSTOCKSCODE_ASSETS_URL. 'js/vue-router.js', array(), time(), false ); wp_register_script( 'check-stocks-code-axios', CHECKSTOCKSCODE_ASSETS_URL. 'js/axios.min.js', array(), time(), false ); wp_register_script( '[email protected]', CHECKSTOCKSCODE_ASSETS_URL. '[email protected]/quasar.umd.min.js', array(), time(), true ); wp_register_script( 'check-stocks-code-sweetalert2', CHECKSTOCKSCODE_ASSETS_URL. 'sweetalert2/sweetalert2.min.js', array('jquery'), time(), false ); wp_register_script( 'vue-ctk-date-time-picker', CHECKSTOCKSCODE_ASSETS_URL. 'vue-ctk-date-time-picker/vue-ctk-date-time-picker.min.js', array('jquery'), time(), false ); wp_register_script( 'check-stocks-code-select2', CHECKSTOCKSCODE_ASSETS_URL. 'select2/select2.min.js', array('jquery','check-stocks-code-vue', 'check-stocks-code-vue-router', 'check-stocks-code-axios', 'check-stocks-code-sweetalert2'), time(), false ); wp_register_script( 'check-stocks-code-init', CHECKSTOCKSCODE_COMPONENTS_URL. 'init.js', array('jquery'), time(), false ); wp_enqueue_script( 'check-stocks-code-select2' ); wp_enqueue_script( 'check-stocks-code-init' ); wp_localize_script( 'check-stocks-code-init', 'check_stocks_code_vars', array( 'ajax_url' => admin_url( 'admin-ajax.php', 'relative' ), 'files_url' => CHECKSTOCKSCODE_FILES_URL ) ); //wp_enqueue_script( 'vue-ctk-date-time-picker' ); } add_filter('script_loader_tag', array($this,'add_type_attribute') , 10, 3); function add_type_attribute($tag, $handle, $src) { // if not your script, do nothing and return original $tag if ( 'check-stocks-code-init' !== $handle ) { return $tag; } // change the script tag by adding type="module" and return it. $tag = '<script type="module" src="' . esc_url( $src ) . '"></script>'; return $tag; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function include_css_js(){ global $post; //css wp_register_style( 'healyourlife-font-awesome', HEALYOURLIFEAUTO_ASSETS_URL.'font-awesome/font-awesome.min.css', array(), time(), false ); wp_register_style( 'healyourlife-quasar', HEALYOURLIFEAUTO_ASSETS_URL.'[email protected]/quasar-fe.css', array(), time(), false ); if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'hyl_user_list') ) { wp_enqueue_style( 'healyourlife-font-awesome' ); wp_enqueue_style( 'healyourlife-quasar' ); } //js wp_register_script( 'healyourlife-vue', HEALYOURLIFEAUTO_ASSETS_URL. 'js/vue.min.js', array(), time(), false ); wp_register_script( 'healyourlife-axios', HEALYOURLIFEAUTO_ASSETS_URL. 'js/axios.min.js', array(), time(), false ); wp_register_script( 'healyourlife-quasar', HEALYOURLIFEAUTO_ASSETS_URL. '[email protected]/quasar.umd.min.js', array('jquery'), time(), false ); if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'hyl_user_list') ) { wp_enqueue_script( 'healyourlife-vue' ); wp_enqueue_script( 'healyourlife-axios' ); wp_enqueue_script( 'healyourlife-quasar' ); } } |
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 |
<div id="settings"> <div class="row q-col-gutter-md q-mb-md"> <div class="col-7"> <h1 style="font-size: 20px; font-weight: 700; margin-bottom:20px; line-height: 1;">Cài đặt</h1> <div style="margin-bottom:20px;"> <q-input outlined v-model="settings.autoDeleteSearchHistoryAfter" label="Tự động xóa lịch sử tìm kiếm sau (đơn vị: ngày)" /> </div> <div><button class="custom-btn" @click="autoDeleteSearchHistoryAfterSave" v-html="settingsText" ></button></div> </div> </div> </div> <script type="module"> const AJAX_URL = '<?php echo admin_url('admin-ajax.php'); ?>' new Vue({ el: '#settings', data: function () { return { settingsText: '<i class="fa fa-floppy-o" aria-hidden="true"></i> Lưu', settings:{ } } }, methods:{ NOTIFY(msg, type = 1){ this.$q.notify({ message: msg, color: type == 1 ? 'green' : 'red', position: 'top', timeout: 2000 }) }, buildFormData(formData, data, parentKey) { if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) { Object.keys(data).forEach(key => { this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); }); } else { const value = data == null ? '' : data; formData.append(parentKey, value); } }, jsonToFormData(data) { const formData = new FormData(); this.buildFormData(formData, data); return formData; }, autoDeleteSearchHistoryAfterSave(){ this.settingsText = '<i class="fa fa-spinner fa-spin"></i> Lưu' axios.post( AJAX_URL, this.jsonToFormData({ action: 'autoDeleteSearchHistoryAfterSave', settings: this.settings }) ).then(res => { const response = res.data this.settingsText = '<i class="fa fa-floppy-o" aria-hidden="true"></i> Lưu' this.NOTIFY("Đã lưu thành công!",1) console.log(response) }) }, loadSettings(){ axios.post( AJAX_URL, this.jsonToFormData({ action: 'loadSettings', }) ).then(res => { const response = res.data.data this.settings = response console.log(response) }) } }, watch:{ }, created(){ this.loadSettings() } }) </script> |
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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 |
const template =` <div id="search-results"> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12"> <div class="topBarButton"> <div><q-btn color="red" icon="delete" label="Xóa" @click="deleteList" /></div> <div><q-btn color="blue" @click="openModalAddNew"><i class="fa fa-plus-circle" aria-hidden="true"></i> Thêm mới</q-btn> </div> <div> <select v-model="searchData.bySelected" class="filter-bySelected" v-if="searchData.options.length > 0"> <option v-for="(item, index) in searchData.options" :key="index" :value="item.value">{{item.name}} </option> </select> </div> <div class="searchSuggestOut"> <q-input filled bottom-slots v-model="searchKeyword" @keypress="searchStocksByEnter" @click="triggerOpenSearchSuggest" label="Từ khóa" dense debounce="500"> <template v-slot:append> <q-icon name="close" @click="resetSearchKeyword" class="cursor-pointer" /> </template> </q-input> <ul :class="{searchSuggestList: true, open: openSearchSuggest}" v-if="searchSuggest.length > 0"> <li v-for="(item, index) in searchSuggest" @click="selectKeyword(index)">{{item}}</li> </ul> </div> <div style="margin-right:10px;"><button class="custom-btn" @click="searchStocks" v-html="searchStocksText" ></button></div> <div><button class="custom-btn" @click="sendToAPI" v-html="sendToAPIText" ref="btnSendToAPI" ></button></div> <div> <q-toggle v-model="autoRunAPI" label="Tự động gửi API" /> </div> </div> </div> </div> <div class="wrap-content" > <div class="q-markup-table q-table__container q-table__card q-table--horizontal-separator q-table--no-wrap"> <table class="q-table" > <thead> <th class="text-left" width="50px"><q-btn round color="primary" icon="playlist_add_check" size="sm" @click="toggleSelection" ref="btnToggleSelection"></q-btn></th> <th class="text-left" width="50px">STT</th> <th class="text-left" width="70px">Mã cổ phiếu</th> <th class="text-left" width="70px">Link</th> <th class="text-left" width="70px">Gủi API</th> <th class="text-left" width="70px"> </th> </thead> <tbody v-if="list.length > 0"> <tr v-for="(item, index) in list" :key="'stockscode' + index"> <td width="50px"><q-checkbox v-model="selection" :val="index"/></td> <td>{{index + 1}}</td> <td>{{item.stocksCode}}</td> <td> <div class="stocksCodeLink"> <a :href="item.link" target="_blank" >{{item.shortLink}}</a> </div> </td> <td> <div v-if="item.status === 0" > <i style="color: blue;" class="fa fa-question-circle" aria-hidden="true"></i> </div> <div v-else-if="item.status === 1" > <q-spinner-dots color="primary" size="2em" /> <q-tooltip :offset="[0, 8]">QSpinnerDots</q-tooltip> </div> <div v-else-if="item.status === 2" > <i style="color: green;" class="fa fa-check" aria-hidden="true"></i> </div> <div v-else-if="item.status === 3" > <i style="color: red;" class="fa fa-exclamation-circle" aria-hidden="true"></i> </div> </td> <td> <button class="custom-btn small" @click="openModalEdit(index)" ><i class="fa fa-pencil-square-o" aria-hidden="true"></i> Chỉnh sửa</button> </td> </tr> </tbody> </table> </div> </div> <div class="modal"> <q-dialog v-model="modalAddNew"> <q-card style="width: 1000px; max-width: 80vw;"> <q-card-section class="row items-center q-pb-none"> <div class="text-h6">Thêm mới</div> <q-space></q-space> <q-btn icon="close" flat round dense v-close-popup ></q-btn> </q-card-section> <q-card-section > <template> <div class="q-pa-md"> <div class="q-gutter-md" style="max-width: 1000px"> <div class="row q-col-gutter-md q-mb-md" v-for="(item, index) in dataAddNew" :key="'addNewSearchHistory' + index"> <div class="col-2"> <div><q-input square outlined v-model="item.stocksCode" :label="'Mã cổ phiếu'" /></div> </div> <div class="col-2"> <div><q-input square outlined v-model="item.searchKeyword" :label="'Từ khóa'" /></div> </div> <div class="col-7"> <div><q-input square outlined v-model="item.link" :label="'Link'" /></div> </div> <div class="col-1 addNewSearchHistoryButton"><q-btn color="blue" @click="addSearchHistoryRow()"><i class="fa fa-plus-circle" aria-hidden="true"></i></q-btn></div> </div> <div class="row q-col-gutter-md q-mb-md"> <div class="col-4"> <button class="custom-btn" @click="triggerAddNew" v-html="triggerAddNewText" ></button> </div> </div> </div> </div> </template> </q-card-section> </q-card> </q-dialog> <q-dialog v-model="modalEdit"> <q-card style="width: 800px; max-width: 80vw;"> <q-card-section class="row items-center q-pb-none"> <div class="text-h6">Chỉnh sửa</div> <q-space></q-space> <q-btn icon="close" flat round dense v-close-popup ></q-btn> </q-card-section> <q-card-section > <template> <div class="q-pa-md"> <div class="q-gutter-md" style="max-width: 800px"> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12"> <div><q-input square outlined v-model="currentStocksCode" :label="'Mã cổ phiếu'" /></div> </div> </div> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12"> <div><q-input square outlined v-model="currentLink" :label="'Link'" /></div> </div> </div> <div class="row q-col-gutter-md q-mb-md"> <div class="col-4"> <button class="custom-btn" @click="triggerEdit" v-html="triggerEditText" ></button> </div> </div> </div> </div> </template> </q-card-section> </q-card> </q-dialog> </div> </div> ` export default { data: () => ({ autoRunAPI: true, currentIndex: null, currentStocksCode:'', currentLink:'', triggerEditText: '<i class="fa fa-floppy-o" aria-hidden="true"></i> Lưu', sendToAPIText: '<i class="fa fa-paper-plane" aria-hidden="true" ></i> Gửi API', searchStocksText: '<i class="fa fa-search" aria-hidden="true"></i> Tìm kiếm', searchKeyword: '', dataAddNew:[ { stocksCode: '', searchKeyword: '', link: ''} ], triggerAddNewText: '<i class="fa fa-floppy-o" aria-hidden="true"></i> Lưu', searchData: { bySelected: 'stocksCodeAndPhrase', options: [ { value: 'stocksCodeAndPhrase', name: 'Mã cổ phiếu + Cụm từ' }, { value: 'phraseAndStocksCode', name: 'Cụm từ + Mã cổ phiếu' }, { value: 'custom', name: 'Hỗn hợp' } ] }, openSearchSuggest: false, searchSuggest:[ 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới', 'ctg + ban lãnh đạo mới' ], searchSuggestTemp:[ ], modalAddNew: false, modalEdit: false, totalRecord: null, addNewRunning: false, shopmallInformation: '', isRunning: false, list: [ ], listTemp:[ ], pagination: { page: 1, max: 1, per_page: 20 }, selection: [] }), methods: { addSearchHistoryRow(){ this.dataAddNew.push({ stocksCode: '', searchKeyword: '', link: ''}) }, triggerAddNew(){ if(this.dataAddNew[0].stocksCode.length === 0){ this.NOTIFY("Bạn chưa nhập dữ liệu!",0) return false } this.triggerAddNewText = '<i class="fa fa-spinner fa-spin"></i> Lưu' axios.post( check_stocks_code_vars.ajax_url, this.jsonToFormData({ action: 'addNewSearchStocks', dataAddNew: this.dataAddNew }) ).then(res => { const response = res.data.data this.list = response.list this.triggerAddNewText = '<i class="fa fa-floppy-o" aria-hidden="true"></i> Lưu' if(response.linkExist.length > 0){ this.NOTIFY("Các link: " + response.linkExist.toString() + " đã gửi api",0) } this.modalAddNew = false }) }, openModalAddNew(){ this.modalAddNew = true }, openModalEdit(index){ this.modalEdit = true this.currentStocksCode = this.list[index].stocksCode this.currentIndex = index this.currentLink = this.list[index].link }, triggerEdit(){ const index = this.currentIndex this.triggerEditText = '<i class="fa fa-spinner fa-spin"></i> Lưu' this.list[index].stocksCode = this.currentStocksCode this.list[index].link = this.currentLink this.list[index].shortLink = this.currentLink this.triggerEditText = '<i class="fa fa-floppy-o" aria-hidden="true"></i> Lưu' this.modalEdit = false }, deleteList(){ if(this.selection.length == 0){ this.notify('Bạn chưa chọn dữ liệu nào để xóa.', 0) return; } //console.log(this.list) this.$q.dialog({ title: 'Xác nhận', message: 'Bạn chắc chắn muốn xóa?', cancel: true, persistent: true }).onOk(() => { this.selection.map( (item, index) => { this.list.splice(item, 1) } ) this.NOTIFY("Đã xóa các kết quả được chọn",1) this.selection.splice(0, this.selection.length) }) }, async sendToAPI(){ if(this.selection.length === 0){ this.NOTIFY("Bạn chưa chọn dữ liệu!",0) return false } this.sendToAPIText = '<i class="fa fa-spinner fa-spin"></i> Gửi API' for (const item of this.selection) { const data = this.jsonToFormData({ action: 'sendToAPI', stocksItem: this.list[item] }) console.log(data) this.list[item].status = 1 await axios({ url: check_stocks_code_vars.ajax_url, method: 'post', data: data }).then((res) => { const response = res.data.data this.list[item].status = response.status console.log(response) }) .catch((err) => { console.log(err) }) } console.log(this.list) this.sendToAPIText = '<i class="fa fa-paper-plane" aria-hidden="true" ></i> Gửi API' this.NOTIFY("Đã gửi xong tất cả link đến API!",1) }, toggleSelection(){ if(this.selection.length > 0){ this.selection = [] }else{ this.list.map((item, index) => { this.selection.push(index) }) } }, resetSearchKeyword(){ this.searchKeyword = '' }, selectKeyword(index){ this.searchKeyword = this.searchSuggest[index].toString() this.openSearchSuggest = false this.searchStocksText = '<i class="fa fa-spinner fa-spin"></i> Tìm kiếm' axios.post( check_stocks_code_vars.ajax_url, this.jsonToFormData({ action: 'searchStocks', bySelected: this.searchData.bySelected, searchKeyword: this.searchKeyword }) ).then(res => { const response = res.data.data this.list = response.list console.log(response) this.listTemp = response.list this.searchStocksText = '<i class="fa fa-search" aria-hidden="true"></i> Tìm kiếm' if(this.list.length == 0){ this.NOTIFY("Không tìm thấy kết quả nào!",0) return false; } if(this.autoRunAPI){ this.$refs.btnToggleSelection.click() this.$refs.btnSendToAPI.click() } }) }, triggerOpenSearchSuggest(){ this.openSearchSuggest = !this.openSearchSuggest }, loadDataSearch(){ axios.post( check_stocks_code_vars.ajax_url, this.jsonToFormData({ action: 'loadDataSearch', bySelected: this.searchData.bySelected }) ).then(res => { const response = res.data.data this.searchSuggest = response.searchSuggest this.searchSuggestTemp = response.searchSuggest //console.log(response) }) }, searchStocks(){ if(this.searchKeyword === ''){ this.NOTIFY("Chưa nhập từ khóa tìm kiếm!",0) return false } this.searchStocksText = '<i class="fa fa-spinner fa-spin"></i> Tìm kiếm' axios.post( check_stocks_code_vars.ajax_url, this.jsonToFormData({ action: 'searchStocks', bySelected: this.searchData.bySelected, searchKeyword: this.searchKeyword }) ).then(res => { const response = res.data.data this.list = response.list console.log(response) this.listTemp = response.list this.list.sort(this.compareValues('stocksCode', 'asc')) this.searchStocksText = '<i class="fa fa-search" aria-hidden="true"></i> Tìm kiếm' if(this.list.length == 0){ this.NOTIFY("Không tìm thấy kết quả nào!",0) return false; } if(this.autoRunAPI){ this.$refs.btnToggleSelection.click() this.$refs.btnSendToAPI.click() } }) }, searchStocksByEnter(e){ if (e.key === "Enter") { this.openSearchSuggest = false if(this.searchKeyword === ''){ this.NOTIFY("Chưa nhập từ khóa tìm kiếm!",0) return false } this.searchStocksText = '<i class="fa fa-spinner fa-spin"></i> Tìm kiếm' axios.post( check_stocks_code_vars.ajax_url, this.jsonToFormData({ action: 'searchStocks', bySelected: this.searchData.bySelected, searchKeyword: this.searchKeyword }) ).then(res => { const response = res.data.data this.list = response.list this.list.sort(this.compareValues('stocksCode', 'asc')) this.listTemp = response.list this.searchStocksText = '<i class="fa fa-search" aria-hidden="true"></i> Tìm kiếm' if(this.list.length == 0){ this.NOTIFY("Không tìm thấy kết quả nào!",0) return false; } if(this.autoRunAPI){ this.$refs.btnToggleSelection.click() this.$refs.btnSendToAPI.click() } console.log(this.list) }) } } }, components:{ }, props:{ }, template: template, created() { }, mounted(){ this.loadDataSearch() }, watch: { 'searchData.bySelected': function(){ this.loadDataSearch() }, 'searchKeyword': function(){ if(this.searchKeyword.length > 0){ this.searchSuggest = this.searchSuggestTemp.filter((item)=>{ return this.searchKeyword.toLowerCase().split(' ').every(v => item.toLowerCase().includes(v)) }) }else{ this.searchSuggest = this.searchSuggestTemp } } } } |
Để re render một child component chúng ta dùng :key=”reRender”, với reRender là một biến để kích hoạt sự render
ví dụ
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 |
<vuepaginatescroll v-if="list.length" :src="list" :per-scroll="50" :key="reRender"> <template slot-scope="{ data, currentScroll, lastScroll }"> <div class="pagination row q-col-gutter-md q-mb-md"> <div class="col-6">{{ data.length }} / {{ list.length }}</div> <div class="col-6 text-right"><span>Trang:</span>{{ currentScroll }}</div> </div> <div class="wrap-content" v-if="list.length > 0"> <div class="q-markup-table q-table__container q-table__card q-table--horizontal-separator q-table--no-wrap"> <table class="q-table"> <thead> <th class="text-left" width="50px"> <q-btn round color="primary" icon="playlist_add_check" size="sm" @click="toggleSelection"></q-btn> </th> <th class="text-left" width="50px">STT</th> <th class="text-left" width="70px">Mã cổ phiếu</th> <th class="text-left" width="70px">Ghi chú</th> </thead> <tbody> <tr v-for="(item, index) in data" :key="'stockscode' + index"> <td width="50px"> <q-checkbox v-model="selection" :val="item.id"/> </td> <td>{{item.stt}}</td> <td>{{item.code}}</td> <td>{{item.note}}</td> </tr> </tbody> </table> </div> </div> </template> </vuepaginatescroll> |
và ở data
1 2 3 |
data: () => ({ reRender: false }) |
Khi nào cần trigger re render thì chỉ cần set
1 |
this.reRender = !this.reRender |
trong jquery chúng ta thường dùng là $(‘.phan_tu’).html(‘noi dung’) còn trong vue js sẽ dùng v-html để làm việc này
ví dụ
1 2 3 4 5 |
<button @click="sendProductReview" type="button" v-html="buttonSendReviewTitle" ></button> //đây là data data: () => ({ buttonSendReviewTitle: 'Gửi đánh giá' }), |
code mẫu với listCoins là dữ liệu tất cả trong table
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 |
const template = ` <div class="touch-scroll-table"> <vuepaginatescroll v-if="listCoins.length" :src="listCoins" :per-scroll="8"> <template slot-scope="{ data, currentScroll, lastScroll }"> <div class="pagination"> <div class="mr-3">{{ data.length }} / {{ listCoins.length }}</div> <div class="mr-3"> <span>Trang:</span> {{ currentScroll }} </div> </div> <div v-for="(item, index) in data" :key="item.id" class="bsb3JW"> <coinIconReceive v-if="item.status == 'in'" /> <coinIconUsed v-if="item.status == 'out'" /> <div class="Qjnl2T"> <p>{{item.source}}</p> <p class="date-time">{{item.date_time}}</p> </div> <div v-if="item.status == 'in'" class="R519Sm _5Q-g4s">+{{item.coin_number}}</div> <div v-if="item.status == 'out'" class="R519Sm">-{{item.coin_number}}</div> </div> </template> </vuepaginatescroll> </div>` import vuepaginatescroll from './vue-paginate-scroll.js' import coinIconReceive from './coin-icon-receive.js'; import coinIconUsed from './coin-icon-used.js'; export default { data: () => ({ listCoins: [ ], pagination: { currentPage: 1, pageCount:1 } }), methods: { getListCoins(){ this.$parent.$data.loading = true axios.post(wallet_coin_for_woocommerce_vars.ajax_url, this.jsonToFormData({ action: 'getListCoinsReceive' })).then(res => { this.$parent.$data.loading = false this.listCoins = res.data.data.listCoins }) } }, components:{ vuepaginatescroll, coinIconReceive, coinIconUsed }, watch:{ }, template: template, created() { this.getListCoins() }, mounted () { } } |
Ví dụ trong jquery bạn thường dùng $(‘#id_phantu’) hoặc dùng class $(‘.class_phantu’), còn trong vue js
1 2 3 4 |
//ví dụ <input ref="phantu" /> //rồi môt trỏ tới thì dùng this.$refs.phantu.focus() |
nguyên tắc cập nhật bạn xem hình sau:
Tại child component bạn cần emit một sự kiện và tại parent component sẽ bắt sự kiện này để xử lý. ví dụ
tại child component
1 2 |
//sẽ send một event show-modal-rating tới parent và dữ liệu mang theo là dataItem this.$root.$emit('show-modal-rating', dataItem) |
Tại parent component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
mounted(){ this.$root.$on('show-modal-rating', (dataItem) => { this.productThumbnail = dataItem.image this.productTitle = dataItem.name this.orderID = dataItem.id //show modal this.$modal.show( 'formRatingModal', {height: "auto"}, { draggable: true } ) }) } |
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 |
const ajax_url = manage_sites_users_vars.ajax_url import siteAll from "./site-all.js" import siteFee from "./site-fee.js"; import siteTrial from "./site-trial.js"; import siteSuspend from "./site-suspend.js"; Vue.config.debug = true // turn on debugging mode const router = new VueRouter({ routes: [ { path: '/', component: siteAll }, { path: '/sitefee', component: siteFee }, { path: '/sitetrial', component: siteTrial }, { path: '/sitesuspend', component: siteSuspend }, ] }); //golbal function is here //các functions dùng cho các components để ở đây Vue.mixin({ methods:{ openURL(url){ Quasar.utils.openURL(url) }, addCommas(nStr) { nStr += ''; let x = nStr.split('.'); let x1 = x[0]; let x2 = x.length > 1 ? '.' + x[1] : ''; let rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); } return x1 + x2; }, buildFormData(formData, data, parentKey) { if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) { Object.keys(data).forEach(key => { this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); }); } else { const value = data == null ? '' : data; formData.append(parentKey, value); } }, jsonToFormData(data) { const formData = new FormData(); this.buildFormData(formData, data); return formData; }, NOTIFY(msg, type = 1){ this.$q.notify({ message: msg, color: type == 1 ? 'green' : 'red', position: 'top', timeout: 2000 }) }, deepMerge(target, source) { Object.entries(source).forEach(([key, value]) => { if (value && typeof value === 'object') { this.deepMerge(target[key] = target[key] || {}, value); return; } target[key] = value; }); return target; } } }) new Vue({ router, el: '#q-app', data: function () { return { sitesCountAll: 0, sitesCountFee: 0, sitesCountTrial: 0, sitesCountSuspend: 0, loading: false } }, methods: { getStatistic(){ axios.post( manage_sites_users_vars.ajax_url, this.jsonToFormData({ action: 'getStatistic', }) ).then(res => { const data = res.data.data console.log(data) this.sitesCountAll = data.sitesCountAll this.sitesCountFee = data.sitesCountFee this.sitesCountTrial = data.sitesCountTrial this.sitesCountSuspend = data.sitesCountSuspend }).catch(error => { console.log('Hi has error') }) } }, components:{ }, created(){ }, updated(){ this.$root.$on('refresh-statistic', (data) => { console.log(data) this.getStatistic() }) }, mounted(){ this.getStatistic() }, watch: { $route(to, from) { this.loading = false } }, // }); |
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 |
const AJAX_URL = register_shop_normal_vars.ajax_url; new Vue({ el: '#registerShopNormalApp', data: function () { return { formData: { } } }, methods:{ buildFormData(formData, data, parentKey) { if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) { Object.keys(data).forEach(key => { this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); }); } else { const value = data == null ? '' : data; formData.append(parentKey, value); } }, jsonToFormData(data) { const formData = new FormData(); this.buildFormData(formData, data); return formData; }, handle(){ axios.post( AJAX_URL, this.jsonToFormData({ action: 'handleRegisterShopNormal', data: this.formData }) ).then(res => { const response = res.data }) } }, watch:{ }, created(){ } }) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
const template =`day la component` export default { data: () => ({ }), methods: { }, components:{ //nếu không muốn sư dụng tag </getCoidByLoginDaily> thì ta định danh cho no giờ sẽ sử dụng </get-coin-by-login-daily> 'get-coin-by-login-daily': getCoidByLoginDaily, PulseLoader }, props:{ }, template: template, created() { }, mounted(){ }, watch: { } } |
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 |
Vue.mixin({ methods:{ openURL(url){ Quasar.utils.openURL(url) }, addCommas(nStr) { nStr += ''; let x = nStr.split('.'); let x1 = x[0]; let x2 = x.length > 1 ? '.' + x[1] : ''; let rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); } return x1 + x2; }, buildFormData(formData, data, parentKey) { if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) { Object.keys(data).forEach(key => { this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); }); } else { const value = data == null ? '' : data; formData.append(parentKey, value); } }, jsonToFormData(data) { const formData = new FormData(); this.buildFormData(formData, data); return formData; }, NOTIFY(msg, type = 1){ this.$q.notify({ message: msg, color: type == 1 ? 'green' : 'red', position: 'top', timeout: 2000 }) }, deepMerge(target, source) { Object.entries(source).forEach(([key, value]) => { if (value && typeof value === 'object') { this.deepMerge(target[key] = target[key] || {}, value); return; } target[key] = value; }); return target; } } }) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
axios.post( AJAX_URL, this.jsonToFormData({ action: 'getList', current_page:this.pagination.page, per_page:this.pagination.per_page }) ).then(res => { console.log(res.data.data.list) this.list = res.data.data.list this.listTemp = res.data.data.list this.allRows = res.data.data.allRows this.totalRecord = res.data.data.totalRecord this.pagination.total = res.data.data.totalRecord this.pagination.max = res.data.data.totalRecord/this.pagination.per_page this.isLoading = false this.spinnerHide() }).catch(error => { console.log(error.response) }) |
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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 |
<style> .custom-dropdown.q-list a { text-decoration: none; } .custom-dropdown.q-list a .fa { margin-right: 8px; } </style> <div id="q-app"> <div class="q-pa-lg"> <div class="row q-col-gutter-md q-mb-md"> <div class="col-3"> <q-btn color="red" icon="delete" @click="deleteItem" label="Xóa" ></q-btn> <q-btn color="primary" @click="openAddNewModal" ><i style="margin-right: 10px;" class="fa fa-plus-circle" aria-hidden="true"></i> Thêm mới</q-btn> </div> <div class="col-5"> <div class="filter-bySelected-out"> <div> <select v-model="searchData.bySelected" class="filter-bySelected" v-if="searchData.options.length > 0"> <option v-for="(item, index) in searchData.options" :key="index" :value="item.value">{{item.name}} </option> </select> </div> <div><q-input filled v-model="searchData.keyword" label="Từ khóa" dense debounce="500"/></div> </div> </div> <div class="col-4 text-right" style="font-weight:700"> <span>Tổng: </span> <span>{{this.totalRecord}}</span> </div> </div> <div class="wrap-content" v-if="list.length > 0"> <div class="q-markup-table q-table__container q-table__card q-table--horizontal-separator q-table--no-wrap"> <table class="q-table"> <thead> <th class="text-left" width="50px"> <q-btn round color="primary" icon="playlist_add_check" size="sm" @click="toggleSelection"></q-btn> </th> <th class="text-left" width="50px">ID</th> <th class="text-left" width="70px">Url</th> <th class="text-left" width="70px">Ngày đăng ký</th> <th class="text-left" width="70px">Ngày hết hạn</th> <th class="text-left" width="70px">Tình trạng</th> <th class="text-left" width="70px">User quản lý</th> <th class="text-left" width="70px">Ghi chú</th> </thead> <tbody> <tr v-for="item in list" :key="list.id"> <td width="50px"> <q-checkbox v-model="selection" :val="item.id"/> </td> <td>{{item.id}}</td> <td> <div><span>Họ và tên: {{item.name}}</span>, <span>UserID: {{item.user_id}}</span></div> <div>Email: {{item.email}}</div> <div><span>ĐT: {{item.phone}}</span>, <span>UserName: {{item.username}}</span></div> </td> <td> <div style="min-width: 180px; white-space: normal;">{{item.title}}</div> </td> <td>{{item.license}}</td> <td>{{item.datetime}}</td> <td>{{item.expiry_date}}</td> <td> {{item.activated}} </td> <td > <q-btn-dropdown color="primary" > <q-list class="custom-dropdown"> <q-item clickable v-close-popup > <q-item-section> <a :href="newManageLicenseVars.link_to_activations + item.id"><span class="fa fa-info mr-2"></span>Activations</a> </q-item-section> </q-item> <q-item clickable v-close-popup > <q-item-section> <a :href="'post.php?post=' + item.order_id + '&action=edit'"> <span class="fa fa-shopping-cart mr-2"></span>Go to this order</a> </q-item-section> </q-item> </q-list> </q-btn-dropdown> </td> </tr> </tbody> </table> </div> <div class="flex flex-center q-mt-lg"> Số trang <q-pagination v-model="pagination.page" :max="pagination.max" direction-links boundary-links icon-first="skip_previous" icon-last="skip_next" icon-prev="fast_rewind" icon-next="fast_forward" :disabled="isLoading" ></q-pagination> | Số bài viết trên trang <q-btn-dropdown color="primary" :label="pagination.per_page" class="q-ml-xs"> <q-list> <q-item clickable v-close-popup> <q-item-section @click="pagination.per_page = 10"> <q-item-label>10</q-item-label> </q-item-section> </q-item> <q-item clickable v-close-popup> <q-item-section @click="pagination.per_page = 20"> <q-item-label>20</q-item-label> </q-item-section> </q-item> <q-item clickable v-close-popup> <q-item-section @click="pagination.per_page = 50"> <q-item-label>50</q-item-label> </q-item-section> </q-item> <q-item clickable v-close-popup> <q-item-section @click="pagination.per_page = 100"> <q-item-label>100</q-item-label> </q-item-section> </q-item> </q-list> </q-btn-dropdown> </div> </div> <div class="modal"> <q-dialog v-model="modalAddNew"> <q-card style="width: 500px; max-width: 80vw;"> <q-card-section class="row items-center q-pb-none"> <div class="text-h6">Tạo license</div> <q-space></q-space> <q-btn icon="close" flat round dense v-close-popup ></q-btn> </q-card-section> <q-card-section > <template> <div class="q-pa-md"> <div class="q-gutter-md" style="max-width: 800px"> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12"><q-input outlined v-model="addNew.user_id" label="User ID" /></div> </div> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12"><q-input outlined v-model="addNew.product_id" label="Product ID" /></div> </div> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12"><q-input outlined v-model="addNew.order_id" label="Order ID" /></div> </div> <div class="row q-col-gutter-md q-mb-md"> <div class="col-12 text-center"> <q-btn @click="add" color="primary" ><i v-if="addNewRunning" class="fa fa-spinner fa-spin"></i> Thêm</q-btn> </div> </div> </div> </div> </template> </q-card-section> </q-card> </q-dialog> </div> </div> </div> <script type="module"> const AJAX_URL = '<?php echo admin_url('admin-ajax.php'); ?>' Vue.directive('select2', { inserted(el) { jQuery(el).on('select2:select', () => { const event = new Event('change', { bubbles: true, cancelable: true }); el.dispatchEvent(event); }); jQuery(el).on('select2:unselect', () => { const event = new Event('change', {bubbles: true, cancelable: true}) el.dispatchEvent(event) }) }, }); new Vue({ el: '#q-app', data: function () { return { searchData: { bySelected: 'email', keyword: '', options: [ { value: 'email', name: 'Email' }, { value: 'name', name: 'Họ và tên' }, { value: 'phone', name: 'Điện thoại' }, { value: 'user_id', name: 'UserID' }, ] }, addNew: { user_id: null, product_id: null, order_id: null }, modalAddNew: false, totalRecord: null, addNewRunning: false, shopmallInformation: '', isLoading: false, list: [ ], listTemp:[ ], pagination: { page: 1, max: 1, per_page: 20 }, selection: [], } }, methods: { spinner(){ this.$q.loading.show({ spinner: 'QSpinnerBall', spinnerSize: 60, delay: 100 }) }, spinnerHide(){ this.$q.loading.hide() }, openAddNewModal(){ this.modalAddNew = true }, openURL(url){ Quasar.utils.openURL(url) }, notify(msg, type){ this.$q.notify({message: msg, color: type ? 'green' : 'negative', position: 'top'}) }, buildFormData(formData, data, parentKey) { if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) { Object.keys(data).forEach(key => { this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); }); } else { const value = data == null ? '' : data; formData.append(parentKey, value); } }, jsonToFormData(data) { const formData = new FormData(); this.buildFormData(formData, data); return formData; }, toggleSelection(){ if(this.selection.length > 0) this.selection = [] else this.selection = this.list.map(el => el.id) }, deleteItem(){ if(this.selection.length == 0){ this.notify('Bạn chưa chọn dữ liệu nào để xóa.', 0) return; } this.$q.dialog({ title: 'Xác nhận', message: 'Bạn chắc chắn muốn xóa?', cancel: true, persistent: true }).onOk(() => { axios.post( AJAX_URL, this.jsonToFormData({ action: 'deleteItem', ids: this.selection }) ).then(res => { //console.log(res.data.data) this.getList() }).catch(error => { console.log(error.response) }) }) }, add(){ this.addNewRunning = true axios.post( AJAX_URL, this.jsonToFormData({ action: 'addNew', data:this.addNew }) ).then(res => { console.log(res.data.data) this.addNewRunning = false this.modalAddNew = false this.getList() }).catch(error => { console.log(error.response) }) }, getList(){ const { pagination } = this //console.log(newManageLicenseVars) axios.post( AJAX_URL, this.jsonToFormData({ action: 'getList', current_page:this.pagination.page, per_page:this.pagination.per_page }) ).then(res => { //console.log(res.data.data.list) this.list = res.data.data.list this.listTemp = res.data.data.list this.allRows = res.data.data.allRows this.totalRecord = res.data.data.totalRecord this.pagination.total = res.data.data.totalRecord this.pagination.max = res.data.data.totalRecord/this.pagination.per_page this.isLoading = false this.spinnerHide() }).catch(error => { console.log(error.response) }) }, deleteShopMall(){ if(this.selection.length == 0){ this.notify('Bạn chưa chọn phê duyệt shop nào để xóa.', 0) return; } this.$q.dialog({ title: 'Xác nhận', message: 'Bạn chắc chắn muốn xóa?', cancel: true, persistent: true }).onOk(() => { axios.post(AJAX_URL, this.jsonToFormData({action: 'deleteShopNormal', ids: this.selection})).then(res => { console.log(res.data.data); this.selection.forEach(el => { const index = this.list.findIndex(shopmall => shopmall.id == el) this.list.splice(index, 1); }) this.notify('Đã xóa', res.data.status) }) }) } }, watch:{ 'searchData.keyword' : function(){ let bySelected = this.searchData.bySelected if(this.searchData.keyword.length > 0){ this.list = this.allRows.filter((item)=>{ return this.searchData.keyword.toLowerCase().split(' ').every(v => item[bySelected].toLowerCase().includes(v)) }) this.totalRecord = this.list.length this.pagination.total = this.list.length this.pagination.max = this.pagination.total/this.pagination.per_page }else{ // console.log('sdfsd') this.list = this.listTemp this.totalRecord = this.list.length } // }, 'searchData.bySelected' : function(){ let bySelected = this.searchData.bySelected if(this.searchData.keyword.length > 0){ this.list = this.allRows.filter((item)=>{ return this.searchData.keyword.toLowerCase().split(' ').every(v => item[bySelected].toLowerCase().includes(v)) }) this.totalRecord = this.list.length this.pagination.total = this.list.length this.pagination.max = this.pagination.total/this.pagination.per_page }else{ // console.log('sdfsd') this.list = this.listTemp this.totalRecord = this.list.length } // }, 'pagination.page': function(){ this.spinner() this.getList() }, 'pagination.per_page': function(){ this.spinner() this.pagination.page = 1 this.getList() } }, updated(){ /*jQuery('#approveShopProvince').select2({}) jQuery('#approveShopDistrict').select2({}) jQuery('#approveShopWard').select2({})*/ }, created(){ this.getList() } // ...etc }) </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//code js siteStatus:{ selected:1, options: [ { code: 1, text: 'Dùng Thử' }, { code: 2, text: 'Đang trả phí' }, { code: 3, text: 'Tạm khóa' } ] } //code render <select v-model="siteStatus.selected"> <option v-for="status in siteStatus.options" :key="status.code" :value="status.code">{{status.text}}</option> </select> |
include vào head
1 |
<script type='text/javascript' src='../appchat/vue-js-modal.js' ></script> |
trước new vue thêm
1 |
Vue.use(window["vue-js-modal"].default) |
code modal nhớ là đặt trong new vue
1 2 3 |
<modal name="openEditAccount" :draggable="true" :adaptive="true" :resizable="true" :height=450 :scrollable="true" > nội dung modal </modal> |
Mở modal
1 2 3 4 5 6 7 8 |
this.$modal.show( 'openEditAccount', {height: "auto"}, { draggable: true } ) |
Đóng modal
1 |
this.$modal.hide('openEditAccount') |
Bạn chỉ việc thêm v-cloak vào wrap của tag id
ví dụ:
1 2 |
<section class="clearfix content_box_home w88" id="list-wrap" v-cloak> </section> |
Rồi sau đó thêm style sau vào css
1 2 3 |
[v-cloak] { display: none; } |
Mọi sự sao chép xin ghi rõ nguồn là fcwordpress.net
Chuyên trang về wordpress: hướng dẫn thiết kế theme, plugin, thủ thuật wordpress