代码之家  ›  专栏  ›  技术社区  ›  omarello

grails中一对多关系的动态形式参数处理

  •  2
  • omarello  · 技术社区  · 15 年前

    我这里的主要问题是在一个动态表单中管理一对多关系时如何处理pramas映射,以及在通过动态表单编辑/更新域对象时如何处理一对多关系的最佳实践。我的问题的输入如下。

    我已经成功地破解了一个表单,它允许我在一个动态表单中创建如下所示的域对象,因为没有必要使用一个单独的表单来创建电话号码,然后将其分配给联系人,所以在我的应用程序中只需在一个表单中创建所有内容就很有意义了。我成功地实现了一些类似于我在工作中所要求的东西 Previous Question (感谢那些帮忙的人)

    class Contact{
    
        String firstName
        String lastName
        // ....
        // some other properties
        // ...
    
        static hasMany = [phones:Phone]
        static mapping = {
            phones sort:"index", cascade: "all-delete-orphan"
        }
    }
    
    class Phone{
        int index
        String number
        String type
        Contact contact
    
        static belongsTo = [contact:Contact]
    }
    

    我基本上设法从“params”映射中获取值,并自己解析它们,然后手动创建域对象和关联。也就是说,我没有使用默认支架中使用的相同逻辑,即。

    Contact c = new Contact(params)
    

    //create the contact by handpicking params values
    def cntct = new Contact()
    cntct.firstName = params.firstName
    cntct.lastName = params.lastName
    //etc...
    
    //get array of values for number,type
    def numbers = params['phone.number']
    def types =  params['phone.type']
    
    //loop through one of the arrays and create the phones
    numbers.eachWithIndex(){ num, i ->
        //create the phone domain object from 
        def phone = new Phone()
        phone.number = num
        phone.type = types[i]
        phone.index = i
        cntct.addToPhones(phone)
    }
    
    //save
    

    我的问题如下:

    • 在这种情况下,在编辑联系人对象时添加/删除电话方面,处理电话关系的最佳方法是什么。我的意思是创建逻辑很简单,因为我必须总是在保存时创建新电话,但是在处理更新联系人时,用户可能已经删除了一个电话和/或编辑了一个退出的电话和/或添加了一些新电话。现在我所做的只是删除一个联系人的所有手机,然后根据表单发布的内容重新创建它们,但我觉得这不是最好的方法,我也不认为在现有的手机上循环并与发布的值进行比较和手动差异是最好的方法,关于如何处理这个问题有没有最佳实践?

    谢谢,希望问题清楚。

    [编辑]为了获得更多信息,可以在表单[/edit]中使用javascript(jquery)动态添加和删除电话信息

    4 回复  |  直到 8 年前
        1
  •  1
  •   Community Mohan Dere    8 年前

    免责声明:我不知道下面的方法在使用grails时是否有效。以后再告诉我。

    看到了吗 better way for dynamic forms . 作者说:

    为了添加LineItems,我有一些js来计算新索引并将其添加到DOM中。删除行项目时 我得把所有的索引重新编号 这是我想避免的

    那我该怎么办

    var nextIndex = 0;
    

    静态添加子级

    {索引} )

    var child   = "<div>"
               +=     "<div>"
               +=         "<label>Name</label>"
               +=         "<input type="text" name=\"childList[{index}].name\"/>"
               +=     "</div>"
               += "</div>"
    

    当用户单击 钮扣,我换 {索引}

    另请参见 Add and Remove HTML elements dynamically with Javascript

    以数字方式添加子对象

    Here

    通过移除

    但我认为删除是长大的问题。无论移除多少子级,都不会触及nextIndex变量。看到这里了吗

    /**
      * var nextIndex = 3;
      */
    
    <input type="text" name="childList[0].name"/>
    <input type="text" name="childList[1].name"/> // It will be removed
    <input type="text" name="childList[2].name"/>
    

    假设我把 儿童名单 1 我做什么???我应该对所有索引重新编号吗???

    1 已删除,自动填充 . 所以在初始化的时候我是这样做的

    List<Child> childList = new AutoPopulatingList(new ElementFactory() {
       public Object createElement(int index) throws ElementInstantiationException {
           /**
             * remove any null value added
             */    
           childList.removeAll(Collections.singletonList(null));
    
           return new Child();
       }
    });
    

    我不需要对客户端的所有索引重新编号

    关于添加/删除,您可以看到 link 在这里我展示了一个场景,它可以给你一些启示。

    另请参见 Grails UI plugin

        2
  •  1
  •   omarello    15 年前

    谢谢,

    你的回答给我带来了一些见解,让我做了更广泛的搜索,我实际上发现了一个伟大的职位,涵盖了我的问题的所有投入。这只是一个参考,供任何人阅读。我很快就会写一篇关于我是如何实现我的案例的博客,但是这个链接应该会提供一个很好的ino资源和一个正在工作的exmaple。

    http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/

        3
  •  0
  •   dsharew    11 年前

    所以当用户点击 add new phone 为了便于管理,我从服务器上获取了模板UI(该UI与我用来编辑、更新手机的GSP模板完全相同),因此,这样您就不会将UI与js代码混合在一起,每当您想要更改UI时,您只需处理我们的GSP代码。

    在获得UI之后,我使用jquerydom操作将其添加到页面中。在填完表格之后 add(save)

    当用户单击 edit phone 从服务器加载相同的UI模板,填充已有的手机数据,然后点击update,会立即通过ajax更新相应的手机,删除操作也是如此。

    但是有一天,我得到了一个用例的附加场景,它说 “呃。。

    为此,我开始使用 Session ,因此我解释的上述操作将作用于我存储在会话中的phone list对象,而不是DB。这很简单,可以在计算机上执行所有操作 phonesInSession

    phonesToBeDeleted = phonesInDB - phonesInSession 
    
    phonesToBeDeleted.each{
    contact.removeFromPhones(it)
    it.delete()
    }
    

    如果有人有类似的问题/解决方案,请留下评论。

        4
  •  0
  •   Carlos Parraga    8 年前

    首先,在所有输入字段名称中添加@:

    <input type="text" name="references[@].name"/>
    

    <g:form action="save" onsubmit="replaceAllWildCardsWithConsecutiveNumbers();">
    

    function replaceAllWildCardsWithConsecutiveNumbers(){
        var inputs = $('form').find("[name*='@']");
        var names  = $.map(inputs, function(el) { return el.name });
        var uniqueNames = unique(names);
    
        for (index in uniqueNames) {
            var uniqueName = uniqueNames[index];                                    
            replaceWildCardsWithConsecutiveNumbers("input", uniqueName);                        
            replaceWildCardsWithConsecutiveNumbers("select", uniqueName);
        }
    }
    
    function unique(array){
        return array.filter(function(el, index, arr) {
            return index === arr.indexOf(el);
        });
    }
    
    function replaceWildCardsWithConsecutiveNumbers(inputName, name){
        counter = 0;
        $(inputName + "[name='" + name + "']").each(function (i, el) {
            var curName = $(this).attr('name');
            var newName = curName.replace("@", counter);
            $(this).attr('name', newName);
            counter += 1;
        });
    }
    

    基本上,replaceAllWildcardsWithConcertiveNumbers()的代码所做的是为名称包含@的所有输入(或选择)元素创建一个列表。删除重复项。然后对它们进行迭代,用数字替换@。

    我希望这对其他人有帮助,因为我自己也有一段时间被困在这个问题上。