日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
在Grails中使用jQuery和DataTables

本文介紹如何構(gòu)建一個(gè)基于 Grails 的數(shù)據(jù)瀏覽器來可視化復(fù)雜的表格數(shù)據(jù)。

成都創(chuàng)新互聯(lián)公司專注于虎丘企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城建設(shè)?;⑶鹁W(wǎng)站建設(shè)公司,為虎丘等地區(qū)提供建站服務(wù)。全流程按需定制設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

我是 Grails 的忠實(shí)粉絲。當(dāng)然,我主要是熱衷于利用命令行工具來探索和分析數(shù)據(jù)的數(shù)據(jù)從業(yè)人員。數(shù)據(jù)從業(yè)人員經(jīng)常需要查看數(shù)據(jù),這也意味著他們通常擁有優(yōu)秀的數(shù)據(jù)瀏覽器。利用 Grails、jQuery,以及 DataTables jQuery 插件,我們可以制作出非常友好的表格數(shù)據(jù)瀏覽器。

DataTables 網(wǎng)站提供了許多“食譜式”的教程文檔,展示了如何組合一些優(yōu)秀的示例應(yīng)用程序,這些程序包含了完成一些非常漂亮的東西所必要的 JavaScript、HTML,以及偶爾出現(xiàn)的 PHP。但對(duì)于那些寧愿使用 Grails 作為后端的人來說,有必要進(jìn)行一些說明示教。此外,樣本程序中使用的數(shù)據(jù)是一個(gè)虛構(gòu)公司的員工的單個(gè)平面表格數(shù)據(jù),因此處理這些復(fù)雜的表關(guān)系可以作為讀者的一個(gè)練習(xí)項(xiàng)目。

本文中,我們將創(chuàng)建具有略微復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和 DataTables 瀏覽器的 Grails 應(yīng)用程序。我們將介紹 Grails 標(biāo)準(zhǔn),它是 Groovy 式的 Java Hibernate 標(biāo)準(zhǔn)。我已將代碼托管在 GitHub 上方便大家訪問,因此本文主要是對(duì)代碼細(xì)節(jié)的解讀。

首先,你需要配置 Java、Groovy、Grails 的使用環(huán)境。對(duì)于 Grails,我傾向于使用終端窗口和 Vim,本文也使用它們。為獲得現(xiàn)代的 Java 環(huán)境,建議下載并安裝 Linux 發(fā)行版提供的 Open Java Development Kit (OpenJDK)(應(yīng)該是 Java 8、9、10 或 11 之一,撰寫本文時(shí),我正在使用 Java 8)。從我的角度來看,獲取***的 Groovy 和 Grails 的***方法是使用 SDKMAN!。

從未嘗試過 Grails 的讀者可能需要做一些背景資料閱讀。作為初學(xué)者,推薦文章 創(chuàng)建你的***個(gè) Grails 應(yīng)用程序。

獲取員工信息瀏覽器應(yīng)用程序

正如上文所提,我將本文中員工信息瀏覽器的源代碼托管在 GitHub上。進(jìn)一步講,應(yīng)用程序embrow是在 Linux 終端中用如下命令構(gòu)建的:

 
 
 
 
  1. cd Projects
  2. grails create-app com.nuevaconsulting.embrow

域類和單元測(cè)試創(chuàng)建如下:

 
 
 
 
  1. grails create-domain-class com.nuevaconsulting.embrow.Position
  2. grails create-domain-class com.nuevaconsulting.embrow.Office
  3. grails create-domain-class com.nuevaconsulting.embrow.Employeecd embrowgrails createdomaincom.grails createdomaincom.grails createdomaincom.

這種方式構(gòu)建的域類沒有屬性,因此必須按如下方式編輯它們:

Position 域類:

 
 
 
 
  1. package com.nuevaconsulting.embrow
  2.  
  3. class Position {
  4.     String name
  5.     int starting
  6.     static constraints = {
  7.         name nullable: false, blank: false
  8.         starting nullable: false
  9.     }
  10. }com.Stringint startingstatic constraintsnullableblankstarting nullable

Office 域類:

 
 
 
 
  1. package com.nuevaconsulting.embrow
  2.  
  3. class Office {
  4.     String name
  5.     String address
  6.     String city
  7.     String country
  8.     static constraints = {
  9.         name nullable: false, blank: false
  10.         address nullable: false, blank: false
  11.         city nullable: false, blank: false
  12.         country nullable: false, blank: false
  13.     }
  14. }

Enployee 域類:

 
 
 
 
  1. package com.nuevaconsulting.embrow
  2.  
  3. class Employee {
  4.     String surname
  5.     String givenNames
  6.     Position position
  7.     Office office
  8.     int extension
  9.     Date hired
  10.     int salary
  11.     static constraints = {
  12.         surname nullable: false, blank: false
  13.         givenNames nullable: false, blank: false
  14.         : false
  15.         office nullable: false
  16.         extension nullable: false
  17.         hired nullable: false
  18.         salary nullable: false
  19.     }
  20. }

請(qǐng)注意,雖然 PositionOffice 域類使用了預(yù)定義的 Groovy 類型 String 以及 int,但 Employee 域類定義了 PositionOffice 字段(以及預(yù)定義的 Date)。這會(huì)導(dǎo)致創(chuàng)建數(shù)據(jù)庫(kù)表,其中存儲(chǔ)的 Employee 實(shí)例中包含了指向存儲(chǔ) PositionOffice 實(shí)例表的引用或者外鍵。

現(xiàn)在你可以生成控制器,視圖,以及其他各種測(cè)試組件:

 
 
 
 
  1. -all com.nuevaconsulting.embrow.Position
  2. grails generate-all com.nuevaconsulting.embrow.Office
  3. grails generate-all com.nuevaconsulting.embrow.Employeegrails generateall com.grails generateall com.grails generateall com.

此時(shí),你已經(jīng)準(zhǔn)備好了一個(gè)基本的增刪改查(CRUD)應(yīng)用程序。我在 grails-app/init/com/nuevaconsulting/BootStrap.groovy 中包含了一些基礎(chǔ)數(shù)據(jù)來填充表格。

如果你用如下命令來啟動(dòng)應(yīng)用程序:

 
 
 
 
  1. grails run-app

在瀏覽器輸入 http://localhost:8080/,你將會(huì)看到如下界面:

Embrow 應(yīng)用程序主界面。

單擊 “OfficeController” 鏈接,會(huì)跳轉(zhuǎn)到如下界面:

Office 列表

注意,此表由 OfficeControllerindex 方式生成,并由視圖 office/index.gsp 顯示。

同樣,單擊 “EmployeeController” 鏈接 跳轉(zhuǎn)到如下界面:

employee 控制器

好吧,這很丑陋: Position 和 Office 鏈接是什么?

上面的命令 generate-all 生成的視圖創(chuàng)建了一個(gè)叫 index.gsp 的文件,它使用 Grails 標(biāo)簽,該標(biāo)簽?zāi)J(rèn)會(huì)顯示類名(com.nuevaconsulting.embrow.Position)和持久化示例標(biāo)識(shí)符(30)。這個(gè)操作可以自定義用來產(chǎn)生更好看的東西,并且自動(dòng)生成鏈接,自動(dòng)生成分頁(yè)以及自動(dòng)生成可排序列的一些非常簡(jiǎn)潔直觀的東西。

但該員工信息瀏覽器功能也是有限的。例如,如果想查找 “position” 信息中包含 “dev” 的員工該怎么辦?如果要組合排序,以姓氏為主排序關(guān)鍵字,“office” 為輔助排序關(guān)鍵字,該怎么辦?或者,你需要將已排序的數(shù)據(jù)導(dǎo)出到電子表格或 PDF 文檔以便通過電子郵件發(fā)送給無法訪問瀏覽器的人,該怎么辦?

jQuery DataTables 插件提供了這些所需的功能。允許你創(chuàng)建一個(gè)完成的表格數(shù)據(jù)瀏覽器。

創(chuàng)建員工信息瀏覽器視圖和控制器的方法

要基于 jQuery DataTables 創(chuàng)建員工信息瀏覽器,你必須先完成以下兩個(gè)任務(wù):

  1. 創(chuàng)建 Grails 視圖,其中包含啟用 DataTable 所需的 HTML 和 JavaScript
  2. 給 Grails 控制器增加一個(gè)方法來控制新視圖。

員工信息瀏覽器視圖

在目錄 embrow/grails-app/views/employee 中,首先復(fù)制 index.gsp 文件,重命名為 browser.gsp

 
 
 
 
  1. cd Projects
  2. cd embrow/grails-app/views/employee
  3. cp gsp browser.gsp

此刻,你自定義新的 browser.gsp 文件來添加相關(guān)的 jQuery DataTables 代碼。

通常,在可能的時(shí)候,我喜歡從內(nèi)容提供商處獲得 JavaScript 和 CSS;在下面這行后面:

 
 
 
 
  1. <g:message code="default.list.label" args="[entityName]" />

插入如下代碼:

 
 
 
 

然后刪除 index.gsp 中提供數(shù)據(jù)分頁(yè)的代碼:

 
 
 
 
  1. ${flash.message}
  • 并插入實(shí)現(xiàn) jQuery DataTables 的代碼。

    要插入的***部分是 HTML,它將創(chuàng)建瀏覽器的基本表格結(jié)構(gòu)。DataTables 與后端通信的應(yīng)用程序來說,它們只提供表格頁(yè)眉和頁(yè)腳;DataTables JavaScript 則負(fù)責(zé)表中內(nèi)容。

     
     
     
     
    1. Employee Browser

    2. Surname Given name(s) Position Office Extension Hired Salary
      Surname Given name(s) Position Office Extension Hired Salary

    接下來,插入一個(gè) JavaScript 塊,它主要提供三個(gè)功能:它設(shè)置頁(yè)腳中顯示的文本框的大小,以進(jìn)行列過濾,建立 DataTables 表模型,并創(chuàng)建一個(gè)處理程序來進(jìn)行列過濾。

     
     
     
     
    1. $('#employee_dt tfoot th').each( function() {javascript

    下面的代碼處理表格列底部的過濾器框的大?。?/p>

     
     
     
     
    1. var title = $(this).text();
    2. if (title == 'Extension' || title == 'Hired')
    3. $(this).html('');
    4. else
    5. $(this).html('');
    6. });titletitletitletitletitle

    接下來,定義表模型。這是提供所有表選項(xiàng)的地方,包括界面的滾動(dòng),而不是分頁(yè),根據(jù) DOM 字符串提供的裝飾,將數(shù)據(jù)導(dǎo)出為 CSV 和其他格式的能力,以及建立與服務(wù)器的 AJAX 連接。 請(qǐng)注意,使用 Groovy GString 調(diào)用 Grails createLink() 的方法創(chuàng)建 URL,在 EmployeeController 中指向 browserLister 操作。同樣有趣的是表格列的定義。此信息將發(fā)送到后端,后端查詢數(shù)據(jù)庫(kù)并返回相應(yīng)的記錄。

     
     
     
     
    1. var table = $('#employee_dt').DataTable( {
    2. "scrollY": 500,
    3. "deferRender": true,
    4. "scroller": true,
    5. "dom": "Brtip",
    6. "buttons": [ 'copy', 'csv', 'excel', 'pdf', 'print' ],
    7. "processing": true,
    8. "serverSide": true,
    9. "ajax": {
    10. "url": "${createLink(controller: 'employee', action: 'browserLister')}",
    11. "type": "POST",
    12. },
    13. "columns": [
    14. { "data": "surname" },
    15. { "data": "givenNames" },
    16. { "data": "position" },
    17. { "data": "office" },
    18. { "data": "extension" },
    19. { "data": "hired" },
    20. { "data": "salary" }
    21. ]
    22. });

    ***,監(jiān)視過濾器列以進(jìn)行更改,并使用它們來應(yīng)用過濾器。

     
     
     
     
    1. table.columns().every(function() {
    2. var that = this;
    3. $('input', this.footer()).on('keyup change', function(e) {
    4. if (that.search() != this.value && 8 < e.keyCode && e.keyCode < 32)
    5. that.search(this.value).draw();
    6. });

    這就是 JavaScript,這樣就完成了對(duì)視圖代碼的更改。

     
     
     
     
    1. });

    以下是此視圖創(chuàng)建的UI的屏幕截圖:

    這是另一個(gè)屏幕截圖,顯示了過濾和多列排序(尋找 “position” 包括字符 “dev” 的員工,先按 “office” 排序,然后按姓氏排序):

    這是另一個(gè)屏幕截圖,顯示單擊 CSV 按鈕時(shí)會(huì)發(fā)生什么:

    ***,這是一個(gè)截圖,顯示在 LibreOffice 中打開的 CSV 數(shù)據(jù):

    好的,視圖部分看起來非常簡(jiǎn)單;因此,控制器必須做所有繁重的工作,對(duì)吧? 讓我們來看看……

    控制器 browserLister 操作

    回想一下,我們看到過這個(gè)字符串:

     
     
     
     
    1. "${createLink(controller: 'employee', action: 'browserLister')}"

    對(duì)于從 DataTables 模型中調(diào)用 AJAX 的 URL,是在 Grails 服務(wù)器上動(dòng)態(tài)創(chuàng)建 HTML 鏈接,其 Grails 標(biāo)記背后通過調(diào)用 createLink() 的方法實(shí)現(xiàn)的。這會(huì)最終產(chǎn)生一個(gè)指向 EmployeeController 的鏈接,位于:

     
     
     
     
    1. embrow/grails-app/controllers/com/nuevaconsulting/embrow/EmployeeController.groovy

    特別是控制器方法 browserLister()。我在代碼中留了一些 print 語(yǔ)句,以便在運(yùn)行時(shí)能夠在終端看到中間結(jié)果。

     
     
     
     
    1.     def browserLister() {
    2.         // Applies filters and sorting to return a list of desired employees

    首先,打印出傳遞給 browserLister() 的參數(shù)。我通常使用此代碼開始構(gòu)建控制器方法,以便我完全清楚我的控制器正在接收什么。

     
     
     
     
    1.       println "employee browserLister params $params"
    2.         println()

    接下來,處理這些參數(shù)以使它們更加有用。首先,jQuery DataTables 參數(shù),一個(gè)名為 jqdtParams 的 Groovy 映射:

     
     
     
     
    1. def jqdtParams = [:]
    2. params.each { key, value ->
    3. def keyFields = key.replace(']','').split(/\[/)
    4. def table = jqdtParams
    5. for (int f = 0; f < keyFields.size() - 1; f++) {
    6. def keyField = keyFields[f]
    7. if (!table.containsKey(keyField))
    8. table[keyField] = [:]
    9. table = table[keyField]
    10. }
    11. table[keyFields[-1]] = value
    12. }
    13. println "employee dataTableParams $jqdtParams"
    14. println()

    接下來,列數(shù)據(jù),一個(gè)名為 columnMap 的 Groovy 映射:

     
     
     
     
    1. def columnMap = jqdtParams.columns.collectEntries { k, v ->
    2. def whereTerm = null
    3. switch (v.data) {
    4. case 'extension':
    5. case 'hired':
    6. case 'salary':
    7. if (v.search.value ==~ /\d+(,\d+)*/)
    8. whereTerm = v.search.value.split(',').collect { it as Integer }
    9. break
    10. default:
    11. if (v.search.value ==~ /[A-Za-z0-9 ]+/)
    12. whereTerm = "%${v.search.value}%" as String
    13. break
    14. }
    15. [(v.data): [where: whereTerm]]
    16. }
    17. println "employee columnMap $columnMap"
    18. println()

    接下來,從 columnMap 中檢索的所有列表,以及在視圖中應(yīng)如何排序這些列表,Groovy 列表分別稱為 allColumnListorderList

     
     
     
     
    1. def allColumnList = columnMap.keySet() as List
    2. println "employee allColumnList $allColumnList"
    3. def orderList = jqdtParams.order.collect { k, v -> [allColumnList[v.column as Integer], v.dir] }
    4. println "employee orderList $orderList"

    我們將使用 Grails 的 Hibernate 標(biāo)準(zhǔn)實(shí)現(xiàn)來實(shí)際選擇要顯示的元素以及它們的排序和分頁(yè)。標(biāo)準(zhǔn)要求過濾器關(guān)閉;在大多數(shù)示例中,這是作為標(biāo)準(zhǔn)實(shí)例本身的創(chuàng)建的一部分給出的,但是在這里我們預(yù)先定義過濾器閉包。請(qǐng)注意,在這種情況下,“date hired” 過濾器的相對(duì)復(fù)雜的解釋被視為一年并應(yīng)用于建立日期范圍,并使用 createAlias 以允許我們進(jìn)入相關(guān)類別 PositionOffice

     
     
     
     
    1. def filterer = {
    2. createAlias 'position', 'p'
    3. createAlias 'office', 'o'
    4. if (columnMap.surname.where) ilike 'surname', columnMap.surname.where
    5. if (columnMap.givenNames.where) ilike 'givenNames', columnMap.givenNames.where
    6. if (columnMap.position.where) ilike 'p.name', columnMap.position.where
    7. if (columnMap.office.where) ilike 'o.name', columnMap.office.where
    8. if (columnMap.extension.where) inList 'extension', columnMap.extension.where
    9. if (columnMap.salary.where) inList 'salary', columnMap.salary.where
    10. if (columnMap.hired.where) {
    11. if (columnMap.hired.where.size() > 1) {
    12. or {
    13. columnMap.hired.where.each {
    14. between 'hired', Date.parse('yyyy/MM/dd',"${it}/01/01" as String),
    15. Date.parse('yyyy/MM/dd',"${it}/12/31" as String)
    16. }
    17. }
    18. } else {
    19. between 'hired', Date.parse('yyyy/MM/dd',"${columnMap.hired.where[0]}/01/01" as String),
    20. Date.parse('yyyy/MM/dd',"${columnMap.hired.where[0]}/12/31" as String)
    21. }
    22. }
    23. }

    是時(shí)候應(yīng)用上述內(nèi)容了。***步是獲取分頁(yè)代碼所需的所有 Employee 實(shí)例的總數(shù):

     
     
     
     
    1.         def recordsTotal = Employee.count()
    2.         println "employee recordsTotal $recordsTotal"

    接下來,將過濾器應(yīng)用于 Employee 實(shí)例以獲取過濾結(jié)果的計(jì)數(shù),該結(jié)果將始終小于或等于總數(shù)(同樣,這是針對(duì)分頁(yè)代碼):

     
     
     
     
    1.         def c = Employee.createCriteria()
    2.         def recordsFiltered = c.count {
    3.             filterer.delegate = delegate
    4.             filterer()
    5.         }
    6.         println "employee recordsFiltered $recordsFiltered"

    獲得這兩個(gè)計(jì)數(shù)后,你還可以使用分頁(yè)和排序信息獲取實(shí)際過濾的實(shí)例。

     
     
     
     
    1. def orderer = Employee.withCriteria {
    2. filterer.delegate = delegate
    3. filterer()
    4. orderList.each { oi ->
    5. switch (oi[0]) {
    6. case 'surname': order 'surname', oi[1]; break
    7. case 'givenNames': order 'givenNames', oi[1]; break
    8. case 'position': order 'p.name', oi[1]; break
    9. case 'office': order 'o.name', oi[1]; break
    10. case 'extension': order 'extension', oi[1]; break
    11. case 'hired': order 'hired', oi[1]; break
    12. case 'salary': order 'salary', oi[1]; break
    13. }
    14. }
    15. maxResults (jqdtParams.length as Integer)
    16. firstResult (jqdtParams.start as Integer)
    17. }

    要完全清楚,JTable 中的分頁(yè)代碼管理三個(gè)計(jì)數(shù):數(shù)據(jù)集中的記錄總數(shù),應(yīng)用過濾器后得到的數(shù)字,以及要在頁(yè)面上顯示的數(shù)字(顯示是滾動(dòng)還是分頁(yè))。 排序應(yīng)用于所有過濾的記錄,并且分頁(yè)應(yīng)用于那些過濾的記錄的塊以用于顯示目的。

    接下來,處理命令返回的結(jié)果,在每行中創(chuàng)建指向 Employee、PositionOffice 實(shí)例的鏈接,以便用戶可以單擊這些鏈接以獲取相關(guān)實(shí)例的所有詳細(xì)信息:

     
     
     
     
    1.         def dollarFormatter = new DecimalFormat('$##,###.##')
    2.         def employees = orderer.collect { employee ->
    3.             ['surname': "${employee.surname}",
    4.                 'givenNames': employee.givenNames,
    5.                 'position': "${employee.position?.name}",
    6.                 'office': "${employee.office?.name}",
    7.                 'extension': employee.extension,
    8.                 'hired': employee.hired.format('yyyy/MM/dd'),
    9.                 'salary': dollarFormatter.format(employee.salary)]
    10.         }

    ***,創(chuàng)建要返回的結(jié)果并將其作為 JSON 返回,這是 jQuery DataTables 所需要的。

     
     
     
     
    1. def result = [draw: jqdtParams.draw, recordsTotal: recordsTotal, recordsFiltered: recordsFiltered, data: employees]
    2. render(result as JSON)
    3. }

    大功告成。

    如果你熟悉 Grails,這可能看起來比你原先想象的要多,但這里沒有火箭式的一步到位方法,只是很多分散的操作步驟。但是,如果你沒有太多接觸 Grails(或 Groovy),那么需要了解很多新東西 - 閉包,代理和構(gòu)建器等等。

    在那種情況下,從哪里開始? ***的地方是了解 Groovy 本身,尤其是 Groovy closures 和 Groovy delegates and builders。然后再去閱讀上面關(guān)于 Grails 和 Hibernate 條件查詢的建議閱讀文章。

    結(jié)語(yǔ)

    jQuery DataTables 為 Grails 制作了很棒的表格數(shù)據(jù)瀏覽器。對(duì)視圖進(jìn)行編碼并不是太棘手,但 DataTables 文檔中提供的 PHP 示例提供的功能僅到此位置。特別是,它們不是用 Grails 程序員編寫的,也不包含探索使用引用其他類(實(shí)質(zhì)上是查找表)的元素的更精細(xì)的細(xì)節(jié)。

    我使用這種方法制作了幾個(gè)數(shù)據(jù)瀏覽器,允許用戶選擇要查看和累積記錄計(jì)數(shù)的列,或者只是瀏覽數(shù)據(jù)。即使在相對(duì)適度的 VPS 上的百萬行表中,性能也很好。

    一個(gè)警告:我偶然發(fā)現(xiàn)了 Grails 中暴露的各種 Hibernate 標(biāo)準(zhǔn)機(jī)制的一些問題(請(qǐng)參閱我的其他 GitHub 代碼庫(kù)),因此需要謹(jǐn)慎和實(shí)驗(yàn)。如果所有其他方法都失敗了,另一種方法是動(dòng)態(tài)構(gòu)建 SQL 字符串并執(zhí)行它們。在撰寫本文時(shí),我更喜歡使用 Grails 標(biāo)準(zhǔn),除非我遇到雜亂的子查詢,但這可能只反映了我在 Hibernate 中對(duì)子查詢的相對(duì)缺乏經(jīng)驗(yàn)。


    網(wǎng)頁(yè)題目:在Grails中使用jQuery和DataTables
    網(wǎng)頁(yè)鏈接:http://www.dlmjj.cn/article/djieeds.html