У меня возникла проблема с некоторым кодом. Я не буду публиковать весь код, так как страница довольно сложная, но вот упрощенная версия.

По сути, у меня есть страница visualforce "TestPage"

<apex:page id="TestPage" controller="ControllerTestPage">
<apex:form>
    <apex:repeat value="{!allForms}" var="form">
        <c:CustomForm FormToRender="{!form}"/>
    </apex:repeat>
</apex:form>
</apex:page>

У меня есть пользовательский компонент CustomForm, который отображает форму на странице.

Важные части этого компонента приведены ниже:

<apex:actionRegion >
    <apex:actionFunction name="{!formPrefix}submitForm" action="{!submitForm}"/>

    <!--Generates a form for the user to fill in !-->
    <apex:outputPanel id="formBuilder">
    <button type="button" class="btn-primary onclick="{!formPrefix}readyFormSubmit();">Submit</button>
    <script>
    function {!formPrefix}readyFormSubmit()
    {
        //if no uploads to handle on form, submit form
        if({!formPrefix}dataIdToDownloadMap == undefined || {!formPrefix}dataIdToDownloadMap.size == 0)
            {!formPrefix}submitForm();
        //otherwise handle uploads before submitting form
        else
        {
            ...
        }

    }
  </script>
  ...

Проблема в том, что мне нужно вызвать javascript «readyFormSubmit» перед использованием функции действия для отправки формы, чтобы убедиться, что загрузка обрабатывается правильно. Теперь в документации Salesforce говорится: «Примечание. Начиная с версии API 23, вы не можете размещать apex:actionFunction внутри компонента итерации — apex:pageBlockTable, apex:repeat и т. д. Поместите apex:actionFunction после компонента итерации и внутри итерация помещает обычную функцию JavaScript, которая ее вызывает». (https://developer.salesforce.com /docs/atlas.en-us.pages.meta/pages/pages_compref_actionFunction.htm)

Но это решение для меня невозможно, так как функция действия является частью пользовательского компонента. Visualforce отказывается вызывать функцию действия, если она находится в повторителе. Если убрать повторитель, вот так:

<apex:page id="TestPage" controller="ControllerTestPage">
<apex:form>
        <c:CustomForm FormToRender="{!allForms[0]}"/>
</apex:form>
</apex:page>

Тогда пользовательская форма работает отлично. Есть ли обходные пути для такого рода проблемы?

2
Hans Donkersloot 19 Июл 2021 в 19:40

1 ответ

Вам просто нужно передать форму в качестве параметра и настроить ее по всему коду.

<button type="button" class="btn-primary onclick="readyFormSubmit('{!formPrefix}');">Submit</button>

...

<!-- in page, not individual component -->
<apex:actionFunction name="submitForm" action="{!submitForm}">
  <apex:param name="formPrefix" assignTo="{!submittedFormPrefix}" value="" />
</apex:actionFunction>

...

// Also at the page level, not individual component
function readyFormSubmit(formPrefix)
{
    //if no uploads to handle on form, submit form
    if(dataIdToDownloadMap[formPrefix] == undefined || dataIdToDownloadMap[formPrefix].size == 0)
        submitForm(formPrefix);
    //otherwise handle uploads before submitting form
    else
    {
        ...
    }
}

Вам, вероятно, потребуется настроить этот код в соответствии с вашими потребностями, поскольку этот ответ касается только кода, фактически включенного в вопрос, но, надеюсь, вы видите шаблон и можете экстраполировать оттуда.

0
sfdcfox 19 Июл 2021 в 19:52
К сожалению, такой подход не сработает. «SubmitForm» — это действие на контроллере пользовательского компонента. Это компонент, используемый на нескольких страницах Visualforce, поэтому нецелесообразно создавать функцию submitForm на каждой странице, которая его использует. Если есть решение, в котором я могу полностью исключить actionFunction, это действительно то, что я ищу.
 – 
Hans Donkersloot
19 Июл 2021 в 20:21
Нет, это не сыграет в вашу пользу. Метод должен быть в контроллере страницы. Помните, что JavaScript используется на всей странице в Visualforce. Этот дизайн будет очень хорошо работать в Aura/LWC, но не в Visualforce. Вместо этого вам придется изменить кнопку на apex:commandButton и выполнить любую проверку, которую вы хотите выполнить, используя onclick="{!formPrefix}validate()" или что-то в этом роде.
 – 
sfdcfox
19 Июл 2021 в 22:23
Возможно, я неправильно понимаю, но я не уверен, почему метод должен быть в контроллере страницы. {!formPrefix} используется, чтобы сделать каждый вызов javascripts customForm уникальным. Каждая форма имеет уникальный идентификатор, установленный при ее создании. это делает определения JavaScript уникальными для формы. Например, {!formPrefix}readyFormSubmit() превращается в: form_0_readyFormSubmit(), а следующая форма будет иметь определение: form_1_readyFormSubmit() -- Опять же, возможно, я чего-то не понимаю, но я использовал этот подход в прошлое, чтобы определить функции JS в повторителе
 – 
Hans Donkersloot
20 Июл 2021 в 00:11
Как говорят документы, это больше не разрешено. Предположительно, была ошибка или что-то в этом роде, поэтому они «объявили» это вне закона. Повторяющаяся логика в Visualforce в целом довольно глючна из-за технологии, на которой она основана (JSP). Лучше писать код в Lightning и использовать Lightning Out.
 – 
sfdcfox
20 Июл 2021 в 00:52