복붙노트

[SPRING] grails에서 일대 다 관계를위한 동적 폼의 매개 변수 처리

SPRING

grails에서 일대 다 관계를위한 동적 폼의 매개 변수 처리

여기에서 가장 중요한 질문은 동적 양식을 통해 도메인 객체를 편집 / 업데이트 할 때 일대 다 방식을 다루는 모범 사례뿐만 아니라 하나의 동적 양식 내에서 일대 다 관계를 관리 할 때 프라 마 맵을 처리하는 것입니다. 내 질문에 대한 입력은 다음과 같습니다.

필자는 전화 번호 생성을 위해 별도의 양식을 작성한 다음 연락처에 할당 할 필요가 없으므로 하나의 동적 양식으로 아래에 표시된 도메인 개체를 만들 수있는 양식을 해킹 할 수있었습니다. 내 응용 프로그램에서 모든 것을 하나의 양식으로 만듭니다. 이전 질문에서 물어 본 것과 비슷한 것을 구현했습니다 (도와 준 사람들에게 감사드립니다).

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

내 질문은 다음과 같습니다.

고마워, 질문은 분명히 잘하면.

[편집] 좀 더 자세한 정보를 원하면 전화 정보는 [/ 편집] 형식의 자바 스크립트 (jquery)를 사용하여 동적으로 추가 및 삭제할 수 있습니다.

해결법

  1. ==============================

    1.면책 조항 : grails를 사용할 때 다음 접근 방식이 작동하는지 모르겠습니다. 나중에 알려줘.

    면책 조항 : grails를 사용할 때 다음 접근 방식이 작동하는지 모르겠습니다. 나중에 알려줘.

    동적 양식을위한 더 나은 방법을 참조하십시오. 저자는 말한다 :

    그래서 내가 뭘하는지.

    다음 색인을 저장하는 변수가 있습니다.

    var nextIndex = 0;
    

    페이지가로드되면 컬렉션에있는 자식의 수를 계산하고 nextIndex 변수를 구성하는 JavaScript 함수를 수행합니다. JQuery 또는 YUI를 사용할 수 있습니다.

    아이를 정적으로 추가하기

    템플릿 (Notice {index})을 저장하는 변수를 생성합니다.

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

    사용자가 Add child 버튼을 클릭하면, nextIndex 변수에 저장된 값으로 regex를 사용하여 {index}를 대체하고 1 씩 증가시킵니다. 그런 다음 DOM에 추가합니다.

    또한 자바 스크립트로 동적으로 HTML 요소 추가 및 제거를 참조하십시오.

    동적으로 자식 추가하기

    여기서 Paolo Bergantino 솔루션을 볼 수 있습니다.

    제거함으로써

    그러나 나는 그것을 삭제할 때 성장하는 문제라고 생각한다. 얼마나 많은 자식을 삭제해도 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"/>
    

    내가 childList1을 제거한다고 가정 할 때 나는 무엇을합니까 ??? 나는 모든 인덱스의 번호를 다시 매겨 야하나요?

    서버 측에서 AutoPopulatingList를 사용합니다. childList1이 제거되었으므로 AutoPopulatingList는이를 null로 처리합니다. 그래서 초기화에 내가 할

    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();
       }
    });
    

    이 방법으로, 내 컬렉션은 null 값이없는 두 개의 자식을 포함하며 클라이언트 측의 모든 인덱스의 번호를 다시 매길 필요가 없습니다.

    추가 / 제거에 대한 정보를 볼 수있는 링크를 볼 수 있습니다.

    Grails UI 플러그인을 참고하십시오

  2. ==============================

    2.감사,

    감사,

    귀하의 대답은 제가 더 넓은 검색을 할 수있는 몇 가지 통찰력을 가져다 주었고 실제로 제 질문의 모든 입력을 다루는 위대한 게시물을 발견했습니다. 이것은 이것을 읽는 모든 사람들을위한 참조 일뿐입니다. 곧 내 사례를 어떻게 구현했는지에 대한 블로그 항목을 작성 하겠지만,이 링크는 잘 작동하는 예제를 제공하는 좋은 소스를 제공해야한다.

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

  3. ==============================

    3.대부분의 경우 이러한 문제를 관리하기 위해 아약스를 사용합니다.

    대부분의 경우 이러한 문제를 관리하기 위해 아약스를 사용합니다.

    그래서 사용자가 새 휴대 전화 추가를 클릭하면 관리 편의성을 위해 서버에서 템플리트 UI (UI를 편집하고 전화를 업데이트하는 것과 동일한 GSP 템플릿)를 얻습니다. 이렇게하면 UI가 js 코드와 혼합되지 않습니다. UI를 변경하려면 GSP 코드 만 처리해야합니다.

    그런 다음 UI를 얻은 후 jquery DOM 조작을 사용하여 페이지에 추가합니다. 그런 다음 add (save)를 눌렀을 때 양식을 채우면 요청이 ajax를 통해 서버로 보내지고 즉시 지속됩니다.

    사용자가 전화 수정을 클릭하면 동일한 UI 템플릿이 기존 휴대 전화 데이터로 채워진 서버에서로드 된 다음 업데이트를 클릭하면 해당 휴대 전화가 ajax를 통해 즉시 업데이트되며 동일한 작업이 삭제 작업에 적용됩니다.

    그러나 언젠가 나는 유스 케이스에 대한 추가적인 시나리오를 가지고있다. "연락처를 저장할 때까지 백엔드에는 전화가 저장되지 않을 것이며, 다른 페이지로 이동하여 나중에 다시 나오면 UI의 연락처에 전화를 추가 한 후에도 전화가 저장되지 않습니다. 연락처 페이지에 내가 전에 추가 한 전화가 있어야합니다. " 어 ..

    이렇게하기 위해 나는 세션을 사용하기 시작 했으므로 위에서 설명한 작업은 DB 대신 세션에 저장된 전화 목록 개체에서 작동합니다. 이것은 phonesInSession에 대한 모든 작업을 간단하게 수행하지만 마침내 이렇게하는 것을 잊지 않습니다 (업데이트 삭제).

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

    나는 많은 데이터를 세션에 넣지 않아도된다는 것을 알고 있지만 이것이 나의 시나리오에서 얻은 유일한 해결책이다.

    누군가가 비슷한 문제 / 해결책을 가지고 있다면 의견을 남겨주세요.

  4. ==============================

    4.첫째, 모든 입력 필드 이름에 @을 추가합니다.

    첫째, 모든 입력 필드 이름에 @을 추가합니다.

    <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;
        });
    }
    

    기본적으로 replaceAllWildCardsWithConsecutiveNumbers ()의 코드는 이름에 @이 들어있는 모든 입력 (또는 선택) 요소에 대한 목록을 만드는 것입니다. 중복을 제거합니다. 그리고 나서 @를 숫자로 대체하면서 반복합니다.

    이 기능은 테이블이 있고 처음으로 도메인 클래스를 만들 때 명령 객체의 목록에 값을 제출하는 경우에 효과적입니다. 업데이트하는 경우 카운터의 값을 더 높은 값으로 변경해야합니다.

    내가이 문제에 잠시 머물렀던 이래로 이것이 다른 누군가에게 도움이되기를 바랍니다.

  5. from https://stackoverflow.com/questions/3505023/handling-parameters-from-dynamic-form-for-one-to-many-relationships-in-grails by cc-by-sa and MIT license