Updating an overlay contents via AJAX

Basilio

Member
Guys, can you please help me with this - I've figured out how to use the overlay, but what I want to do is grab the form contents, send them to the forum, get them analyzed, receive a response, and depending on that response take some action - either replace the contents of the overlay form with a new form requiring some additional input, or give an error message and ask to repeat the input, or just close the form and redirect to some page of the forum.
For now I am completely stuck, as the normal methods used in Fuhrmann's howtos for jquery forms do not seem to work for the overlay, and I can't seem to find any additional information on how to operate the overlay form.
 
This is what I have done:

I created a template called overlayupdate_form with the form that the user will submit the data. The form has one input, and the user must input a even number. (not odd). This form takes an action called actionTest that I created extending the XenForo_ControllerPublic_Member (just for tests).

The template:

Rich (BB code):
<xen:require js="js/OverlayUpdate/front.js" />
<form action="{xen:link members/test, $user}" method="post" class="xenForm formOverlay UpdateOverlay">
    <dl class="pairs">
        <dt>Enter a par number:</dt>
        <dd><input type="text" name="number" /></dd>
    </dl>
    <dl class="ctrlUnit submitUnit">
        <dt></dt>
        <dd><input type="submit" value="Ok!" class="button primary" /></dd>
    </dl>
 
    <input type="hidden" name="_xfToken" value="{$visitor.csrf_token_page}" />
    <input type="hidden" name="_xfConfirm" value="1" />
</form>

This action filters a number (in that form) and return true if is even, or false if is odd. This action has two responseView. One when opening the overlay to show the form and other, if the request is a confirmed post, to filter the number and verify.

This is the action:

PHP:
<?php
class OverlayUpdate_Member extends XFCP_OverlayUpdate_Member
{
    public function actionTest()
    {
        if ($this->isConfirmedPost())
        {
            $number = $this->_input->filterSingle('number', XenForo_Input::INT);
            $resul = ($number % 2) ? false : true;
       
            return $this->responseView('OverlayUpdate_View', 'overlayupdate_form', array('result' => $resul));
        }
        else
        {
            return $this->responseView('XenForo_ViewPublic_Base', 'overlayupdate_form', array('user' => XenForo_Visitor::getInstance()));
        }
    }
}
?>

After the action, I have created a ViewClass (extending XenForo_ViewPublic_Base) which pass the parameter result to the jquery (using a funcion renderJson)


PHP:
<?php
class OverlayUpdate_View extends XenForo_ViewPublic_Base
{
    public function renderJson()
    {
        $output = $this->_renderer->getDefaultOutputArray(get_class($this), $this->_params, $this->_templateName);
 
        $output['result'] = $this->_params['result'];
 
        return XenForo_ViewRenderer_Json::jsonEncodeForOutput($output);
    }
}
?>


This form has a custom class called UpdateOverlay. This class is used to manipulate the data of the form in a jquery file.

After that, I created a link (a href), with the class 'OverlayTrigger', so we click in this link and the overlay is opened.

All set, I wrote jquery file with registering a element called 'UpdatedOverlay' (remember, this is the class of the form). There is:



Code:
/** @param {jQuery} $ jQuery Object */
!function($, window, document, _undefined)
{
    XenForo.UpdateOverlay = function($form)
    {
        var $overlay = $form.closest('.xenOverlay');
   
        if ($overlay.length)
        {
            $form.submit(function(e)
            {
                e.preventDefault();
           
                //Make the request
                XenForo.ajax(
                    $form.attr('action'),
                    $form.serializeArray(),
                    function(ajaxData, textStatus)
                    {
                        if (XenForo.hasResponseError(ajaxData))
                        {
                            return false;
                        }
                   
                        if (ajaxData.result == true)
                        {
                            //do something
                        }
                        else
                        {
                            //error!
                            $('input[name=number]').css('background', 'red');
                        }
                   
                    }
                );
            });
        }
    };
 
 
    XenForo.register('.UpdateOverlay', 'XenForo.UpdateOverlay');
}
(jQuery, this, document);


I put the overlay in a variable:

Code:
var $overlay = $form.closest('.xenOverlay');



On the form submit
Code:
$form.submit(function(e)


prevent the default action of changing the page:
Code:
e.preventDefault();

Make the request to the action that was set to the form
Code:
XenForo.ajax(

Remember of the parameter result?? I check it in here to see if it is true (even) or false (odd)
Code:
if (ajaxData.result == true)
{
 
}
else
{
$('input[name=number]').css('background', 'red');
}

If the result is true, do something. If is not, take the input that the user filled with the wrong number and set the background to red, so he will know that he have to change it.
 
You can also, depending of the response you get (in the action), if is a error or not, you can set diferents responseview to return.

Example, if you want to show a form, after the user submit the data and this data is correct, create a template, and use this:

PHP:
return $this->responseView('OverlayUpdate_View', 'template_of_the_form_correct', array('my_data' => $my_data));

Then, in the JQuery you can set all the content of the overlay, selecting the actual form and replacing by you template:

Code:
$template = $(ajaxData.templateHtml);
$template.xfInsert('replaceAll', $form, 'slideDown', XenForo.speed.fast);
 
One more questions - thanks to your explanation, I managed to replace the overlay with a new form. However, there is another thing - generally, I made both forms very similar (for the second one I just cloned the first template and replaced some text in it).
However, in the second form I don't see a title, although I have a
Code:
<xen:title>Overlay Title</xen:title>
in it.
And the second issue, in the both templates I have
Code:
   <input type="reset" value="{xen:phrase close}" class="button OverlayCloser" accesskey="d" />
- it works in the first form, but it doesn't work in the second form. So it looks like I'm still missing something.
 
In the close button of the second form put this:

Code:
onclick="$(this).closest('.xenOverlay').data('overlay').close()"



About the title, I'll take a look at it.
 
Top Bottom