Grails
  1. Grails
  2. GRAILS-3000

Using the default scaffolding template for an Edit view, the "Add" link for a One-to-Many relationship does not cause the correct owner object to be selected in the "Create" editor for the related object

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.0.2
    • Fix Version/s: None
    • Component/s: Scaffolding
    • Labels:
      None
    • Environment:
      All
    • Patch Submitted:
      Yes

      Description

      To reproduce the problem, set up a domain model as follows:

      class Container {
          static hasMany = {
              items: Item
          }
      }
      
      class Item {
          static belongsTo = [ container: Container ]
          
          Container container
      }
      

      When using dynamic scaffolding, the "Edit" page for Container will look something like this:

      Items:

      • Item A
      • Item B
        ...
        <<Add Item>>

      Clicking the <<Add Item>> link opens the "Create" page for the Item. This page includes a <select> drop-down to choose the owning Container. The select should be defaulted to the Container from which we clicked the <<Add Item>> link, but it is not.

      The root cause is that the code to generate the <<Add Item>> link is broken.

      Looking in the renderEditor.template from the scaffolding code, you will see the following code on line 74:

      pw.println "<g:link controller=\"${property.referencedDomainClass.propertyName}\" params=\"[\"${domainClass.propertyName}.id\":${domainClass.propertyName}?.id]\" action=\"create\">Add ${property.referencedDomainClass.shortName}</g:link>"
      

      There are two problems:

      Problem 1 - $

      {domainClass.propertyName}?.id should not be surrounded by double quotes, but by single quotes. This causes the generated GSP code to never process the params declaration.

      Problem 2 - ${domainClass.propertyName}

      will only work if the back-reference on the Item object happens to have the same name as the type (i.e. container). If the field has a different name (e.g. myContainer), this will fail. The resolution to this is to use $

      {property.otherSide.name} instead. This will give the actual name of the back-reference on the Item object.

      The complete fix for this is to change line 74 of renderEditor.template to the below:

      pw.println "<g:link controller=\"${property.referencedDomainClass.propertyName}\" params=\"['${property.otherSide.name}

      .id':$

      {domainClass.propertyName}

      ?.id]\" action=\"create\">Add $

      {property.referencedDomainClass.shortName}

      </g:link>"

      I've attached a corrected version of the file.

      It's a quick fix - hopefully someone can commit it for me.

      Thanks!

        Activity

        Hide
        Martin Vlcek added a comment -

        The above solution will crash, if there is no property on the other side, thus the code in renderOneToMany should be:
        ...
        if (property.otherSide) {
        pw.println "<g:link controller=\"$

        {property.referencedDomainClass.propertyName}\" params=\"['${property.otherSide.name}.id':${domainInstance}?.id]\" action=\"create\">Add ${property.referencedDomainClass.shortName}</g:link>"
        } else {
        pw.println "<g:link controller=\"${property.referencedDomainClass.propertyName}

        \" action=\"create\">Add $

        {property.referencedDomainClass.shortName}

        </g:link>"
        }
        ...

        Show
        Martin Vlcek added a comment - The above solution will crash, if there is no property on the other side, thus the code in renderOneToMany should be: ... if (property.otherSide) { pw.println "<g:link controller=\"$ {property.referencedDomainClass.propertyName}\" params=\" ['${property.otherSide.name}.id':${domainInstance}?.id] \" action=\"create\">Add ${property.referencedDomainClass.shortName}</g:link>" } else { pw.println "<g:link controller=\"${property.referencedDomainClass.propertyName} \" action=\"create\">Add $ {property.referencedDomainClass.shortName} </g:link>" } ...

          People

          • Assignee:
            Unassigned
            Reporter:
            Percy M. Wegmann
          • Votes:
            1 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Last Reviewed:

              Development