<p>Since the shuffled markup is the root of the problem, one might follow examples from the Craft control panel source that serialize the form's data and submit via AJAX (and often <code>$.proxy()</code> to help with scope).</p>

<p>This is a lot of work, however, for minor stylistic gain. <strong>If the problem is limited to presentation, the solution should be too.</strong> @narration_sd helped me see how fragile the jQuery hack is compared to a CSS hack, and so in lieu of The Perfect Answer I've created a <code>pseudo-hud-footer</code> class to wrap my action buttons. It's inelegant, looks identical, and it's less risky than my previous workaround:</p>

<pre><code>.approval-request-form .field { margin-top: 0; margin-bottom: 0; }
.pseudo-hud-footer {
    position: relative;
    left: -24px;
    bottom: -24px;
    border-radius: 0 0 4px 4px;
    padding: 6px 24px 10px 24px;
    width: 100%;
    height: 35px;
    background-image: -webkit-linear-gradient(#ecedef, #e9eaec);
    background-image: -moz-linear-gradient(#ecedef, #e9eaec);
    background-image: -ms-linear-gradient(#ecedef, #e9eaec);
    background-image: -o-linear-gradient(#ecedef, #e9eaec);
    background-image: linear-gradient(#ecedef, #e9eaec);
    -webkit-box-shadow: inset 0 2px 1px -2px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0 2px 1px -2px rgba(0, 0, 0, 0.2);
    box-shadow: inset 0 2px 1px -2px rgba(0, 0, 0, 0.2);
}
</code></pre>

CC BY-SA 3.0
2017-05-26T22:12:21.000Z
2017-05-26T22:18:04.797Z
2017-05-26T22:18:04.797Z
Matt Stein
<p>I'm working on a Dashboard widget from which users can submit entries for review from a Garnish HUD, like so...</p>

<p><a href="https://i.sstatic.net/seifg.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/seifg.png" alt="Garnish HUD without a footer."></a></p>

<p>I've started by placing a hidden form next to each little <em>Submit</em> button... </p>

<pre><code>&lt;form method="post" class="approval-request-form hidden" action="/actions/plugin/submitPost"&gt;
    &lt;input type="hidden" name="entryId" value="{{ element.id }}"&gt;
    {{ forms.textareaField({
        name: 'notes',
        label: 'Review Note',
        instructions: 'Add a note for the person reviewing your work.',
        maxlength: 140
    }) }}

    &lt;div class="buttons right"&gt;
        &lt;div class="btn cancel"&gt;Cancel&lt;/div&gt;
        &lt;input type="submit" class="btn submit" value="Submit for Review"&gt;
    &lt;/div&gt;
&lt;/form&gt;
</code></pre>

<p>Once that little button is clicked, I clone the form into a new Garnish HUD with delightful ease:</p>

<pre><code>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);
    });
});
</code></pre>

<p>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...</p>

<p><a href="https://i.sstatic.net/6BMKR.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/6BMKR.png" alt="The new goal: Garnish HUD with footer."></a></p>

<p>I wrap my form's buttons in <code>class="hud-footer"</code>, which applies exactly the style I want...</p>

<pre><code>&lt;form method="post" class="approval-request-form hidden" action="/actions/plugin/submitPost"&gt;
    &lt;input type="hidden" name="entryId" value="{{ element.id }}"&gt;
    {{ forms.textareaField({
        name: 'notes',
        label: 'Review Note',
        instructions: 'Add a note for the person reviewing your work.',
        maxlength: 140
    }) }}
    &lt;div class="hud-footer"&gt;
        &lt;div class="buttons right"&gt;
            &lt;div class="btn cancel"&gt;Cancel&lt;/div&gt;
            &lt;input type="submit" class="btn submit" value="Submit for Review"&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
</code></pre>

<p>This is where the pain starts, because my submit button looks fantastic yet does nothing. After a while I realize it's because <a href="https://github.com/pixelandtonic/garnishjs/blob/develop/src/HUD.js" rel="nofollow noreferrer">HUD.js</a> redraws things and pulls the action buttons out of my <code>&lt;form&gt;</code> element where they <em>would have</em> known what to do...</p>

<pre><code>&lt;div class="hud has-footer"&gt;
    &lt;div class="tip tip-top"&gt;&lt;/div&gt;
    &lt;form class="body"&gt;
        &lt;div class="main-container"&gt;
            &lt;div class="main"&gt;
                &lt;form method="post" class="approval-request-form last" action="/actions/plugin/submitPost"&gt;
                ... my form elements without .buttons ...
                &lt;/form&gt;
                &lt;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;"&gt;&lt;/object&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=""&gt;&lt;/div&gt;
    &lt;/form&gt;
    &lt;div class="hud-footer"&gt;
        &lt;div class="buttons right last"&gt;
            &lt;div class="btn cancel" tabindex="0"&gt;Cancel&lt;/div&gt;
            &lt;input type="submit" class="btn submit" value="Submit for Review"&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>

<p>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 <code>onSubmit</code> property...</p>

<pre><code>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');
        }
    });
});
</code></pre>

<p>That successfully reaches into my form and submits it (and allows me to add some validation logic later), but <strong>how can I use the HUD's footer button to submit the form in <code>.main</code> without the questionable hackery of triggering a click on a hidden button?</strong></p>

<p>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.</p>

<plugin-development><control-panel><garnish><dashboard-widgets><hud>
How can I submit a form from a Garnish HUD footer?
# How can I submit a form from a Garnish HUD footer?

(Asked by: username_0 on 2017-05-26)

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... 

    
    {{ forms.textareaField({
        name: 'notes',
        label: 'Review Note',
        instructions: 'Add a note for the person reviewing your work.',
        maxlength: 140
    }) }}

    
        Cancel
        
    


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...

    
    {{ forms.textareaField({
        name: 'notes',
        label: 'Review Note',
        instructions: 'Add a note for the person reviewing your work.',
        maxlength: 140
    }) }}
    
        
            Cancel
            
        
    


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  element where they would have known what to do...

    
    
        
            
                
                ... my form elements without .buttons ...
                
                
            
        
        
    
    
        
            Cancel
            
        
    


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.

**Tags:** plugin-development, control-panel, garnish, dashboard-widgets, hud

---

## 1 answers

### Answer by username_0 on 2017-05-26. Score: 3 | Accepted answer

Since the shuffled markup is the root of the problem, one might follow examples from the Craft control panel source that serialize the form's data and submit via AJAX (and often $.proxy() to help with scope).
This is a lot of work, however, for minor stylistic gain. If the problem is limited to presentation, the solution should be too. @narration_sd helped me see how fragile the jQuery hack is compared to a CSS hack, and so in lieu of The Perfect Answer I've created a pseudo-hud-footer class to wrap my action buttons. It's inelegant, looks identical, and it's less risky than my previous workaround:
.approval-request-form .field { margin-top: 0; margin-bottom: 0; }
.pseudo-hud-footer {
    position: relative;
    left: -24px;
    bottom: -24px;
    border-radius: 0 0 4px 4px;
    padding: 6px 24px 10px 24px;
    width: 100%;
    height: 35px;
    background-image: -webkit-linear-gradient(#ecedef, #e9eaec);
    background-image: -moz-linear-gradient(#ecedef, #e9eaec);
    background-image: -ms-linear-gradient(#ecedef, #e9eaec);
    background-image: -o-linear-gradient(#ecedef, #e9eaec);
    background-image: linear-gradient(#ecedef, #e9eaec);
    -webkit-box-shadow: inset 0 2px 1px -2px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0 2px 1px -2px rgba(0, 0, 0, 0.2);
    box-shadow: inset 0 2px 1px -2px rgba(0, 0, 0, 0.2);
}


---

