Обработка параметров из динамической формы для отношений один-ко-многим в Grails - PullRequest
2 голосов
/ 17 августа 2010

Мой главный вопрос здесь касается карты прам при наличии отношений один-ко-многим, управляемой в одной динамической форме, а также рекомендаций по работе с один-ко-многим при редактировании / обновлении объекта домена черездинамическая форма.Входные данные для моих вопросов следующие:

Мне удалось взломать форму, которая позволяет мне создавать доменные объекты, показанные ниже, в одной динамической форме, поскольку нет смысла иметь отдельную форму для созданияномера телефонов, а затем назначая их контакту, имеет смысл просто создать все в одной форме в моем приложении.Мне удалось реализовать нечто подобное тому, что я задал в моем предыдущем вопросе (спасибо за людей, которые помогли)

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

У меня следующие вопросы:

  • Какова лучшая практика работы с такой ситуацией, будет ли в этом случае работать объект Command, если да, где я могу найти дополнительную информацию об этом, все примеры, которые я нашел во время поиска, касаются отношений один-к-одному,Я не смог найти пример для одного ко многим?
  • Как лучше всего справиться с соотношениями телефонов в этом случае, с точки зрения добавления / удаления телефонов при редактировании объекта контакта.Я имею в виду, что логика создания проста, так как мне нужно всегда создавать новые телефоны при сохранении, но при работе с обновлением контакта пользователь мог удалить телефон и / или редактировать текущий, и / или добавить несколько новых телефонов.Прямо сейчас я просто удаляю все телефоны, которые есть у контакта, и воссоздаю их в соответствии с тем, что было опубликовано в форме, но я чувствую, что это не лучший способ сделать это, я также не думаю, что перебираю существующиеи если сравнивать с опубликованными значениями и выполнять ручное сравнение, это лучший способ сделать это, есть ли лучшая практика, как с этим справиться?

Спасибо, надеюсь, вопросы понятны.

[edit] Просто для получения дополнительной информации телефонную информацию можно динамически добавлять и удалять с помощью javascript (jquery) в форме [/ edit]

Ответы [ 4 ]

1 голос
/ 20 августа 2010

Спасибо,

Ваш ответ помог мне сделать более широкий поиск, и я на самом деле нашел отличный пост, который охватывает все входные данные в моем вопросе.Это просто ссылка для тех, кто читает это.Я скоро напишу в блоге о том, как я реализовал свое дело, но эта ссылка должна предоставить хороший источник ino с рабочим примером.

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

1 голос
/ 19 августа 2010

отказ от ответственности: я не знаю, работает ли следующий подход при использовании грааля.Дайте мне знать позже.

См. лучший способ для динамических форм .Автор говорит:

Чтобы добавить LineItems, у меня есть несколько js, которые вычисляют новый индекс и добавляют его в DOM.При удалении LineItem я должен изменить нумерацию всех индексов , и это то, чего я хотел бы избежать

Так что я делаю

У меня есть переменная, котораясохраняет следующий индекс

var nextIndex = 0;

Когда страница загружена, я выполняю функцию JavaScript, которая вычисляет, сколько дочерних элементов имеет коллекция, и настраивает переменную nextIndex.Вы можете использовать JQuery или YUI, не стесняйтесь.

Статическое добавление дочернего элемента

Я создаю переменную, в которой хранится шаблон (Примечание {index} )

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

Когда пользователь нажимает кнопку Добавить дочерний элемент , я заменяю {index} - с помощью регулярных выражений - на значение, сохраненное в nextIndexпеременная и увеличение на единицу.Затем я добавляю в DOM

См. Также Динамическое добавление и удаление элементов HTML с помощью Javascript

Динамическое добавление ребенка

Здесь вы можете увидеть решение 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"/>

Предположим, я удалил childList 1 Что я делаю ???Должен ли я перенумеровать все индексы ???

На стороне сервера я использую AutoPopulationList.Поскольку childList 1 был удален, AutoPopulationList обрабатывает его как ноль .Так что при инициализации я делаю

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

0 голосов
/ 26 мая 2017

Во-первых, во все имена полей ввода вы добавляете @:

<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 () выполняет создание списка для всех входных (или выбранных) элементов, имя которых содержит символ @. Удаляет дубликаты. И затем перебирает их, заменяя @ на число.

Это прекрасно работает, если у вас есть таблица и вы отправляете значения в список объектов команды при первом создании класса домена. Если вы обновляете, я думаю, вам придется изменить значение счетчика на что-то более высокое.

Надеюсь, это поможет кому-то еще, так как я сам на некоторое время застрял в этой проблеме.

0 голосов
/ 09 апреля 2015

Большую часть времени я использую ajax для решения такой проблемы.

Поэтому, когда пользователь нажимает add new phone, я получаю пользовательский интерфейс шаблона с сервера для удобства управления (пользовательский интерфейс - это тот же шаблон GSP, который я использую для редактирования, обновления телефона), поэтому вы не смешиваете свой пользовательский интерфейс с ваш код js, когда вы хотите изменить пользовательский интерфейс, вы должны иметь дело только с нашим кодом GSP.

Затем, после получения пользовательского интерфейса, я добавляю его на страницу, используя манипуляции с DOM в jquery. Затем после заполнения формы, когда они нажимают add(save), запрос отправляется на сервер через ajax и немедленно сохраняется.

Когда пользователь нажимает edit phone, тот же шаблон пользовательского интерфейса загружается с сервера, заполненного существующими данными телефона, затем нажатие кнопки «Обновить» немедленно обновит соответствующий телефон через ajax, и то же самое применимо к операции удаления.

Но однажды я получил дополнительный сценарий для сценария использования, который гласит: «, пока я не скажу« Сохранить контакт », телефон не будет сохранен на бэкэнде, также после добавления телефонов к контакту на интерфейсе пользователя, если перейти к еще одну страницу и вернитесь позже на страницу контактов, телефоны, которые я добавил ранее, должны быть еще там."тьфу ..

Для этого я начал использовать Session, поэтому описанные выше операции будут действовать для объекта списка телефонов, который я сохранил в сеансе, а не в БД. Это просто выполнить все операции на phonesInSession, но, наконец, не забудьте сделать это (удалить обновление):

phonesToBeDeleted = phonesInDB - phonesInSession 

phonesToBeDeleted.each{
contact.removeFromPhones(it)
it.delete()
}

Я знаю, что мне не нужно помещать много данных в сеанс, но это единственное решение, которое я получил для своего сценария.

Если у кого-то возникла подобная проблема / решение, пожалуйста, оставьте комментарий.

...