استفاده از Grails در جی کوئری و جدول داده ها

چهارشنبه 12 تیر 1398

استفاده از Grails برای data tebel ها کاربرد زیادی دارد. در این مطلب قصد داریم درباره Grails و استفاده از آن در جدول های داده های بزرگ صحبت کنیم.

 استفاده از Grails در جی کوئری و جدول داده ها

من یکی از طرفداران پر و پا قرص Grails هستم. من جزء آن دسته از افرادی هستم که علاقه مند به کار کردن با داده ها و آنالیز کردن آنها با استفاده از ابزارهای خط فرمان هستم، تمامی افراد گاهی اوقات نیاز دارند که بتوانند نگاهی به برخی از داده ها انداخته و آن ها را تجزیه و تحلیل کنند، داشتن یک جدول بزرگ از داده ها و تجزیه و تحلیل آن می تواند کار نسبتا سختی باشد، با استفاده از Grails در جی کوئری شما می توانید این کار را به راحتی انجام دهید. پلاگین data tables در جی کوئری کمک زیادی به شما در درک درستی از داده ها خواهد کرد.

وب سایت data tebels یک داکیومنتیشن بسیار قوی را به شما ارائه می دهد که به شما نشان می دهد چگونه می توانید از یک برنامه خوب برای تجزیه و تحلیل داده های خود استفاده کنید که این برنامه شامل جاوا اسکریپت و اچ تی ام ال می باشد. برای افرادی که علاقه مند به استفاده از Grails در قسمت بک اند خود هستند داشتن یک درک درست از نحوه ی کار کردن با داده ها ضروری می باشد، علاوه بر این داده هایی که در یک جدول یک سطری قرار دارند نیز دارای پیچیگی های خاص خود می باشند که برای کار کردن با آنها نیاز دارید که بتوانید از Grails استفاده کنید و کار کردن با آن را تمرین کنید.
مقدمه ای درباره این مقاله

در این مقاله ما قصد داریم که دو باگ بزرگ را با استفاده از ساختن یک اپلیکیشن با استفاده از Grails به شما آموزش دهیم که می تواند ساختارهای پیچیده را به راحتی برای شما تجزیه و تحلیل کند. ما برای انجام این کار قصد داریم برخی از معیارهای Grails را به شما آموزش دهیم که در واقع همان معیارهای Groovy-fied Java Hibernate می باشند، من کد مربوط به این مقاله را در گیت هاب قرار داده ام و این مقاله تنها به بیان تفاوت های ظاهری میان این کد با سایر کدها خواهد پرداخت.

 Grails


پیش نیازهای مورد نیاز

به عنوان پیش نیاز برای انجام این کار شما نیاز دارید که محیط های جاوا، گرووی و Grails را بر روی سیستم خود نصب کنید، من به شخصه علاقه مند هستم که از پنجره ترمینال و Vim استفاده کنم. همانطور که مشاهده می کنید در این جا هم استفاده کرده ام. برای دریافت نسخه مدرن جاوا به شما پیشنهاد می کنم Open Java Development Kit (OpenJDK) را دانلود و نصب کنید که توسط توزیع لینوکس تولید شده و امروزه نسخه های 8، 9، 10 و 11 آن موجود است و در زمان تولید این مقاله من از نسخه 8 آن استفاده کرده ام. از نظر من بهترین راه برای این که بتوانید Groovy و Grails را به روزرسانی کنید این است که از SDKMAN برای انجام این کار استفاده کنید.

 Grails


دریافت برنامه employee browser

همانطور که در بالا ذکر شد من سورس کد این برنامه employee browser  را در گیت هاب قرار داده ام، برای توضیح بیشتر این برنامه با زدن کد زیر در خط فرمان لینوس تولید شده است:

cd Projects

grails create-app com.nuevaconsulting.embrow

کلاس های دامین و یونیت تست ها نیز به شکل زیر انجام می شوند:

cd embrow

grails create-domain-class com.nuevaconsulting.embrow.Position

grails create-domain-class com.nuevaconsulting.embrow.Office

grails create-domain-class com.nuevaconsulting.embrow.Employee

کلاس های دامین که با استفاده از این روش ساخته می شوند هیچ گونه ویژگی ندارند و به همین علت است که شما باید آنها را ویرایش کنید.

 Grails


ویرایش کلاس های دامین

کلاس دامین پوزیشن:

package com.nuevaconsulting.embrow


class Position {


    String name

    int starting


    static constraints = {

       name nullable: false, blank: false

       starting nullable: false

    }

}

کلاس دامین Office:

package com.nuevaconsulting.embrow


class Office {


    String name

    String address

    String city

    String country


    static constraints = {

       name nullable: false, blank: false

       address nullable: false, blank: false

       city nullable: false, blank: false

       country nullable: false, blank: false

    }

}

و کلاس دامین Employee نیز به شکل زیر باید ویرایش شود:

package com.nuevaconsulting.embrow


class Employee {


    String surname

    String givenNames

    Position position

    Office office

    int extension

    Date hired

    int salary

    static constraints = {

       surname nullable: false, blank: false

       givenNames nullable: false, blank: false

       position nullable: false

       office nullable: false

       extension nullable: false

       hired nullable: false

       salary nullable: false

    }

}

 Grails


یک نکته بسیار مهم

توجه داشته باشید که کلاس های دامین و آفیس از نوع داده ای String و int استفاده می کنند. علاوه بر این کلاس Employee نیز از فیلدهایی استفاده می کند که از نوع کلاس های پوزیشن و دامین می باشد. این موضوع باعث به وجود آمدن جدول پایگاه داده ای می شود که در آن شیء های ساخته شده از کلاس Employee برای نگهداری منابع ذخیره شده اند یا از کلیدهای خارجی برای ذخیره سازی اشیایی که از کلاس position و Office ساخته شده اند استفاده شده است.

حال شما می توانید کنترلرها، ویوها و سایر کامپوننت های تست دیگر را به شکل زیر تعریف کنید:

grails generate-all com.nuevaconsulting.embrow.Position

grails generate-all com.nuevaconsulting.embrow.Office

grails generate-all com.nuevaconsulting.embrow.Employee

در این مرحله شما یک CRUD (create، read، update و Delete) پایه ای دارید که آماده ی اجرا و استفاده است. من برخی از داده های پایه ای برای اجرای Grails را در Grails-app/init/com/nuevaconsulting/BootStrap.groovy گنجانده ام.

اگر شما این اپلیکیشن را با استفاده از دستورات کامند اجرا کنید:

grails run-app

حال شما می توانید اسکرین شات زیر از Grails را در آدرس http://localhost:8080/: از مرورگر خود مشاهده کنید:

 Grails

با کلیک کردن بر روی لینک مربوط به OfficeController می توانید اسکرین شاتی مانند اسکرین شات زیر را در صفحه مرورگر خود مشاهده کنید:

توجه داشته باشید که این لیست توسط متد OfficeController index ساخته شده و توسط ویو مربوط به office/index.gsp. در Grails به نمایش گذاشته شده است.

به صورت مشابه شما می توانید با کلیک بر روی لینک مربوط به EmployeeController اسکرین شاتی مشابه اسکرین شات زیر را دریافت کنید:

 Grails

با کلیک بر روی لینک مربوط به پوزیشن و آفیس چه اتفاقی خواهد افتاد؟

ویوها با استفاده از دستورات کلی تولید که در فایل index.gsp در Grails رخ داد به وجود می آیند  و از برچسب Grails <f:table/> استفاده می کنند، که به صورت پیشفرض نام کلاس مربوط به آنها می باشد. شما می توانید این متد را به راحتی شخصی سازی کنید تا نتیجه ی بهتری را برای شما به ارمغان بیاورد که از جمله آنها می توان به مختصر و مفیدتر شدن صفحه، تولید لینک ها به صورت خودکار، صفحه بندی خودکار و تولید خودکار ستون های قابل مرتب سازی اشاره کرد.

با این وجود حتی زمانی که Grails به صورت کاملا شفاف کار می کند نیز قابلیت های محدودی را در اختیار شما قرار می دهد، به عنوان مثال فرض کنید که می خواهید تمامی کارکنانی که موقعیت آنها شامل کلمه dev می باشد را پیدا کنید، چه اتفاقی می افتد اگر شما بخواهید که ستون ها را به منظور مرتب سازی با یکدیگر ترکیب کنید و این موضوع باعث شود که مرتب سازی اولیه از بین برود؟ یا این که چه اتفاقی می افتد اگر شما یک زیر مجموعه مرتب شده را به یک صفحه پی دی اف تبدیل کنید؟

پلاگین های data table جی کوئری در Grails به شما کمک می کنند و قابلیت های زیادی را برای شما فراهم می کنند تا بتوانید یک جدول کامل از داده ها را در مرورگر خود ایجاد کنید.


ساخت ویو مرورگر employee و متدهای کنترل کننده آن

برای ساخت یک مرورگر با داده های مربوط به employee در جی کوئری و Grails شما باید دو کار را انجام دهید:

1-      یک ویو مربوط به Grails ایجاد کنید که شامل اچ تی ام ال و جاوا اسکریپت برای فعال کردن Data tables باشد.

2-      یک متد به کنترلر Grails اضافه کنید که ویوی جدید را مدیریت کند.
employee browser view

در داخل دایرکتور embrow/grails-app/views/employee یک فایل کپی از index.gsp را ایجاد کرده و آن را فراخوانی کنید:

cd Projects

cd embrow/grails-app/views/employee

cp index.gsp browser.gsp

در این مرحله شما می خواهید فایل browser.gsp جدید را شخصی سازی کنید و کد مربوط به Data tables در جی کوئری را به آن اضافه کنید:

به عنوان مثال من می خواهم کدهای مربوط به جاوا اسکریپت و سی اس اس را به محض امکان پذیر بودن دریافت کنم، برای انجام این کار در خط فرمان باید کدهای زیر را وارد کنم:

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

خطوط زیر را نیز باید به این کد اضافه کنید:

script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.css">

<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.js"></script>

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/scroller/1.4.4/css/scroller.dataTables.min.css">

<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/scroller/1.4.4/js/dataTables.scroller.min.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/1.5.1/js/dataTables.buttons.min.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.flash.min.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/pdfmake.min.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.html5.min.js"></script>

<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.print.min.js "></script>

Next, remove the code that provided the data pagination in index.gsp:

حال کدهایی که data pagination را در فایل index.gsp: فراهم می کنند را حذف کنید:

<div id="list-employee" class="content scaffold-list" role="main">

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

<g:if test="${flash.message}">

<div class="message" role="status">${flash.message}</div>

</g:if>

<f:table collection="${employeeList}" />


<div class="pagination">

<g:paginate total="${employeeCount ?: 0}" />

</div>

</div>

و کدهایی که باعث زیبا سازی جدول داده ها در جی کوئری و Grails می شوند را نیز اضافه کنید.

 Grails


گام اول برای زیباسازی جدول

اولین مرحله برای انجام این کار اضافه کردن کدهای html می باشد که یک حالت جدولی پایه را برای داده های شما در مرورگر ایجاد می کند، در این اپلیکیشن زمانی که data tables با قسمت بک اند پایگاه داده ارتباط برقرار می کند، تنها حاشیه ها و ستون های جدول را ایجاد می کند و جاوا اسکریپت نیز از محتویات این جدول در Grails نگهداری می کند.

<div id="employee-browser" class="content" role="main">

<h1>Employee Browser</h1>

<table id="employee_dt" class="display compact" style="width:99%;">

<thead>

<tr>

<th>Surname</th>

<th>Given name(s)</th>

<th>Position</th>

<th>Office</th>

<th>Extension</th>

<th>Hired</th>

<th>Salary</th>

</tr>

</thead>

<tfoot>

<tr>

<th>Surname</th>

<th>Given name(s)</th>

<th>Position</th>

<th>Office</th>

<th>Extension</th>

<th>Hired</th>

<th>Salary</th>

</tr>

</tfoot>

</table>

</div>

گام دوم برای زیباسازی جدول

در مرحله بعدی شما باید کدهای مربوط به جاوا اسکریپت را اضافه کنید و سه عمل اصلی را در آن قرار دهید، ابتدا شما باید سایز باکس های مربوط به متن را وارد کنید، بعد از آن فاصله از پایین و فیلدهای هر یک از ستون ها را نیز باید وارد کنید تا بتوانید یک حالت جدولی مناسب را برای داده های خود ایجاد کنید.

<g:javascript>

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

قطعه کد زیر سایز دادن به فیلترهایی که در انتهای جدول هستند را مدیریت می کند:

var title = $(this).text();

if (title == 'Extension' || title == 'Hired')

$(this).html('<input type="text" size="5" placeholder="' + title + '?" />');

else

$(this).html('<input type="text" size="15" placeholder="' + title + '?" />');

});

 Grails


گام سوم از زیباسازی جدول

بعد از انجام تمامی این کارها شما باید مدل جدول خود را تعریف کنید، در این مرحله تمامی متدهای جدول شما باید تعریف شده باشند که از جمله آنها می توان به اسکرول کردن، یک رابط کاربری طبیعی، توانایی ارسال داده های مختلف در فرمت های مختلف و همین طور خاصیت اتصال به سرور و ارتباط با آن و ... توجه داشته باشید که در Grails آدرس را همان Url با استفاده از Groovy GString و متد  Grails createLink() ایجاد می شوند، اطلاعات به وجود آمده به قسمت بک اند پایگاه داده ارسال می شوند و این پایگاه داده آنها را به نمایش می گذارد و نتیجه ی مناسب را باز می گرداند.

var table = $('#employee_dt').DataTable( {

"scrollY": 500,

"deferRender": true,

"scroller": true,

"dom": "Brtip",

"buttons": [ 'copy', 'csv', 'excel', 'pdf', 'print' ],

"processing": true,

"serverSide": true,

"ajax": {

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

"type": "POST",

},

"columns": [

{ "data": "surname" },

{ "data": "givenNames" },

{ "data": "position" },

{ "data": "office" },

{ "data": "extension" },

{ "data": "hired" },

{ "data": "salary" }

]

});

 Grails

گام آخر برای زیباسازی جدول

در این مرحله شما باید فیلترهای ستون های خود را به نمایش بگذارید،

table.columns().every(function() {

var that = this;

$('input', this.footer()).on('keyup change', function(e) {

if (that.search() != this.value && 8 < e.keyCode && e.keyCode < 32)

that.search(this.value).draw();

});

در ادامه این کد باعث کامل شدن کدهای مربوط به زیباسازی شما می شود:

});

</g:javascript>

 
مشاهده ی نتایج

در این جا یک اسکرین شات از UI که توسط این ویو ساخته شده است را مشاهده می کنید:

 Grails

در ادامه اسکرین شات دیگری وجود دارد که فیلتر کردن ستون و مرتب سازی چند ستونه ی آنها را نشان می دهد (مربوط به مثالی بود که به دنبال تمامی کارکنانی که آدرس فعلی آنها با dev شروع می شد بودیم):

 Grails

اسکرین شات زیر نشان می دهد که اگر شما بر روی دکمه CSV کلیک کنید چه اتفاقی می افتد:

و در انتها تصویر زیر نشان دهنده ی داده های CSV در بخش LibreOffice از Grails می باشد:

 Grails

بسیار خب، به نظر این بخش ساده بود، بنابراین عمل کنترلر باید تمامی محاسبات و بخش های سنگین را دارا باشد، این طور نیست؟ با ما در ادامه این مطلب همراه باشید.
عملیات employee controller browserLister

توجه داشته باشید که ما String زیر را داشتیم:

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

این String به عنوان یک URL برای برقراری ارتباط بین جدول داده ها و Data tables برچسب گذاری شده در Grails مورد استفاده قرار می گرفت که به صورت پویا یک لینک تولید می کرد و با استفاده از HTML پردازش های لازم را بر روی سرور Grails انجام می داد، با تولید یک لینک در Grails که برای EmployeeController می باشد و در آدرس زیر قرار گرفته است این پردازش به پایان می رسد:

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

این کار به صورت اختصاصی برای متد کنترل کننده browserLister() نیز در Grails اتفاق می افتد. من برخی از دستورات پرینت را که نشان دهنده ی خروجی ها بودند در پنجره ترمینال قرار دادم تا در حین اجرا دیده شوند.

def browserLister() {

       

       // Applies filters and sorting to return a list of desired employees


مرحله ی اول برای چاپ نتایج

در ابتدا پارامترهایی که به متد browserLister() ارسال شده بودند چاپ می شود، من معمولا کار خود برای ساخت یک متد کنترل کننده را با این کد شروع می کنم تا به صورت کامل آن را دریافت کنم:

println "employee browserLister params $params"

       println()

بعد از آن باید این پارامترها را پردازش کرد تا آن ها را به شکل قابل استفاده تری درآورد، ابتدا برای پارامترهای Data tables جی کوئری باید jqdtParams توسط Groovy map فراخوانی شود.

def jqdtParams = [:]

       params.each { key, value ->

           def keyFields = key.replace(']','').split(/\[/)

           def table = jqdtParams

           for (int f = 0; f < keyFields.size() - 1; f++) {

               def keyField = keyFields[f]

               if (!table.containsKey(keyField))

                   table[keyField] = [:]

               table = table[keyField]

           }

           table[keyFields[-1]] = value

       }

       println "employee dataTableParams $jqdtParams"

       println()

مرحله ی دوم برای چاپ نتایج

بعد از آن بر روی ستون مربوط به داده های مربوط به ستون باید این عملیات انجام شود که این کار از طریق فراخوانی columnMap توسط Groovy map شکل می گیرد:

def columnMap = jqdtParams.columns.collectEntries { k, v ->

           def whereTerm = null

           switch (v.data) {

           case 'extension':

           case 'hired':

           case 'salary':

               if (v.search.value ==~ /\d+(,\d+)*/)

                   whereTerm = v.search.value.split(',').collect { it as Integer }

               break

           default:

               if (v.search.value ==~ /[A-Za-z0-9 ]+/)

                   whereTerm = "%${v.search.value}%" as String

               break

           }

           [(v.data): [where: whereTerm]]

       }

       println "employee columnMap $columnMap"

       println()

 Grails


مرحله ی سوم از چاپ نتایج

در نهایت لیستی از تمامی نام های ستون ها از columnMap و همینطور لیست متناظر با ترتیبی که ستون ها در این ویو باید باشند بازگردانده می شود، لیست های Groovy می توانند allColumnList و orderList را به ترتیب زیر فراخوانی کنند:

def allColumnList = columnMap.keySet() as List

       println "employee allColumnList $allColumnList"

       def orderList = jqdtParams.order.collect { k, v -> [allColumnList[v.column as Integer], v.dir] }

       println "employee orderList $orderList"

 Grails


پیاده سازی هایبرنیت Grails

ما در این جا قصد داریم تا از معیار Hibernate Grails استفاده کرده و آن را پیاده سازی کنیم تا به این طریق بتوانیم انتخاب عناصر را به شکل زیباتری نشان دهیم و همینطور آنها را سفارشی سازی کنیم. استفاده کردن از این معیار در Grails نیازمند استفاده از برخی از فیلترها می باشد، ما در این جا باید فیلتر خود را به صورت مشخص تعریف کنیم که در این مثال می تواند پیچیدگی هایی را به همراه داشته باشد، استفاده از createAlias می تواند در این کار کمک زیادی به شما بکند.

def filterer = {

           createAlias 'position',        'p'

           createAlias 'office',          'o'


           if (columnMap.surname.where)    ilike  'surname',     columnMap.surname.where

           if (columnMap.givenNames.where) ilike  'givenNames', columnMap.givenNames.where

           if (columnMap.position.where)   ilike 'p.name', columnMap.position.where

           if (columnMap.office.where)     ilike  'o.name',      columnMap.office.where

           if (columnMap.extension.where)  inList 'extension', columnMap.extension.where

           if (columnMap.salary.where)     inList 'salary',      columnMap.salary.where

           if (columnMap.hired.where) {

               if (columnMap.hired.where.size() > 1) {

                   or {

                       columnMap.hired.where.each {

                           between 'hired', Date.parse('yyyy/MM/dd',"${it}/01/01" as String),

                               Date.parse('yyyy/MM/dd',"${it}/12/31" as String)

                       }

                   }

               } else {

                   between 'hired', Date.parse('yyyy/MM/dd',"${columnMap.hired.where[0]}/01/01" as String),

                       Date.parse('yyyy/MM/dd',"${columnMap.hired.where[0]}/12/31" as String)

               }

           }

در این مرحله ما باید تمامی کارهایی که کرده ایم را اجرا کنیم، در مرحله اول ما نیاز داریم که تمامی شیء هایی که از کلاس Employee ساخته ایم را محاسبه کنیم که این کار با استفاده از قطعه کد زیر امکان پذیر می باشد:

def recordsTotal = Employee.count()

       println "employee recordsTotal $recordsTotal"

در مرحله بعدی فیلترهای مربوط به شیء های Employee را محاسبه کنید که باید کمتر از تعداد کل باشد:

def c = Employee.createCriteria()

       def recordsFiltered = c.count {

           filterer.delegate = delegate

           filterer()

       }

       println "employee recordsFiltered $recordsFiltered"

زمانی که شما این دو تعداد را داشته باشید می توانید شیء های ساخته شده با فیلترهای واقعی را همراه با اطلاعات خود دریافت کنید:

def orderer = Employee.withCriteria {

           filterer.delegate = delegate

           filterer()

           orderList.each { oi ->

               switch (oi[0]) {

               case 'surname':    order 'surname',    oi[1]; break

               case 'givenNames': order 'givenNames', oi[1]; break

               case 'position':   order 'p.name',     oi[1]; break

               case 'office':     order 'o.name',     oi[1]; break

               case 'extension':  order 'extension', oi[1]; break

               case 'hired':      order 'hired',      oi[1]; break

               case 'salary':     order 'salary',     oi[1]; break

               }

           }

           maxResults (jqdtParams.length as Integer)

           firstResult (jqdtParams.start as Integer)

   }

حال شما باید نتایجی که به ترتیب به شما بازگشت داده می شود را پردازش کنید، لینک های مربوط به Employee، پوزیشن و ... را بسازید و همینطور اشیای مد نظر را نیز به عنوان سطرهای جدول در نظر بگیرید:

def dollarFormatter = new DecimalFormat('$##,###.##')

       def employees = orderer.collect { employee ->

           ['surname': "<a href='${createLink(controller: 'employee', action: 'show', id: employee.id)}'>${employee.surname}</a>",

               'givenNames': employee.givenNames,

               'position': "<a href='${createLink(controller: 'position', action: 'show', id: employee.position?.id)}'>${employee.position?.name}</a>",

               'office': "<a href='${createLink(controller: 'office', action: 'show', id: employee.office?.id)}'>${employee.office?.name}</a>",

               'extension': employee.extension,

               'hired': employee.hired.format('yyyy/MM/dd'),

               'salary': dollarFormatter.format(employee.salary)]

     }

در پایان نیز باید نتیجه ای که می خواهید به صورت JSON باز گردانید را تولید کنید که این کار نیز به شکل زیر انجام می شود:

def result = [draw: jqdtParams.draw, recordsTotal: recordsTotal, recordsFiltered: recordsFiltered, data: employees]

       render(result as JSON)

    }

 Grails
 

ایمان مدائنی

نویسنده 1299 مقاله در برنامه نویسان
  • Jquery
  • 2k بازدید
  • 0 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

تاکنون هیچ کاربری از این پست تشکر نکرده است

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید