registerNoSubmitButton but NOT skip validation : possible?

registerNoSubmitButton but NOT skip validation : possible?

Joseph Rézeau -
回帖数:10
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

This is a problem with a question edit form, but may be relevant in a more general context of using Moodle forms, so posting here.

In my REGEXP edit form I want to add a button to display a list of alternate correct answers generated from the regular expressions in the Answers fields. This display would look similar to the "Decode and Verify the question text" in the Cloze question edit form.

I know how to use a registerNoSubmitButton element to trigger a reload of the edit form in order to retrieve the form contents like this:

        $mform->addElement('submit', 'showalternate', get_string('showalternate', 'qtype_regexp'));
        $mform->registerNoSubmitButton('showalternate');

However, I have quite a lot of validation operations to conduct upon the entered regular expressions (in the Answers fields). Normally these validation operations are conducted upon saving the question, in the usual function validation($data, $files) located in my edit_regexp_form file.

Now, I need the validation function to be called when pressing the "showalternate" button, before I can do anything with the answers data.

But there is a mechanism in the lib/form/submit.php which makes this impossible.

if ($caller->isNoSubmitButton($arg[0])){
                    //need this to bypass client validation
                    //for buttons that submit but do not process the
                    //whole form.
                    $onClick = $this->getAttribute('onclick');
                    $skip = 'skipClientValidation = true;';
                    $onClick = ($onClick !== null)?$skip.' '.$onClick:$skip;
                    $this->updateAttributes(array('onclick'=>$onClick));
                };

My question is: is there a way to have another kind of submit-"NoSubmitButton" which would still a) trigger the form validation but b) not save the form?

Joseph

回复Joseph Rézeau

Re: registerNoSubmitButton but NOT skip validation : possible?

Darko Miletić -
Core developers的头像 Plugin developers的头像
回复Darko Miletić

Re: registerNoSubmitButton but NOT skip validation : possible?

Joseph Rézeau -
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Hi Darko and thanks for your help.

Actually I was hoping to find a solution based on Moodle's API only. What I do not understand at the moment is that the if ($caller->isNoSubmitButton($arg[0])) condition clearly states that it will
"// bypass client validation
//for buttons that submit but do not process the
//whole form."

but, even if I remove that condition, my registerNoSubmitButton call still bypasses validation, which is not what I want. This seems illogical.

So I here re-state my question : how can I make a "NoSubmitButton" button go through form validation the same as a "normal" Submit button?

Joseph

回复Joseph Rézeau

Re: registerNoSubmitButton but NOT skip validation : possible?

Jamie Pratt -

Hi Joseph,

The if condition you have found is used to bypass the client side validation.

NoSubmitButton is meant to be used when data is not validated and not saved.

There is another option that is available for question editing forms - 'wizard' multipage forms are possible. I am afraid there is not much documentation on this feature but the calculated question types for example have multipage forms. It sounds like what you want to do is similar. The user fills out an initial form and then can move onto a second stage of question editing, this might be an extended form with more options rather than a completely new form page.

I would suggest that you search for 'wizard' in question/types/ to see examples of how wizard is used.

Jamie

回复Jamie Pratt

Re: registerNoSubmitButton but NOT skip validation : possible?

Joseph Rézeau -
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Thanks Jamie (and Itamar) for your help, but I am still stuck.

  1. What I can do is the following:
    1. When the "alternateanswers" (registerNoSubmitButton) button is pressed, from the function definition_inner($mform) I can call $this->validation($data,'');
    2. That way I can a) display the alternate answers (screenshot #1) and - in case errors have been found in the regexps - I can display them. (screenshot #2)
  2. However, but pressing my alternateanswers button I still cannot display the error messages the way that the "normal" form validation would display them, i.e. just above the Answer fields (screenshot #2).
  3. I looked again at the multianswer and calculatedsimple questions, and I can find the same problem in those questions. The error messages get displayed differently when the form is submitted through the normal "Save Changes" button or through the "Find the wild cards..." (calculatedsimple) or the "Decode and verify the question text" (multianswer) buttons. I guess the reason is the same as the problem I have found in my regexp question edit form: the impossibility to submit the question for validation only, without saving.
    1. Multianswer question: type a question text without any embedded question
      1. Click the "Decode and verify the question text" button -> No error message is displayed!
      2. Click the "Save Changes" button -> the "The question text must include at least one embedded answer." error message is displayed.
    2. Calculatedsimple question: type a question text without embedded wild card in answer formula or question text
      1. Click the "Find the wild cards {x) present in the correct answer formulas -> get error message "There must be at least one wild card {x..} present in the correct answer formulas"
      2. Click the "Save Changes" button -> get error message "There should be at least one wild card in answer formula or question text".

Maybe Tim will come up with a bright solution?

Joseph

附件 29-12-2011 17-22-04.jpg
回复Joseph Rézeau

Re: registerNoSubmitButton but NOT skip validation : possible?

Jamie Pratt -

Hi Joseph,

It seems to make sense to me to do things the way the form wizard functionalilty is designed to do - to always save the intermediate state of a partially finished question. If the teacher has entered some data, let's save it so it doesn't get lost.

Save the data, have it properly cleaned and validated by the built in functionality. Then the wizard functionality will bring the user back to your extended form or the next form in your series for editing a question and the displayed data will be displayed and according to the cleaned and saved data you can change the structure of the form in the definition method.

I didn't remember that the calculated question type displayed errors in-form in this rather non standard way. It also is an example of using multipage forms if you search for wizard you will find the relevant code.

You can have a button that submits the form and saves the data on the page and then redisplays the form by putting something like these elements in your form (adding code to definition_inner) :

$mform->addElement('submit', 'recalculatenow',
get_string('recalculatenow', 'qtype_varnumericset', 2));

//we are using a hook in questiontype to resdisplay the form and it expects a parameter
//wizard, which we won't actually use but we need to pass it to avoid an error message.
$mform->addElement('hidden', 'wizard', '');


Here wizard will contain the name of the next from to display or '' if there is no next form. Then in questiontype.php :

public function finished_edit_wizard($fromform) {
//keep browser from moving onto next page after saving question and
//recalculating variable values.
if (!empty($fromform->recalculatenow)) {
    return false;
} else {
    return true;
}
}

 

Jamie

回复Jamie Pratt

Re: registerNoSubmitButton but NOT skip validation : possible?

Jamie Pratt -

You may also want to add some code to your question renderer to show an error if all necessary data has not been entered to complete the question.

回复Jamie Pratt

Re: registerNoSubmitButton but NOT skip validation : possible?

Joseph Rézeau -
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Thanks, Jamie, for spelling out what the wizard can do for me. I have started implementing things the way you describe and have good hope to get things to work the way I need.

Will report here when I have completed my development.

In the meantime, many thanks and a Happy New Year to you! 满意

Joseph

回复Jamie Pratt

Re: registerNoSubmitButton but NOT skip validation : possible?

Joseph Rézeau -
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Jamie "It seems to make sense to me to do things the way the form wizard functionalilty is designed to do - to always save the intermediate state of a partially finished question. If the teacher has entered some data, let's save it so it doesn't get lost."

Well, unfortunately, this behaviour has adverse effects in the case at hand. I have tried using your "wizard" advice and things work as desired... up to a point.

Case #1: creating a new question

When I can create a new question, pressing the showalternate button saves the form data and displays alternate answers as desired. Then, pressing the Save Changes button saves the question OK.

Case #2: editing a question

a. If I edit an existing question, make some changes to the question name or text, possibly add answer fields, etc. and - without having pressed the showalternate button at any time ...

  1. save that question,
  2. make a copy
  3. cancel

then, everything works as expected.

b. But if I press the showalternate button, any changes made to the question being edited are immediately saved to the database, with the following consequences:

  1. saving that question is OK - of course 满意
  2. making a copy saves 2 identical questions: the original one, with new changes and an exact copy 伤心
  3. cancel does not acutally cancel the editing of the original question, since the changes have already been saved 伤心

So, even using the wizard system, I cannot get the behaviour I want, because any submit from my showalternate button does save changes to the actual question in the database. So I am back to square 1 and asking the same question: how can I validate without saving ?

I have tried over-riding the save_question function from questiontypebase.php, trying to "short-circuit" the save to database process when my form is submitted through the showalternate button, but have had not success.

Any suggestions?

Joseph

回复Joseph Rézeau

Re: registerNoSubmitButton but NOT skip validation : possible?

Joseph Rézeau -
Core developers的头像 Particularly helpful Moodlers的头像 Plugin developers的头像 Testers的头像 Translators的头像

Oh well, that last post of mine got me thinking and finally I found a working solution...

I reverted from using the wizard to my original solution of using a NoSubmitButton. Then, from within function definition_inner($mform) I call $this->validation($data,'');

And then I "hi-jacked" this bit of code from question.php:

$moodle_val = $this->validation($data, '');
                if ((is_array($moodle_val) && count($moodle_val)!==0)) {
                    // non-empty array means errors
                    foreach ($moodle_val as $element=>$msg) {
                        $mform->setElementError($element, $msg);
                    }
                    $moodle_val = false;
    
                } else {
                    // anything else means validation ok
                    $moodle_val = true;
                }

... which does exactly what I originally wanted.

Joseph

回复Joseph Rézeau

Re: registerNoSubmitButton but NOT skip validation : possible?

Itamar Tzadok -

The get_data call is designed to fail when a no-submit-button is pressed and since the validation is called inside the get_data, it is bypassed.

If you can modify the 'if (... = $caller->get_data())' clause, you can add a condition there which tests a designated variable you set upon pressing a designated submit button in the form.

(The problem is that sometimes that clause is in the core code but you need it to be more flexible from a plugin. A related requirement is 'save and return to form' button)

微笑