0

grailsプロジェクトのsrc/templates / scaffolding / renderEditor.templateファイルを変更して、jqueryオートコンプリートを構成および使用するために必要なhtmlフィールドボックス(およびjavascriptコード)を、すべての関係で「多対多」に挿入しました。 1"。(コードを以下に示します)

自動生成されたオートコンプリート(_form.gsp)は正しく機能します...しかし、ユーザーがスキャフォールディングを使用してレコードを編集するときに、オートコンプリートテキストボックスに正しい値(コードと説明)を表示する必要があります。

そのためには、ドメイン内の2つのフィールドを識別する必要があります。1つはコード用で、もう1つは説明用です。

この問題に直面するために、プラグイン「constraints」を使用して2つのダミー制約を作成しようとしました。最初の制約はコードのように使用され、2番目の制約は説明のように使用されます。制約がドメイン内で数回使用される可能性があるため、このソリューションは好きではありません。

src / テンプレート/scaffolding/renderEditor.templateファイルに変更されたコードは次のとおりです:(オートコンプリートに使用される2つの入力ボックスと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}"
    }
}

コントローラー内のコード:

 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 / テンプレート/scaffolding/renderEditor.templateからこの配列にアクセスして、フィールド名(codeおよびlongName)を取得し、_forms.gspに正しいhtmlコードを生成して、問題を修正します。

他の解決策?何か案は?

よろしくお願いします。...そして私の悪い英語を許してください。

4

1 に答える 1

1

読んで、テストして、もう一度テストしてください...私は答えを見つけました、ステップに従ってください:

  1. 次のコードをDomainクラスに追加します。

    class DomainClass {String codeField; 文字列descriptionField; static autoCompleteConfig = ["codeField"、"descriptionField"]}

  2. src / テンプレート/scaffolding/renderEditor.templateを変更します(renderManyToOneメソッドのみ):

    private renderManyToOne(domainClass、property){

        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
    
    
        }
    
    }
    
  3. jqueryライブラリをsrc/templates / scaffolding/edit.gspに追加します。jqueryプラグインをインストールすることを忘れないでください:

  4. ドメインコントローラー内に、次のような独自のautoCompleteRoutineを記述します。

    def autoCompleteList = {def domainAutoCompleteService = new DomainAutoCompleteService()render domainAutoCompleteService.domainList(params)as JSON}

  5. 次のような独自のdomainAutoCompleteServiceを記述します。

    パッケージpackageName

    // 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
    
        }
    }
    
  6. ビューを生成します....そして出来上がり!すべてが機能しています。

コメントはありますか?もっとエレガントにできると思いますが、それが最初のステップです...

于 2012-05-16T17:27:09.323 に答える