Skip Navigation

[Resolved] CRED assets registration is a mess

The Toolset Community Forum is closed, for technical support questions, please head on to our Toolset Professional Support (for paid clients), with any pre-sale or admin question please contact us here.
This support ticket is created 7 years, 12 months ago. There's a good chance that you are reading advice that it now obsolete.
This is the community support forum for Types plugin, which is part of Toolset. Toolset is a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients and people who registered for Types community support can post in it.

Sun Mon Tue Wed Thu Fri Sat
- 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 -
- - - - - - -

Supporter timezone: Europe/Madrid (GMT+01:00)

This topic contains 5 replies, has 2 voices.

Last updated by Juan 7 years, 12 months ago.

Assisted by: Juan.

Author
Posts
#458703

Hi,

I want to replace the CRED validation with my own solution. So I have to deregister the CRED JS (validation.js file). Seems to be an easy and straightforward task. I wasn't able to find an info how to do it in the documentation so I started to study the source code... after 2 hours I found that script are registered in a wrong way.

The registration code is hooked to the wp_footer hook instead of wp_enqueue_scripts. So in order to dequeue the script you have to do the following :

add_action('wp_footer', function () {
  wp_dequeue_script('wptoolset-form-validation');
});

It shouldn't be done this way. According to the WP documentation the only proper hook for JS/CSS registering is wp_enqueue_scripts.

Never mind. I was able to find a solution. But then an error started to appear in the JS console:

Uncaught ReferenceError: wptValidationForms is not defined(…)

.

It happens because of the following code being injected to the page:

<script type="text/javascript">wptValidationForms.push("#cred_form_{{form_id}}");</script>

So the .push() method is called on a undefined wptValidationForms variable, because this variable comes from the wptoolset-form-validation script that has already been dequeued.

So I started to dig into sources again in order to find how this JS code is enqueued. It turned out that an another script relies on the wptoolset-form-validation ! and this script is injected to the page using the wp_footer as well (class.validation.php, line 60).

It should have never be done this way, If one script relies on an another script then it should be defined as a dependency. In this case, it wasn't defined as a dependency because the script content is generated dynamically in PHP. In this case you should have used wp_localize_script in order to generate the script, not print(<script>{{...}}</script>). This is considered to be a bad practice.

If a proper wp_localize_script hook were used then dequeuing wptoolset-form-validation would have caused the another script not to be loaded too and no error would appear in the console after wptoolset-form-validation dequeuing.

#458735

So I decided to get rid of the script that causes the JS error. This is how the script is injected (CRED, class.validation.php, line 60):

add_action('wp_footer', array($this, 'renderJsonData'), 30);

$this is a reference to the WPToolset_Forms_Validation class, renderJsonData is a public method of this class.

So I tried this:

remove_action('wp_footer', ['WPToolset_Forms_Validation', 'renderJsonData'], 30);

It doesn't work.
The problem is that the WPToolset_Forms_Validation class is not publicly accessible so I can't remove the action this way.

PS
Sorry, I wanted to edit the previous post, but I'm not longer allowed to do it.

#458753

I made a workaround. I've defined a dummy JS variable:

var wptValidationForms = wptValidationForms || [];

Thanks to this errors no longer appear in the JS console, because wptValidationForms is no longer undefined and has a .push() method (it's an empty array).

But this is just a dirty hack, not a solution.

#459000

Juan
Supporter

Timezone: Europe/Madrid (GMT+01:00)

Hi there

Thanks for the feedback.

Validation is a core part of CRED so obviously disabling it is not an easy task or something you run by just a line of code. But besides that, let me explain why we do the things in that way that looks so wrong.

When we load a page, we do not know beforehand whether it will have a CRED form to add validation to. We just know when we do render the form itself, so we can not enqueue the form validation script by wp_enqueue_scripts at all. If we wanted to do so, we would be on a all-or-nothing situation: we either load this script in all pages, or we load it in no pages at all.

It is a very common practice among plugins to load scripts that depend on the content of the page this way, which means and ensures this is only added whenever it is needed. In fact, two core scripts (wp-mediaelement and wp-playlist) related to frontend rendering of media elements and playlist, get enqueued on shorcode execution, which means that they will also be printed in the foter. But obviously they are not enqueued in the right hook or you would load them everywhere, which is something to avoid.

Also, we load some scripts in th foter using a script tag. You suggest that we should be doing it by wp_localize_script, which is right and god practice, but falls short in our case. If you look carefully to the piece of code you pasted, you will see that it calls a validation method on a given form. Besides the same consideration explained above (how can we add validation to a form which ID we do not know by the right header time?), another restrction applies here: when localizing a script, you can pass some fixed valus. But we might need to validate more than one form if there ismore than one in the page. Using the localization technique, you can not extend the data that you are passing to the script on-the-fly at all: it is fixed and inmutable. But we do need to pass data to it dynamically, so a custom script tag is the best way.

Again, the media shortcodes are a good example hre. Not only they do not follow the good practice rule of loading scripts at the right ime: they also add some JavaScript templates to the footer. They might add them using the localization method, for sure, but instead they generate scrpt tags in the footer.

Long story short: best practices are important, and we follow them, unless they do not allow for logical behavior, like in this case and in the native media shortcodes. CRED validation is a core feature that should not be easy to remove, hence this is why no public interface for that is provided.

Hope it helps.

Regards.

#459355

Hi Juan,

Thanks for the detailed explanation. I understand the reasons why you used wp_footer hooks, but still I think that it's possible to register WPToolset_Forms_Validation->renderJsonData (and not only this script, this is just an example) in a better way that will allow to dequeue it easily.

If you have good reasons not to follow WP coding standards (and based on your response I believe you have) you can still use custom filters and document these filters.

In addition: I can't agree that JS validation is a critical component of the plugin. Front-end validation is (and should be!) just an additional validation because the form is validated on the backend too. So even if the JS is disabled then the form still works and can be submitted and validation messages still show up (after the submission).

So IMO disabling front-end validation should be as easy as running a single line of PHP and there's no reason to prevent users from doing it on their own. Implementing front-end validation is easy, especially when we have such great JS libraries like ParsleyJS.

It applies to the CSS too. Users should be able to deregister all assets in order to replace them with custom ones.

Thanks.

#459395

Juan
Supporter

Timezone: Europe/Madrid (GMT+01:00)

Hi there

Thanks for the feedback.

I do not agree that we do not follow WordPress coding standards on this (because we do what WordPress itself does when in the same situation). We do follow standards for the things they were intended to, but on places not supported by the standars you simply can not use them, which does not mean that you break them or decide not to follow them. But that is semantics 🙂

In our opinion, frontend validation is indeed a core part of the plugin. However, I can take this as a request to make it optional, and to be able to disable it easily with an easy method. But on the meantime, it is a integral part of the plugin flow, regardless backend validation. I do agree that there are tons of valid and valuable validation libraries out there, but the built-in one has several key features that those lack:
- First, we can read additional setings for a field, like whether it is required on Types, which a third party library can not do.
- Second, we can validate against the value format that Types fields do expect, which is important in several field types and third parties can not do.
- Third, it gets totally integrated with the validation messages described in the form settings, which ensure compatibility with third parties like WPML, something that a third party validation script can not do.

It would be a big usability problem if fields started to get values in formats that they can not hold, or if validation messages stopped being in the relevant language.

Of course, it is up to each developer to manage those issues by himself, but I suspect they would become tickets in our support forum 🙂 And I mentioned developers, intentionally. Users should never be entitled the right to break their site just because. Developers can do whatever they want, hence you found your way to remove the frontend validation. We wll not include a checkbox that allows end users to break things - we had this kind of request before for other plugins in the Toolset family and we are quite sure this will never happen.

Finally, general statements are generally right. Of course you should be able to deregister scripts and styles following the native and standard method. But on edge cases, like this one, where standard methods can not be applied to register and enqueue, nobody can expect that standard methods to disable will be enough.

----------------

Long story short: we will evaluate whether it is possible and wise to provide a better, simple way to remove frontend validation on CRED forms. CRED is in the middle of an ambicious refactor that will include many code changes. I am sure we will also find a way to hook third party validation libraries into the game.

Hope it helps.

Regards.

The forum ‘Types Community Support’ is closed to new topics and replies.