Page 1 of 1

How a module reports messages of error or success to the user

Posted: Sat Jul 19, 2008 9:08 am
by oi_antz
I know you can return an error message to the user when redirecting, but what if you don't want to redirect, but still want to show an error or success message?

Say I have this code in my module:

Code: Select all

<?php
function DoAction($action, $id, $params, $returnid=-1){
    $error = false;
    $errorMsg = '';
    if(count($_POST)>0){
        if($_POST['username']==''){
            $error = true;
            $errorMsg .= 'You must specify a username<br />';
        }
        if(!$error){
            // safe to process
        }
    }
    if($errorMsg != '') $this->RegisterErrorMessage($errorMsg);
    // build our form
    $fieldset = Antz_Form::rapidForm('User details');
    $fieldset->addInput('text', 'username', 'Username:', post('username'));
    $this->smarty->assign('form', $form->render());
    echo $this->smarty->ProcessTemplate('admin.register.tpl.php');
} 

... then how would I write the method "RegisterErrorMessage" ?

Cheers, Anthony.

Re: How a module reports messages of error or success to the user

Posted: Sat Jul 19, 2008 11:05 am
by NaN
What about this:

Code: Select all


...
    if($errorMsg != '') $this->smarty->assign('errorMsg', $errorMsg);
// build our form
...

And in your 'admin.register.tpl.php' (tpl.php? <- is that right?) you just need to check with smarty if there is an errormessage:
e.g:

Code: Select all


{if isset($errorMsg) && $errorMsg!=''}
{$errorMsg}
{/if}

...


Re: How a module reports messages of error or success to the user

Posted: Sat Jul 19, 2008 11:56 am
by oi_antz
Lol! I would just make it .php, but I thought tpl.php is more clear for describing the type of file it is, I'll likely change my mind about that one day...

Ok, so is there no marker in the admin template that I can access by smarty - must I really put it into my own template? I would really prefer to have my messages presented just like all other system messages - looks more official y'know.

Re: How a module reports messages of error or success to the user

Posted: Sat Jul 19, 2008 12:14 pm
by NaN
oi_antz wrote: ...
Ok, so is there no marker in the admin template that I can access by smarty
...
Not by default i guess.
I checked out the source codes of some modules and i didn't find such marker.

oi_antz wrote:
must I really put it into my own template?
Seems to be.
The most modules do that.

oi_antz wrote: ...
I would really prefer to have my messages presented just like all other system messages - looks more official y'know.
...
Isn't that styled by CSS?
So if you just print out your errormessage like this:

Code: Select all


{if isset($errorMsg) && $errorMsg!=''}
<div class="pageerrorcontainer">
	<div class="pageoverflow">
		<ul class="pageerror"><li>{$errorMsg}</li></ul>
	</div>
</div>
{/if}

It should look like all other errormessages.

Re: How a module reports messages of error or success to the user

Posted: Sat Jul 19, 2008 11:40 pm
by NaN
I looked in the source of some core files (e.g. admin/editcontent.php) and found out, that these messages i guess you're talking about are harcoded in there and are displayed as a result of an ajax request.
All modules i've taken a look into the sources are using the smarty stuff to display messages.
I could not find a RegisterErrorMessage function in my whole CMSms installation.

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 12:34 am
by oi_antz
Hey, nice of you to look into it for me. I'd not mind putting the error message in my template if it could look the same, but if you look at the screen shot:
Image
... notice the message is placed above the start of the module, so it is out of reach for my module. Maybe I could devise some JavaScript to move the message in the dom...

Otherwise I will have to rethink my methodology so I can redirect on error or success. This will require some change to my error reporting for forms, since my classes are designed around a policy that each page will try and process before generating the form. When the form is generated, it checks if there are any errors relating to the given form field, and these flags are stored in a global variable. I guess the easiest way is to store the $formErrors variable in the session and reset it when the form is rendered, or on success.

I'll have a go at that.

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 12:40 am
by oi_antz
Doh... That would mean that if I have two forms on one page, the first form will cancel the error messages before the second form is rendered. Oh no! What will I do?

Might have to put it down for a little while, might get a bright idea in a quiet moment  ;)

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 1:29 am
by oi_antz
Heh, well that wasn't so hard, since I'm bootstrapping the admin folder with mod_rewrite, I just reset the $USER->formErrors array before echo $pageAsString;

However, it is not without it's problems:

After checking the form and finding errors, I redirect in order to get the error message to show up. Problem is that when I go to build my form, all the form contents have disappeared because we redirected with a get request. This is easily overcome using my class Antz_IntelliForm, it can save and restore form contents. Problem one is resolved.

What happens when I refresh the page: the form errors disappear, but the error message remains because the error message is in the url! I reckon if I'm going to have one error message, I need to have them all otherwise it would appear buggy. Time for another break me thinks...

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 1:44 am
by oi_antz
I dunno, this whole approach is too complicated for my liking. I'm going to have a go at the JS dom idea I had...

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 4:31 am
by oi_antz
Ok this is my solution:

Method DoAction calls in two extra javascript files: admin.errorMsg.js and AntzBase.js. Admin.errorMsg contains a function to build the error message into the dom:

Code: Select all

function showErrorMsg(msg, rootUrl){
    var cont = document.getElementById('MainContent');
    var pCont = document.getElementsByClassName('pagecontainer');
    pCont = pCont[0];
    var objs = document.getElementsByClassName('navt_menu');
    var navt = objs[0];
    var div = document.createElement('div');
    var div2 = document.createElement('div');
    var img = document.createElement('img');
    var span = document.createElement('span');
    span.innerHTML = ' '+msg;
    img.src = rootUrl+'/admin/themes/default/images/icons/system/stop.gif';
    img.alt = 'Error';
    img.title = 'Error';
    img.className = 'systemicon';
    div.className = 'pageerrorcontainer';
    div.id = 'errorMsg';
    div2.className = 'pageoverflow';
    div2.appendChild(img);
    div2.appendChild(span);
    div.appendChild(div2);
    appendAfter(navt, div);
}

// function derived from http://book.itzero.com/read/others/McGraw.Hill.Osborne.JavaScript.2.0.The.Complete.Reference.Second.Edition.eBook-LiB_html/8166final/LiB0073.html
function appendAfter(existingNode, newNode) 
{
 if (existingNode.parentNode)
  { 
    if (existingNode.nextSibling)
       existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
    else
       existingNode.parentNode.appendChild(newNode);
  }
}
Then at the end of DoAction, I add the following code, which will call the function showErrorMsg, suppying with the error messages that are assembled by my Core class "Antz":

Code: Select all

<?php
// time to add our error messages
$errorMsg = Antz::getError();
if($errorMsg != '')
    echo '<__script__ type="text/javascript" language="javascript">showErrorMsg(\''.$errorMsg.'\', \''.$this->config['root_url'].'\')</__script>';
The file AntzBase.js just contain an object called "AntzBase", which contains useful methods, in particular here:
AntzBase.clearError(), which is called when the user clicks "OK" on the error message. This simply sets display="none" on the error message container (#errorMsg).

Code: Select all

    clearError : function(){
        if(document.getElementById('errorMsg'))
            document.getElementById('errorMsg').style.display = 'none';
    },
... so now I can add error messages to the page at any point in the execution of my module, simply by using Antz::addError('This is the error message');

Simple!

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 4:56 am
by oi_antz
This means that all new modules will start with the following code:

Code: Select all

<?php
function DoAction($action, $id, $params, $returnid=-1){
    switch($action){
        case 'defaultadmin':
            // enable us to insert error messages on the page
            echo '<__script__ src="'.$this->config['root_url'].'/modules/FEUsers/js/admin.errorMsg.js" type="text/javascript"></__script>';
            echo '<__script__ src="'.$this->config['root_url'].'/modules/FEUsers/js/AntzBase.js" type="text/javascript"></__script>';
          
// execute here  
            
            // time to add our error messages
            $errorMsg = Antz::getError();
            if($errorMsg != '')
              echo '<__script__ type="text/javascript" language="javascript">showErrorMsg(\''.$errorMsg.'\', \''.$this->config['root_url'].'\')</__script>';
        break;
        case 'default':
            echo $this->GetFriendlyName();
        break;
    };
}
... And a dependency on the Antz framework ;)

Re: How a module reports messages of error or success to the user

Posted: Sun Jul 20, 2008 5:05 am
by oi_antz
This is what it looks like:
Image