gpt4 book ai didi

grails - 在 CRUD grails 脚手架中自动生成 Jquery Autocomplete(一对多关系)

转载 作者:行者123 更新时间:2023-12-02 15:36:00 25 4
gpt4 key购买 nike

我已经更改了 grails 项目中的 src/templates/scaffolding/renderEditor.template 文件,以便在所有“多对”关系中插入必要的 html 字段框(和 javascript 代码)来配置和使用 jquery 自动完成一”。 (代码如下所示)

自动生成的自动完成(_form.gsp)工作正常......但是当用户使用脚手架编辑记录时,我需要在自动完成文本框中显示正确的值(代码和描述)。

为此,我需要识别域内的两个字段:一个用于代码,另一个用于描述。

面对这个问题,我尝试创建两个虚拟约束,使用插件“约束”,第一个用作代码,第二个用作描述。我不喜欢这个解决方案,因为约束可以在域中多次使用。

更改为 src/templates/scaffolding/renderEditor.template 文件的代码如下:(注意两个输入框和用于自动完成的 Javascript 代码):

private renderManyToOne(domainClass, property) {
if (property.association) {


/* ORIGINAL CODE inside comments
def sb = new StringBuilder()
sb << '<g:select'
// id is "x" and name is "x.id" as the label will have for="x" and "." in an id will confuse CSS
sb << ' id="' << property.name << '"'
sb << ' name="' << property.name << '.id"'
sb << ' from="${' << property.type.name << '.list()}"'
sb << ' optionKey="id"'
if (isRequired()) sb << ' required=""'
sb << ' value="${' << "${domainInstance}?.${property.name}" << '?.id}"'
sb << ' class="many-to-one"'
sb << renderNoSelection(property)
sb << '/>'
sb as String

*/


def sb = new StringBuilder()

// hidden field for domain.id

sb << '<input type=\"hidden\" '
sb << ' id="' << property.name << '.id"'
sb << ' name="' << property.name << '.id"'
sb << ' value="${' << "${domainInstance}" << '?.id}" '
sb << '/>\n'

// Text field to show the description generated by autocomplete
sb << '\t<input type=\"text\" '
sb << ' id="' << property.name << '"'
sb << ' name="' << property.name << '"'
if (isRequired()) sb << ' required="" '
sb << 'style=\"width: 600px;\" '
sb << ' value="${' << "${domainInstance}?.${property.name}" << '?.id}"'
// sb << '${' << "${property.name}" << '"'
sb << '/>'

def js = new StringBuilder()
js << '''
<script type="text/javascript">

/*
* Remember include jquery and jquery-ui libraries into head section of edit.gsp file
* < g:javascript library="jquery"/>
* < g:javascript library="jquery-ui"/>
*/

\$(document).ready(function() {
'''
js << '\t\$("#' << property.name << '").focus(function(){this.select(); });\n'

js << '\t\t$("#' << property.name << '").autocomplete({\n'

js << '''
source: function(request, response){
\$.ajax({
// Define Remote datasource into the controller
'''
js << ' \t\t url: "'
js << '/' << grails.util.Metadata.current.'app.name' << '/' << property.name << '/' << 'autoCompleteList",'

js << '''
data: request,
success: function(data){
// Get the response (JSON format)
response(data);
},
error: function(){
// Handle server errors
response("Error after search records. Try Again.")
}
});
},
// General options: Triggered only after minimum 2 characters have been entered and others
minLength: 2,
delay: 1,
autoFocus: true,
// Event handler when user selects a Loinc from the list.
select: function(event, ui) {
// update the hidden field.
'''
js << '\t\t\t\t \$("#' << property.name << '\\.id").val(ui.item.id);'
js << '''
}
});
});
</script>
'''
sb << js
sb as String


}

使用虚拟约束(autoid 和 autodesc)的域:
class LOINC {

static searchable = {
only = ["code", "shortName", "longName", "property", "system", "scale", "method", "time"]
}

String code // LOINC_NUM * 0
String shortName // SHORTNAME * 29
String longName // LONG_COMMON_NAME * 35
String name // BASE_NAME * 21
String component // COMPONENT * 1
String property // PROPERTY * 2
String time // TIME_ASPCT * 3
String system // SYSTEM * 4
String scale // SCALE_TYP * 5
String method // METHOD_TYP * 6

static constraints = {
code(nullable: false, unique: true, blank: false, maxSize: 100, autoid: true)
shortName(nullable: false)
longName(nullable: false, autodesc: true)
name(nullable: false, maxSize: 100)
component(nullable: false)
property(nullable: false)
time(nullable: false)
system(nullable: false)
scale(nullable: false)
method(nullable: false)
}

String toString(){
"${code} ${longName}"
}
}

Controller 内部的代码:
 def autoCompleteList = {
def loincAutoCompleteService = new LOINCAutoCompleteService()
render loincAutoCompleteService.loincList(params) as JSON
}

服务:
class LOINCAutoCompleteService {

def loincList(params) {

// Creates a new query Object
def query = {
or {
like("code", "${params.term}%") // term is the parameter send by jQuery autocomplete
like("longName", "${params.term}%")
like("shortName", "${params.term}%")
}
projections { // good to select only the required columns.
property("id")
property("code")
property("longName")
}
}

def loincSelectList = [] // aArray List to add each Loinc details
def clist = LOINC.createCriteria().list(query)


clist.each {
// Add to map. jQuery autocomplete expects the JSON object to be with id/label/value
def loincMap = [:]

loincMap.put("id", it[0])

// Label is text showed int he drop-down list
loincMap.put("label", it[1] + " : " + it[2])

// Values is the code to be returned when the user select an item from drop-down list
loincMap.put("value", it[1] + " : " + it[2])

// Add the row to the array list
loincSelectList.add(loincMap)
}


return loincSelectList

}
}

我想要在域类中类似的东西:
<code>
static autocompleteAble = {
fields = ["code", "longName"]
}
</code>

然后从 src/templates/scaffolding/renderEditor.template 访问该数组,以获取字段名称(代码和 longName)并在 _forms.gsp 中生成正确的 html 代码并修复问题。

其他解决方案?有任何想法吗?

提前谢谢了。 ...原谅我的英语不好。

最佳答案

又读又测又测……我找到了答案,按以下步骤操作:

  • 将以下代码添加到 Domain 类:

    类域类{
    字符串代码字段;
    字符串描述字段;
    静态 autoCompleteConfig = ["codeField", "descriptionField"]
    }
  • 更改 src/templates/scaffolding/renderEditor.template(仅 renderManyToOne 方法):

    私有(private) renderManyToOne(域类,属性){
        def AUTOCOMPLETE_PROPERTY = "autoCompleteConfig"
    def className = property.type.name

    def autoCompleteProperty = org.codehaus.groovy.grails.commons.GrailsClassUtils.getStaticPropertyValue(property.referencedDomainClass.clazz, AUTOCOMPLETE_PROPERTY)
    def sb = new StringBuilder()
    // sb << "\n<!-- getFullName(): " << domainClass.getFullName() << " property.type.name: " << property.type.name << " property.referencedDomainClass.propertyName: " << property.referencedDomainClass.propertyName << " property.referencedDomainClass: " << property.referencedDomainClass << " -->\n"
    if (autoCompleteProperty != null) {

    if (autoCompleteProperty[0] ) {
    if (property.association) {

    // hidden field for domain.id

    sb << '<input type=\"hidden\" '
    sb << ' id= "' << property.name << '.id"'
    sb << ' name="' << property.name << '.id"'
    sb << ' value="${' << "${domainInstance}" << '?.id}" '
    sb << '/>\n'

    // Text field to show the description generated by autocomplete
    sb << '\t<input type=\"text\" '
    sb << ' id= "' << property.name << '_' << (autoCompleteProperty[1]? autoCompleteProperty[1]:'Description') << '\" '
    sb << ' name="' << property.name << '_' << (autoCompleteProperty[1]? autoCompleteProperty[1]:'Description') << '\" '
    if (isRequired()) sb << ' required="" '
    sb << 'style=\"width: 600px;\" '

    sb << ' value="${'
    sb << "${domainInstance}?.${property.name}" << '?.' << autoCompleteProperty[0] << '}' << (autoCompleteProperty[1]? '' : '"' )

    if (autoCompleteProperty[1]) {
    sb << ': ${' << "${domainInstance}?.${property.name}" << '?.' << autoCompleteProperty[1] << (autoCompleteProperty[2]? '}' : '}"' )
    }

    if (autoCompleteProperty[2]) {
    sb << ': ${' << "${domainInstance}?.${property.name}" << '?.' << autoCompleteProperty[2] << '}"'
    }


    sb << ' />'

    def js = new StringBuilder()
    js << '''
    <script type="text/javascript">

    /*
    * Remember include jquery and jquery-ui libraries into head section of edit.gsp file
    * < g:javascript library="jquery"/>
    * < g:javascript library="jquery-ui"/>
    *
    */

    \$(document).ready(function() {
    '''
    js << '\t\$("#' << property.name << '").focus(function(){this.select(); });\n'

    js << '\t\t\t\t\t\t' // Tabs to sort the output
    js << '\$("#' << property.name << '_' << (autoCompleteProperty[1]? autoCompleteProperty[1]:'Description') << '").autocomplete({\n'

    js << '''
    source: function(request, response){
    \$.ajax({
    // Define Remote datasource into the controller
    '''
    js << ' \t\t url: "'
    js << '/' << grails.util.Metadata.current.'app.name' << '/' << property.name << '/' << 'autoCompleteList",'

    js << '''
    data: request,
    success: function(data){
    // Get the response (JSON format)
    response(data);
    },
    error: function(){
    // Handle server errors
    response("Error after search records. Try Again.")
    }
    });
    },
    // General options: Triggered only after minimum 2 characters have been entered and others
    minLength: 2,
    delay: 1,
    autoFocus: true,
    // Event handler when user choose un item from the list.
    select: function(event, ui) {
    // update the hidden field.
    '''
    js << '\t\t\t\t '
    js << '\$("#' << property.name << '\\\\.id").val(ui.item.id);'

    js << '''

    }
    });
    });
    </script>
    '''
    sb << js
    sb as String


    }
    }
    } else {


    sb << '<g:select'
    // id is "x" and name is "x.id" as the label will have for="x" and "." in an id will confuse CSS
    sb << ' id="' << property.name << '"'
    sb << ' name="' << property.name << '.id"'
    sb << ' from="${' << property.type.name << '.list()}"'
    sb << ' optionKey="id"'
    if (isRequired()) sb << ' required=""'
    sb << ' value="${' << "${domainInstance}?.${property.name}" << '?.id}"'
    sb << ' class="many-to-one"'
    sb << renderNoSelection(property)
    sb << '/>'
    sb as String


    }

    }
  • 将 jquery 库添加到 src/templates/scaffolding/edit.gsp。记得安装 jquery 插件:

  • 在域 Controller 中编写您自己的 autoCompleteRoutine,例如:

    def autoCompleteList = {
    def domainAutoCompleteService = new DomainAutoCompleteService()
    将 domainAutoCompleteService.domainList(params) 渲染为 JSON
    }
  • 编写自己的 domainAutoCompleteService,类似于:

    包包名
    // Change the words "Domain" and "domain" with your own Domain class name
    class DomainAutoCompleteService {

    def domainList(params) {

    // Creates a new query Object
    def query = {
    or {
    // term is the parameter send by jQuery autocomplete
    like("codeField", "${params.term}%")
    like("descriptionField", "${params.term}%")
    like("otherField", "${params.term}%")
    }
    projections { // good to select only the required columns.
    property("id")
    property("codeField")
    property("descriptionField")
    }
    }

    def domainSelectList = []
    // Replace the word "Domain" by your own domain Name
    def clist = Domain.createCriteria().list(query)


    clist.each {
    // Add to map. jQuery autocomplete expects the JSON object to be with id/label/value
    def map = [:]

    map.put("id", it[0])

    // Label is text showed int he drop-down list
    map.put("label", it[1] + " : " + it[2])

    // Values is the code to be returned when the user select an item from drop-down list
    map.put("value", it[1] + " : " + it[2])

    // Add the row to the array list
    domainSelectList.add(map)
    }


    return domainSelectList

    }
    }
  • 生成 View ....瞧!一切正常。

  • 任何意见?我认为可以更优雅但这是第一步......

    关于grails - 在 CRUD grails 脚手架中自动生成 Jquery Autocomplete(一对多关系),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10587407/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com