1

This has me a bit stumped.

I have two forms - posting to two different actions within the same controller. On error I am attempting to have them both display a flash-notice, as well as pass the model back to my template so that I can display the errors to the user.

This works as intended for one of my forms/actions, but not for the other - well, that is, the flash-message works for both, but for the latter form/action model is undefined in my template.

Some examples (I've stripped out some code to not clutter the question):

Working action

public function actionCreateArtist()
{
  $this->requirePostRequest();
  $request = craft()->request->getPost();
  $model   = new CoverApp_ArtistModel();
  $model->setAttributes($request);
  if ($model->validate() && craft()->coverApp_data->createArtist($model)) {
    craft()->userSession->setNotice('Artist created.');
    $this->redirectToPostedUrl();
  }
  craft()->userSession->setError('Unable to create artist');
  craft()->urlManager->setRouteVariables(array('model' => $model));
}

Working form

<form method="POST" class="styled-form">
  {{ getCsrfInput() }}
  <input type="hidden" name="action" value="coverApp/data/createArtist">
  <input type="hidden" name="redirect" value="coverapp/record-company/{{ companyId }}">
  <input type="submit" value="Create artist">
</form>
{{ model is defined ? 'Yes' : 'No' }}
{% set error = craft.session.getFlash('error', false, false) %}
{% if error and model is defined %}
  <div>
    <ul>
      {% for errorType in model.getErrors() %}
        {% for error in errorType %}
          <li>- {{ error }}</li>
        {% endfor %}
      {% endfor %}
    </ul>
  </div>
{% endif %}

The example above outputs "Yes" and any errors that happened during validation/save, per-example name already taken.

Action I am struggling with

public function actionCreateRecordCompany()
{
  $this->requirePostRequest();
  $request = craft()->request->getPost();
  $model   = new CoverApp_RecordCompanyModel();
  $model->setAttributes($request);
  if ($model->validate() && craft()->coverApp_data->createRecordCompany($model)) {
    craft()->userSession->setNotice('Record company created.');
    $this->redirectToPostedUrl();
  }
  craft()->userSession->setError('Unable to create record-company');
  craft()->urlManager->setRouteVariables(array('model' => $model));
}

Form I am struggling with

<form method="POST" class="styled-form">
  {{ getCsrfInput() }}
  <input type="hidden" name="action" value="coverApp/data/createRecordCompany">
  <input type="hidden" name="redirect" value="coverapp">
  <input type="submit" value="Create record-company">
</form>
{{ model is defined ? 'Yes' : 'No' }}
{% set error = craft.session.getFlash('error', false, false) %}
{% if error and model is defined %}
  <div>
    <ul>
      {% for errorType in model.getErrors() %}
        {% for error in errorType %}
          <li>- {{ error }}</li>
        {% endfor %}
      {% endfor %}
    </ul>
  </div>
{% endif %}

The above outputs 'No' and none of the errors that happened during validation/save, per example name already taken.

To further obfuscate the problem, if I have no errors during validation/save everything works peachy - which at least leads me to believe that my models are fine.

Any ideas?

Update 31/10/2016

registerCpRoutes

public function registerCpRoutes()
{
  return array('coverapp/record-company/create' => array('action' => 'coverApp_Rendering/renderCreateRecordCompany'),
  'coverapp/record-company/(?P<companyId>[\d]+)/createArtist' => array('action' => 'coverApp_Rendering/renderCreateArtist'));
}

rendering-controller

public function actionRenderCreateRecordCompany()
{
  $this->renderPluginTemplate('coverapp/recordCompanyCreate');
}

public function actionRenderCreateArtist(array $variables = array())
{
  $this->renderPluginTemplate('coverapp/artistCreate', $variables);
}

private function renderPluginTemplate($template, $variables = array())
{
  $oldMode = craft()->templates->getTemplateMode();
  craft()->templates->setTemplateMode(TemplateMode::Site);
  if (!$templatePath = craft()->templates->findTemplate($template)) {
    throw new Exception(Craft::t('Could not find template with path: ' . $template));
  }
  else {
    $templateContent   = file_get_contents($templatePath);
    $templateExtension = IOHelper::getExtension($templatePath, 'html');
  }
  craft()->templates->setTemplateMode($oldMode);
  if ($output = craft()->templates->renderString($templateContent, $variables)) {
    if (!HeaderHelper::isHeaderSet('Content-Type')) {
      HeaderHelper::setContentTypeByExtension($templateExtension);
    }
    HeaderHelper::setHeader(array('charset' => 'utf-8'));
    if (in_array(HeaderHelper::getMimeType(), array('text/html', 'application/xhtml+xml'))) {
      $headHtml = craft()->templates->getHeadHtml();
      $footHtml = craft()->templates->getFootHtml();
      if ($headHtml) {
        if (($endHeadPos = mb_stripos($output, '</head>')) !== FALSE) {
          $output = mb_substr($output, 0, $endHeadPos) . $headHtml . mb_substr($output, $endHeadPos);
        }
        else {
          $output .= $headHtml;
        }
      }
      if ($footHtml) {
        if (($endBodyPos = mb_stripos($output, '</body>')) !== FALSE) {
          $output = mb_substr($output, 0, $endBodyPos) . $footHtml . mb_substr($output, $endBodyPos);
        }
        else {
          $output .= $footHtml;
        }
      }
    }
    ob_start();
      echo $output;
      craft()->end();
    }
}
2
  • 1
    For the second form, is there another controller action that is getting called to render the form in the first place? (It’s possible to have a request get routed to a controller action using the registerCpRoutes hook.) Commented Oct 27, 2016 at 13:50
  • @BrandonKelly: Original post updated with code from both registerCpRoutes and the rendering-controller Commented Oct 31, 2016 at 9:36

1 Answer 1

1

So, it turns out (as is often the case) that posting the problem makes you look at it in a fresh light, and as such I found my own solution.

What I needed to do (leaving this here in case someone else has a similar problem and come looking for help) was to make the following change to my rendering-controller:

old

public function actionRenderCreateRecordCompany()
{
  $this->renderPluginTemplate('coverapp/recordCompanyCreate');
}

new

public function actionRenderCreateRecordCompany(array &variables = array())
{
  $this->renderPluginTemplate('coverapp/recordCompanyCreate');
}

I guess this makes sense - I didn't include it originally as my route never passed any variables to it - but of course when I use setRouteVariables in my controller-action I need something on the receiving end to catch it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.