rocklobster-in / contact-form-7

Contact Form 7 - Just another contact form plugin for WordPress.
Other
287 stars 140 forks source link

HTML in success message #345

Closed pwkip closed 3 years ago

pwkip commented 3 years ago

We used to be able to add HTML to the success message with the wpcf7_display_message filter

add_filter('wpcf7_display_message', function($message, $status){
    return 'A <strong>big</strong> thank you for submitting the form. If you want, you can go <a href="/here">here</a> now';
}, 10, 2);

This used to render like this

A big thank you for submitting the form. If you want, you can go here now

But now it just renders as plain HTML code:

A <strong>big</strong> thank you for submitting the form. If you want, you can go <a href="/here">here</a> now

Is this a bug, or what would be the proposed way to add HTML to the success message?

takayukister commented 3 years ago

HTML is not allowed in messages

pwkip commented 3 years ago

I get it that people should not add HTML in the input fields in the backend. But you are now taking away a valuable hook for plugins that build on top of CF7. Could you explain the reasoning behind making it harder for developers to hook into CF7 functions (both on the JS side and on the PHP side)? I would understand it if you want to completely secure the plugin and stop other plugins from hooking into CF7 in order to get more control over the plugin. But if this is indeed the direction you are taking the plugin, please let me know. I have been writing extensions for CF7 for as long as I can remember, but if you are turning it into a proprietary product (which is your full right), please let me know so I can start looking for alternatives.

Quick edit: I realized I might come across a bit harsh. If so, I apologize. I really respect all effort that put in this awesome plugin, and I really mean it wen I say that it is your full right to decide on its direction. I'm just curious what direction that is :)

maxguru commented 3 years ago

I'm guilty of this but I do it in a different way: https://github.com/maximum-software/pdf-forms-for-contact-form-7/blob/master/pdf-forms-for-contact-form-7.php#L1803

Unfortunately, HTML is not allowed in messages method isn't going to work for me because I have to pass data to the frontend.

There might be a way to do it by combining the method described in HTML is not allowed in messages with DOM events but it is still unclear to me how to pass data out of my plugin into the web page (possibly in event.detail object).

pwkip commented 3 years ago

Hi @takayukister,

I want to politely ask you to please reconsider your decision of removing the ability to add HTML to the success message via a filter.

There are loads of valid use cases, where it makes sense to modify the success message based on the values the user has filled out in the form. Right now there is only the possibility for a dynamic message without HTML, or static message with HTML (via the workaround you linked to). But the powerful combination of both does not exist anymore.

While I could "easily" work around it with yet another hack like this:

var wpcf7Elm = document.querySelector( '.wpcf7' );
wpcf7Elm.addEventListener( 'wpcf7submit', function( event ) {
    const successMessage = document.querySelector('.wpcf7-response-output');
    successMessage.innerHTML = successMessage.innerText;
}, false );

It would be so much simpler and cleaner in my opinion if you could change this line

from:

div.innerText = response.message;

to:

div.innerHTML = response.message;

Please think about it. It will be a great help to me and other developers that enjoy extending your amazing plugin

maxguru commented 3 years ago

By the way, I've used a combination of hooks (wpcf7_form_elements, wpcf7_form_response_output, wpcf7_feedback_response and wpcf7_ajax_json_echo) to pass data out of my plugin and add custom HTML to the front end form.

maxguru commented 3 years ago

One issue that I've hit that I would like to mention is that I can't really put my HTML into the response message because it gets overwritten after my JS callback runs. I guess it is not such a big deal, but it would have been nice to be able to rewrite the response message in JS. Maybe I am just not seeing a non-dirty-hack method to do it.

pwkip commented 3 years ago

My above workaround will not work anymore with version 5.4.1 because an extra check was added to strip all HTML tags from the message.

So if you still want to use HTML in your success message, you need to convert the message to html entities in your PHP script first:

add_filter('wpcf7_display_message', function($msg){
  $custom_html_message = '<strong>CF7 is the best!</strong>';
  return htmlentities($custom_html_message);
}, 10, 2);

Then, in Javascript you need to decode the success message again. (relies on jQuery)

var wpcf7Elm = document.querySelector( '.wpcf7' );
wpcf7Elm.addEventListener( 'wpcf7submit', function( event ) {
    setTimeout(function(){
        const successMessage = document.querySelector('.wpcf7-response-output');
        const htmlMessage = htmlEntitiesDecode(successMessage.innerText);
        successMessage.innerHTML = htmlMessage;
    }, 200);
}, false );

function htmlEntitiesDecode(str) {
    return jQuery('<textarea />').html(str).text();
}
Colir commented 3 years ago

Thank you @pwkip @takayukister each update of CF7 become more and more painfull...

But thank you, your plugin is still really usefull

LukaszJaro commented 3 years ago

omg, I was looking into this for hours..this is gonna cause so many headaches on many of my sites..this is just a strange change to make for a filter to lose this much functionality with no good replacement.

LukaszJaro commented 2 years ago

I'm actively now looking into a solution for this. I use wpcf7_display_message quite bit for so many customizations to change the messages depending on a drop down selection. Some cases I have certain words bolded but now that's not possible.

If I we're to use the CF7 solution of hiding the block of html with CSS I would have to add many custom messages to every single form and it would end up looking something like this but each message would be different. Also it would impact some posted data I am using in the success message like serial number, I would also have to test a new solution for that:

<div class="visible-only-if-invalid">
  <font color="#f00">You have <marquee>invalid</marquee> $posted_data['cf7_data]</font>
</div><div class="visible-only-if-dropdown">
  <font color="#f00">You have <marquee>invalid</marquee> fields!</font>
</div><div class="visible-only-if-dropdown1">
  <font color="#f00">You have <marquee>invalid</marquee> fields!</font>
</div><div class="visible-only-if-dropdown-2">
  <font color="#f00">You have <marquee>invalid</marquee> fields!</font>
</div><div class="visible-only-if-invalid etc">
  <font color="#f00">You have <marquee>invalid</marquee> fields!</font>
</div><div class="visible-only-if-invalid etc">
  <font color="#f00">You have <marquee>invalid</marquee> fields!</font>
</div><div class="visible-only-if-invalid etc">
  <font color="#f00">You have <marquee>invalid</marquee> fields!</font>
</div>

Being able to do this from a single PHP filter made things much more simpler and clearer and reduced the workload significantly.

I'll be looking into solutions and post if I find anything, also if anyone else has found new methods to handle this?

I also noticed Cf7 has many breaking changes with the updates to the point where it is one of the plugins most likely to break, especially if you are DEV using hooks to customize cf7.

But at the same time it is one of the strongest well coded plugin, it's free and quite flexible. But now I probably have to spend days rebuilding, I have strict requirements for some sites so I have to find a way to replicate current behavior.

LukaszJaro commented 2 years ago

Final solution I was able to recreate the functionality using dom events https://contactform7.com/dom-events/ No longer using wpcf7_display_message hook. DOM events are more reliable then the clever hack solution provided above. I have to use a timeout with the code so gives the DOM time to appear, mutation observer would work as well but timeout is simpler to implement.

Small snippet of over 160 lines of JS I had to do to recreate the functionality :)

if ( status === 'mail_failed' || status === 'mail_sent' || status === 'spam' ) {
        setTimeout( () => {
            let $message = document.querySelector( '.wpcf7-response-output' );
            $message.innerHTML = '';
            document.querySelector( '.wpcf7-response-output' ).insertAdjacentHTML( 'afterbegin', $pageLvlMsg );
        }, "50" );
    }