Grails GSP с - PullRequest
       66

Grails GSP с

0 голосов
/ 20 февраля 2019

grails v3.3.9 и bootstrap.

Я боролся за то, чтобы grails, поля и начальная загрузка работали без проблем при обработке Java LocalDateTime.Почти там, но не совсем ...

Я создал /fields/localdateTime/_widget.gsp, как это

<div class="input-group date col-sm-8"  >
    <input id="${property}-label" name="${property}" type='datetime-local' class="form-control" value="${value}" placeholder="<empty>"/>
    <div class="input-group-append" >
        <button class="btn btn-icon-fixed-width btn-outline-secondary btn-block" disabled aria-disabled="true" type="button" >
            <i class="fas fa-calendar"></i>
        </button>
    </div>
</div>

, в котором используется начальная загрузка

, когда действие редактирования запускается наshow view, он корректно отображает это поле в форме редактирования и плагин fields, читает _widget.gsp и корректно отображает поле.

Элемент управления (в Chrome), кажется, работает нормально, и я могу выбрать дату и установить время в поле ввода

однако, когда я отправляю кнопку обновления, данные отправляются обратнок действию обновления не не забирает мое измененное значение даты, а скорее отправляет исходное значение, которое было в объекте домена перед этим.

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

def update(BootstrapTest bootstrapTest) {
    if (bootstrapTest == null) {
        notFound()
        return
    }


    if (!bootstrapTest.validate()){
        println "object delivered to update action from edit form doesnt validate "
        respond bootstrapTest.errors, view:'edit'
        return
    }

однако, хотя это выглядит нормально - при попытке проверить это не удается

, а в браузере отображается "Свойство ldtProp не соответствует типу«.Что не так с валидацией LocalDateTime?

Я могу создать данные начальной загрузки grails и сохранить их в db, так что это не класс домена и не валидация при сохранении таким способом - это только когда запись доставляется контроллеру, и она ломается

Я пробовал эквивалентное поле с LocalDate - и это, кажется, работает и правильно проверяет, и я могу сохранить объект, опубликованный в действии обновления контроллера.

Это просто так расстраиваетКто-нибудь проясняет, что это не получается и что нужно сделать, чтобы исправить это?

этот последний бит меня озадачил.

для того, чтобы бороться с тем, что плагин полей на самом деле делает, я получилприватная версия здесь личная копия плагина с настроенным контентом

я запустил его как плагин приватного клона полей, потому что я не мог наблюдать за тем, что происходило под прикрытием, так что у него есть номербиблиотек, таблиц стилей, импортированных обратно, чтобы я мог сделать отладку на месте.различные / поля / xxx / * gsp, определенные для отображения формы начальной загрузки / битов дисплея.

1 Ответ

0 голосов
/ 20 февраля 2019

Blimey, еще одно гнездо червей ...

Во-первых, <input type="date" или <input type="datetime-local" в интерпретации chrome отображает значение браузера как 'mm / dd / yyyy' для даты и для datetime-локальный как мм / дд / гггг ЧЧ: мм: (сс: SSS - выделен серым цветом)

Когда вы предоставляете value="string", он игнорирует вашу строку - поэтому вы должны передать фактический значение на входе как значение = "$ {значение}".Если вы преобразуете это в форматированное поле раньше, то оно игнорируется, и отображается шаблон по умолчанию.

Следующая проблема - при отправке формы значение, отправленное в ваш блок params, фактически является строкой в ​​формате ISO, а неa LocalDateTime и т. д.

Поэтому, когда Grails пытается загрузить для вас запись из базы данных и вставить ее в ваш контроллер, он уже пытался обновить запись один раз.

Проблема в том, что этопроизвел проверку, которая уже не удалась.Поэтому, когда вы получаете объект домена в вашем методе «Update (Domain xxx) {...}», объект уже имеет свои ошибки.

Поэтому я попытался преобразовать строки, отправленные в параметрах, в LocalDateTime, LocalDate, а затем обновить мой объект домена в контроллере - но они потерпели неудачу при использовании validate () в качестве ранее существовавших ошибок там, где они уже есть.

Поэтому мне пришлось сначала удалить ошибки, а затем преобразовать строки параметров вправоТипы дат Java, а затем обновить объект домена и затем проверить.Тогда это радует.

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

def update(BootstrapTest bootstrapTest) {
    if (bootstrapTest == null) {
        notFound()
        return
    }

    LocalDateTime ldtProp
    LocalDate dtProp

    if (bootstrapTest.hasErrors()) {
        bootstrapTest.clearErrors()
        try {
            ldtProp = LocalDateTime.parse(params.ldtProp?.toString()) //ISO_LOCAL_DATE_TIME
            dtProp = LocalDate.parse(params.dtProp?.toString(), DateTimeFormatter.ISO_LOCAL_DATE) //ISO_LOCAL_DATE
            bootstrapTest.ldtProp =  ldtProp
            bootstrapTest.dtProp = dtProp
            bootstrapTest.validate()
        } catch (ex) {
            println "exception $ex.message"
            respond bootstrapTest.errors, view:'edit'
            return
        }
    }


    try {
        bootstrapTestService.save(bootstrapTest)
    } catch (ValidationException e) {
        respond bootstrapTest.errors, view:'edit'
        return
    } ...

Итак, сначала очистите ошибки - затем исправьте / преобразуйте формат карты параметров в формат объекта домена, и это нормально.для свойства класса домена (или определить метод set в домене, который принимает строку и выполняет преобразование внутри)

Как только вы это сделаете, на этот раз повторная проверка завершится успешно, и обновления контроллера / БД начнут работать.

Без использования пользовательских средств выбора даты и т. Д. (И для лесов, которые являются излишними) вам придется жить с текущей обработкой данных для

Я не пробовал это в другом браузере, но Chrome - мой «обычный» браузер разработчика и ведет себякак указано выше.

- PS - дополнительная трассировка.В фоновом режиме, когда объект Domain расположен и загружен, Grails, кажется, имеет преобразователь из String в DateTime, потому что я создал setDtProp (dt) setter - и это вызывается с преобразованным значением, прежде чем объект будет доставлен в контроллер - которыйВот почему я увидел первоначально описанное изменение dtProp, но не изменило ldtProp (где я добавил сеттер также в доменном объекте).

Таким образом, как бы Grails ни выполнял процесс внедрения, он не делает это для LocalDateTime как строки из браузера (но он помещает строку в параметры для вас), но он вызывает метод установки для LocalDate.В любом случае, когда объект домена загружен, его ошибки () были установлены - поэтому вам нужно обработать это с контроллера, как показано.Попытка исправить с помощью сеттеров в классе Domain не работает для LocalDateTime, так как ваш сеттер никогда не вызывается!

Это может быть обработано в контроллере только после того, как объект введен, как показано выше, как я начал делать в первую очередь.

...