Thymeleaf: Ни BindingResult, ни простой целевой объект для имени компонента '#ids' не доступны в качестве атрибута запроса - PullRequest
0 голосов
/ 22 марта 2020

Краткое описание проблемы

Я пытаюсь создать входные данные, имя и идентификатор которых 'workingDay *' (* - последовательный номер). Я сталкивался с сообщениями об ошибках. Кажется, что произошла ошибка во время анализа "$ {# ids.next ('workingDay')}"

Библиотеки

  • JDK: AdoptOpenJDK: 11.0.5
  • Spring Framework: 5.2.2.RELEASE
  • Thymeleaf Spring: 3.0.11.RELEASE

Сообщения об ошибках

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name '#ids' available as request attribute
    at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153)
    at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:903)
    at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:258)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227)
    at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
    at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
    at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
    at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314)
    at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205)
    at org.thymeleaf.engine.Model.process(Model.java:282)
    at org.thymeleaf.engine.Model.process(Model.java:290)
    at org.thymeleaf.engine.IteratedGatheringModelProcessable.processIterationModel(IteratedGatheringModelProcessable.java:367)
    at org.thymeleaf.engine.IteratedGatheringModelProcessable.process(IteratedGatheringModelProcessable.java:221)
    at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1640)
    at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleCloseElementEnd(TemplateHandlerAdapterMarkupHandler.java:388)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleCloseElementEnd(InlinedOutputExpressionMarkupHandler.java:322)
    at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleCloseElementEnd(OutputExpressionInlinePreProcessorHandler.java:220)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleCloseElementEnd(InlinedOutputExpressionMarkupHandler.java:164)
    at org.attoparser.HtmlElement.handleCloseElementEnd(HtmlElement.java:169)
    at org.attoparser.HtmlMarkupHandler.handleCloseElementEnd(HtmlMarkupHandler.java:412)
    at org.attoparser.MarkupEventProcessorHandler.handleCloseElementEnd(MarkupEventProcessorHandler.java:473)
    at org.attoparser.ParsingElementMarkupUtil.parseCloseElement(ParsingElementMarkupUtil.java:201)
    at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:725)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
    at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:158)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:834)

Шаблон Thymeleaf (от строки 30 до строка 74)

<form action="#" id="helper_add" method="post" th:object="${helperForm}">
  <div class="form-row">
    <div class="form-group col-sm-6">
      <label for="inputName">First Name</label>
      <input type="text" class="form-control" id="inputName" placeholder="First Name" th:field="*{firstName}" th:value="*{firstName}">
    </div>
    <div class="form-group col-sm-6">
      <label for="inputKana">Last Name</label>
      <input type="text" class="form-control" id="inputKana" placeholder="Last Name" th:field="*{lastName}" th:value="*{lastName}">
    </div>
  </div>
  <div class="form-row" th:each="i : ${#numbers.sequence(1, 3)}">
    <div class="form-group bmd-form-group col-4 col-sm-2">
      <label th:for="${#ids.next('workingDay')}" class="bmd-label-static working-day-header">Working day 1</label>
      <select class="working-day-body form-control selectpicker" data-style="btn" th:field="${#ids.next('workingDay')}">
        <option value="7">Sun</option>
        <option value="1">Mon</option>
        <option value="2">Tue</option>
        <option value="3">Wed</option>
        <option value="4">Thu</option>
        <option value="5">Fri</option>
        <option value="6">Sat</option>
      </select>
    </div>
    <div class="form-group bmd-form-group col-6 col-sm-4">
      <label class="bmd-label-static working-time-header">Working time 1</label>
      <input type="time" class="working-time-from form-control d-inline" th:field="${#ids.next('timeFrom')}" th:value="${#ids.next('timeFrom')}">~
      <input type="time" class="working-time-to form-control d-inline" th:field="${#ids.next('timeTo')}" th:value="${#ids.next('timeTo')}">
    </div>
    <div class="form-group col-2 col-sm-1">
      <label class="form-check-label" for="chkbox01">All day</label>
      <input id="chkbox03" name="chkbox01" type="checkbox" class="d-block is-all-day" style="margin:1rem .125rem;">
    </div>
    <div class="form-group col-2">
      <label for="">Actions</label>
      <div class="td-actions">
        <button type="button" rel="tooltip" class="btn btn-small btn-success btn-add-line">
          <i class="material-icons d-inline">add</i>
        </button>
        <button type="button" rel="tooltip" class="btn btn-small btn-danger btn-delete-line">
          <i class="material-icons d-inline">delete</i>
        </button>
      </div>
    </div>
  </div>
</div>

желаемый вывод

<form action="#" id="helper_add" method="post" th:object="${helperForm}">
  <div class="form-row">
    <div class="form-group col-sm-6">
      <label for="inputName">First Name</label>
      <input type="text" class="form-control" id="inputName" placeholder="First Name" th:field="*{firstName}" th:value="*{firstName}">
    </div>
    <div class="form-group col-sm-6">
      <label for="inputKana">Last Name</label>
      <input type="text" class="form-control" id="inputKana" placeholder="Last Name" th:field="*{lastName}" th:value="*{lastName}">
    </div>
  </div>
  <div class="form-row">
    <div class="form-group bmd-form-group col-4 col-sm-2">
      <label for="workingDay1" class="bmd-label-static working-day-header">Working day 1</label>
      <select class="working-day-body form-control selectpicker" data-style="btn" id="workingDay1" name="workingDay1">
        <option value="7">Sun</option>
        <option value="1">Mon</option>
        <option value="2">Tue</option>
        <option value="3">Wed</option>
        <option value="4">Thu</option>
        <option value="5">Fri</option>
        <option value="6">Sat</option>
      </select>
    </div>
    <div class="form-group bmd-form-group col-6 col-sm-4">
      <label class="bmd-label-static working-time-header">Working time 1</label>
      <input type="time" class="working-time-from form-control d-inline" id="timeFrom1" name="timeFrom1" value="(object value)">~
      <input type="time" class="working-time-to form-control d-inline" id="timeTo1" name="timeTo1" value="(object value)">
    </div>
    <div class="form-group col-2 col-sm-1">
      <label class="form-check-label" for="chkbox01">All day</label>
      <input id="chkbox03" name="chkbox01" type="checkbox" class="d-block is-all-day" style="margin:1rem .125rem;">
    </div>
    <div class="form-group col-2">
      <label for="">Actions</label>
      <div class="td-actions">
        <button type="button" rel="tooltip" class="btn btn-small btn-success btn-add-line">
          <i class="material-icons d-inline">add</i>
        </button>
        <button type="button" rel="tooltip" class="btn btn-small btn-danger btn-delete-line">
          <i class="material-icons d-inline">delete</i>
        </button>
      </div>
    </div>
  </div>
  <div class="form-row">
    <div class="form-group bmd-form-group col-4 col-sm-2">
      <label for="workingDay1" class="bmd-label-static work-day-header">Working day 2</label>
      <select class="working-day-body form-control selectpicker" data-style="btn" id="workingDay2" name="workingDay2">
        <option value="7">Sun</option>
        <option value="1">Mon</option>
        <option value="2">Tue</option>
        <option value="3">Wed</option>
        <option value="4">Thu</option>
        <option value="5">Fri</option>
        <option value="6">Sat</option>
      </select>
    </div>
    <div class="form-group bmd-form-group col-6 col-sm-4">
      <label class="bmd-label-static work-time-header">Working time 2</label>
      <input type="time" class="working-time-from form-control d-inline" id="timeFrom2" name="timeFrom2" value="(object value)">~
      <input type="time" class="working-time-to form-control d-inline" id="timeTo2" name="timeTo2" value="(object value)">
    </div>
    <div class="form-group col-2 col-sm-1">
      <label class="form-check-label" for="chkbox01">All day</label>
      <input id="chkbox03" name="chkbox01" type="checkbox" class="d-block is-all-day" style="margin:1rem .125rem;">
    </div>
    <div class="form-group col-2">
      <label for="">Actions</label>
      <div class="td-actions">
        <button type="button" rel="tooltip" class="btn btn-small btn-success btn-add-line">
          <i class="material-icons d-inline">add</i>
        </button>
        <button type="button" rel="tooltip" class="btn btn-small btn-danger btn-delete-line">
          <i class="material-icons d-inline">delete</i>
        </button>
      </div>
    </div>
  </div>
  <div class="form-row">
    <div class="form-group bmd-form-group col-4 col-sm-2">
      <label for="workingDay1" class="bmd-label-static work-day-header">Working day 3</label>
      <select class="working-day-body form-control selectpicker" data-style="btn" id="workingDay3" name="workingDay3">
        <option value="7">Sun</option>
        <option value="1">Mon</option>
        <option value="2">Tue</option>
        <option value="3">Wed</option>
        <option value="4">Thu</option>
        <option value="5">Fri</option>
        <option value="6">Sat</option>
      </select>
    </div>
    <div class="form-group bmd-form-group col-6 col-sm-4">
      <label class="bmd-label-static work-time-header">Working time 3</label>
      <input type="time" class="working-time-from form-control d-inline" id="timeFrom3" name="timeFrom3" value="(object value)">~
      <input type="time" class="working-time-to form-control d-inline" id="timeTo3" name="timeTo3" value="(object value)">
    </div>
    <div class="form-group col-2 col-sm-1">
      <label class="form-check-label" for="chkbox01">All day</label>
      <input id="chkbox03" name="chkbox01" type="checkbox" class="d-block is-all-day" style="margin:1rem .125rem;">
    </div>
    <div class="form-group col-2">
      <label for="">Actions</label>
      <div class="td-actions">
        <button type="button" rel="tooltip" class="btn btn-small btn-success btn-add-line">
          <i class="material-icons d-inline">add</i>
        </button>
        <button type="button" rel="tooltip" class="btn btn-small btn-danger btn-delete-line">
          <i class="material-icons d-inline">delete</i>
        </button>
      </div>
    </div>
  </div>
</div>

1 Ответ

0 голосов
/ 23 марта 2020

Мне удалось получить вывод, что я хотел. Я изменил шаблон, как показано ниже.

th: для

, заменив #ids.next('*') на ${'*' + i}".

th: field и th: value

замена #ids.next('*') на *{__${'*' + i}__}>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...