Multi-Page Form in Zend is Validating All Forms too early - zend-framework

I have been working through the Multi Page forms tutorial in the Zend Form Advanced Usage section of the documentation, http://framework.zend.com/manual/en/zend.form.advanced.html.
My first page loads fine, however when I submit it, the second page loads and it includes validation error messages. (Obviously I don't want to see validation errors for this page until the user has filled in the fields...)
I have tracked it down to the final line in the formIsValid() function. It seems that here validation is run for all elements in the three forms (not just the current one), so it's really no surprise that errors are showing on the second page.
I have tried the suggestion in the comments at the end of the tutorial, i.e. $data[$key] = $info[$key].
Have you had a crack at this tutorial? How did you solve the problem?
Any assistance is much appreciated!

I encountered the same problem this is how I solve it.
By replacing
public function formIsValid()
{
$data = array();
foreach ($this->getSessionNamespace() as $key => $info) {
$data[$key] = $info;
}
return $this->getForm()->isValid($data);
}
With
public function formIsValid()
{
$data = array();
foreach ($this->getSessionNamespace() as $key => $info) {
$data[$key] = $info[$key];
}
return (count($this->getStoredForms()) < count($this->getPotentialForms()))? false : $this->getForm()->isValid($data);
}

The documentations reads:
Currently, Multi-Page forms are not
officially supported in Zend_Form;
however, most support for implementing
them is available and can be utilized
with a little extra tooling.
The key to creating a multi-page form
is to utilize sub forms, but to
display only one such sub form per
page. This allows you to submit a
single sub form at a time and
validate it, but not process the form
until all sub forms are complete.
Are you sure you have been validating a single sub-form instead of just whole form?

Related

Remove submitted state in submission handler

I am trying to reset a form so that it appears to Drupal 8 that it hasn't been submitted. So far I have been unable to do this, as I cannot find any available methods (setSubmitted() hardcodes it to TRUE without a FALSE option). The reason is this isn't a full submit, but a submit of one field after which I would like the user to be redirected to another page that has another form, and I would like this secondary form to use the value obtained in the first step.
In the submit handler for the first part I use this to redirect:
$form_state->setRedirect('my.route', [], []);
And this works, but when the form reaches the second form (it seems) that the second form thinks it is a submission. As a result any submit buttons I add to the second form seem to make it auto-submit, and this breaks my user journey.
In the submit for the first part I have tried:
$form_state->setRebuild(TRUE);
$form_state = new FormState();
unset($form_state);
Tried the above in various configurations to no avail. They all prevent/ignore the setRedirect call that I make afterwards. The reason I want/need to do it this way is I want to preserve the POST method used.
Do you want to obtain something similar to what core search module does? It has simple SearchBlockForm that sends data to more complex SearchPageForm.
SearchBlockForm uses GET method (though you may use POST):
$form['#method'] = 'get';
and has no id and token fields:
function search_form_search_block_form_alter(&$form, FormStateInterface $form_state) {
$form['form_build_id']['#access'] = FALSE;
$form['form_token']['#access'] = FALSE;
$form['form_id']['#access'] = FALSE;
}
BTW, the last change allows you to avoid running submit callbacks.
Hope this helps.

Render comments form in any page

I want to know how to render a comments form of a specific node in any page (ex. user profile). I've trying with drupal_get_form but it shows an error.
drupal_get_form('mytype_node_form', array('nid' => $nid));
Solutions & clues are welcome :)
First of all, you should use the proper ID of the comment form: 'comment_form' instead of 'mytype_node_form'.
The code
drupal_get_form('comment_form', array('nid' => $nid));
used to work for me in Drupal 6. In Drupal 7, function comment_form() is expecting an object parameter instead of array. This code should work for you:
$comment = new stdClass;
$comment->nid = $nid;
$form = drupal_get_form('comment_form', $comment);

Atk4 Step by Step form doesn't load Facebook Like Buttons

I have a array with list of sites, I'm coding a step by step form using http://codepad.agiletoolkit.org/newsletter example.
In the second step I put Like Buttons using the following code:
$attr = array (
'data-send' => FALSE,
'data-layout' => 'button_count',
'data-width' => 100,
'data-show-faces' => FALSE
);
foreach($this->sites as $k => $site) {
$div = $form->add('View_HtmlElement')->setElement('div')->set(NULL);
$attr['data-href'] = $site;
$div->addClass('fb-like');
$div->setAttr($attr);
}
This works good when I access directly, but when I try to access via next button, the Like Buttons doesn't load.
Any solution for this?
The reason why the facebook and some other buttons may not work with AJAX pages is because facebook scripts generally process your HTML only during initial load of the page. When the form in your example goes to next step, it uses AJAX to load additional form. As a result you will need to either manually trigger facebook's scripts to re-walk your page or perform redirects instead of reload. You would need to change:
$this->js()->atk4_load($this->api->getDestinationURL('./step2'))
->execute();
to
$this->js()->univ()->location($this->api->getDestinationURL('./step2'))
->execute();
You may also find this article useful: http://agiletoolkit.org/blog/adding-twitter-button-to-ajax-page/

Joomla: Is there a module render plugin event?

Due to some caching issues, I need to explicitly bypass the cache, for a specific module, if certain URL parameters are present. The workaround I've arrived at is to hack the render() function in libraries/joomla/document/html/renderer/module.php, along the lines of:
function render( $module, $params = array(), $content = null )
{
// Existing code:
$mod_params = new JParameter( $module->params );
// My hack:
if ($module->module == 'mod_foo')
{
if (certain URL parameters are present)
{
$mod_params->set('cache', 0);
}
}
...
}
Of course, hacking the core joomla code is a terrible idea, one which I'd like to avoid if at all possible. So, is there an appropriate hook I can plugin to in order to achieve the same? I don't think I can do anything at the module level, since it won't even be inspected if the renderer has already decided to fetch it from cache.
To answer the first question no there isn't a module render event, here's the plugin doc's and the list of events in Joomla!
Turn off caching for your module.
See this article on The Art Of Joomla, additional articles you could look at:
Using Cache to Speed Up your code
JCache API

What's the best method to generate Multi-Page PDFs with Perl and PDF::API2?

I have been using PDF::API2 module to program a PDF. I work at a warehousing company and we are trying switch from text packing slips to PDF packing slips. Packing Slips have a list of items needed on a single order. It works great but I have run into a problem. Currently my program generates a single page PDF and it was all working fine. But now I realize that the PDF will need to be multiple pages if there are more than 30 items in an order. I was trying to think of an easy(ish) way to do that, but couldn’t come up with one. The only thing I could think of involves creating another page and having logic that redefines the coordinates of the line items if there are multiple pages. So I was trying to see if there was a different method or something I was missing that could help but I wasn’t really finding anything on CPAN.
Basically, i need to create a single page PDF unless there are > 30 items. Then it will need to be multiple.
I hope that made sense and any help at all would be greatly appreciated as I am relatively new to programming.
Since you already have the code working for one-page PDFs, changing it to work for multi-page PDFs shouldn't be too hard.
Try something like this:
use PDF::API2;
sub create_packing_list_pdf {
my #items = #_;
my $pdf = PDF::API2->new();
my $page = _add_pdf_page($pdf);
my $max_items_per_page = 30;
my $item_pos = 0;
while (my $item = shift(#items)) {
$item_pos++;
# Create a new page, if needed
if ($item_pos > $max_items_per_page) {
$page = _add_pdf_page($pdf);
$item_pos = 1;
}
# Add the item at the appropriate height for that position
# (you'll need to declare $base_height and $line_height)
my $y = $base_height - ($item_pos - 1) * $line_height;
# Your code to display the line here, using $y as needed
# to get the right coordinates
}
return $pdf;
}
sub _add_pdf_page {
my $pdf = shift();
my $page = $pdf->page();
# Your code to display the page template here.
#
# Note: You can use a different template for additional pages by
# looking at e.g. $pdf->pages(), which returns the page count.
#
# If you need to include a "Page 1 of 2", you can pass the total
# number of pages in as an argument:
# int(scalar #items / $max_items_per_page) + 1
return $page;
}
The main thing is to split up the page template from the line items so you can easily start a new page without having to duplicate code.
PDF::API2 is low-level. It doesn't have most of what you would consider necessary for a document, things like margins, blocks, and paragraphs. Because of this, I afraid you're going to have to do things the hard way. You may want to look at PDF::API2::Simple. It might meet your criteria and it's simple to use.
I use PDF::FromHTML for some similar work. Seems to be a reasonable choice, I guess I am not too big on positioning by hand.
The simplest method is to use PDF-API2-Simple
my #content;
my $pdf = PDF::API2::Simple->new(file => "$name");
$pdf->add_font('Courier');
$pdf->add_page();
foreach $line (#content)
{
$pdf->text($line, autoflow => 'on');
}
$pdf->save();