I'm working on a Dashboard widget from which users can submit entries for review from a Garnish HUD, like so...
I've started by placing a hidden form next to each little Submit button...
<form method="post" class="approval-request-form hidden" action="/actions/plugin/submitPost">
<input type="hidden" name="entryId" value="{{ element.id }}">
{{ forms.textareaField({
name: 'notes',
label: 'Review Note',
instructions: 'Add a note for the person reviewing your work.',
maxlength: 140
}) }}
<div class="buttons right">
<div class="btn cancel">Cancel</div>
<input type="submit" class="btn submit" value="Submit for Review">
</div>
</form>
Once that little button is clicked, I clone the form into a new Garnish HUD with delightful ease:
jQuery(function(){
$('.request-approval').click(function(e){
e.preventDefault();
var $form = $(e.target).siblings('.approval-request-form').first().clone().removeClass('hidden');
var hud = new Garnish.HUD(e.target, $form);
});
});
This works great! I can post to my controller and all is well. Moments later, it occurs to me that I need some field validation and that it'd be nice to use a HUD footer (with its gray backdrop) and hook up my cancel button...
I wrap my form's buttons in class="hud-footer"
, which applies exactly the style I want...
<form method="post" class="approval-request-form hidden" action="/actions/plugin/submitPost">
<input type="hidden" name="entryId" value="{{ element.id }}">
{{ forms.textareaField({
name: 'notes',
label: 'Review Note',
instructions: 'Add a note for the person reviewing your work.',
maxlength: 140
}) }}
<div class="hud-footer">
<div class="buttons right">
<div class="btn cancel">Cancel</div>
<input type="submit" class="btn submit" value="Submit for Review">
</div>
</div>
</form>
This is where the pain starts, because my submit button looks fantastic yet does nothing. After a while I realize it's because HUD.js redraws things and pulls the action buttons out of my <form>
element where they would have known what to do...
<div class="hud has-footer">
<div class="tip tip-top"></div>
<form class="body">
<div class="main-container">
<div class="main">
<form method="post" class="approval-request-form last" action="/actions/plugin/submitPost">
... my form elements without .buttons ...
</form>
<object tabindex="-1" type="text/html" data="about:blank" style="display: block; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; border: none; padding: 0px; margin: 0px; opacity: 0; z-index: -1000; pointer-events: none;"></object>
</div>
</div>
<div class=""></div>
</form>
<div class="hud-footer">
<div class="buttons right last">
<div class="btn cancel" tabindex="0">Cancel</div>
<input type="submit" class="btn submit" value="Submit for Review">
</div>
</div>
</div>
After some trial and error, I wind up sneaking a hidden submit button into my form and "clicking" it with JavaScript via the HUD's onSubmit
property...
jQuery(function(){
$('.request-approval').click(function(e){
e.preventDefault();
var $form = $(e.target).siblings('.approval-request-form').first().clone().removeClass('hidden');
var hud = new Garnish.HUD(e.target, $form, { closeBtn: $form.find('.cancel'), onSubmit: submitForm });
function checkForm() {
$form.find('.submit').trigger('click');
}
});
});
That successfully reaches into my form and submits it (and allows me to add some validation logic later), but how can I use the HUD's footer button to submit the form in .main
without the questionable hackery of triggering a click on a hidden button?
I suspect I'm either missing something or not thinking quite like the Garnish HUD wants me to. The closest example I've found is the element editor you'd see working with Assets, which serializes and posts its form data via AJAX. I could mimic that instead, but I'd rob myself and our fair Stack Exchange of a learning opportunity.