Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strings set in a custom control that use custom lang file show as undefined when first rendered but work on second render #1577

Open
breagol37 opened this issue Jul 3, 2024 · 9 comments
Labels
custom control Issue relating to a custom control

Comments

@breagol37
Copy link

breagol37 commented Jul 3, 2024

Description:

If you create a custom control that references strings via mi18n that are set in a custom .lang file.

All works fine in the builder and strings are set correctly, however if you then render the form the strings that are set show as undefined.
If you then render a second time strings will set correctly.

Below test custom control in builder
image

Then when rendered

image

When rendered a second time show as normal.

image

It will also work as expected if you render the form first before adding the custom control then adding the control and rendering.

Example of the ref in code to one of the strings.

image

And the i18n options passed to render in the main index (for this test)
image

In debugging it seemed that the html is displayed before the applyLanguage function has finished.

Environment Details:

  • formBuilder Version: 3.19.7
  • Browser: Chrome
  • OS: Windows

Expected Behavior

Strings should be applied from the custom lang file on first render.

Actual Behavior

Strings do not get applied from the custom .land file until second render.

Steps to Reproduce

Create a custom .lang file and add the details to the i18n location.
Create a custom control and add refs to any custom strings in your custom lang file using controlClass.mi18n("yourCustomStringKey").
Start Form builder and add your control to your form (All strings added as expected)
Render the form (Custom strings used show as undefined)
Render again (Strings now show as expected)

You can also.
In form builder have either blank or any other controls (NOT your custom) added.
Render
Go back to builder and add your custom control
Strings in your control show as expected as its a second render.

@lucasnetau
Copy link
Collaborator

Can you please provide a custom control script and lang file to reproduce the issue.

@breagol37
Copy link
Author

testControl.txt
en-US.txt

Thanks added above but as text files as could not upload as js or lang.

@lucasnetau
Copy link
Collaborator

Hi @breagol37, thank you. I will take a look.

@lucasnetau lucasnetau added custom control Issue relating to a custom control and removed needs feedback labels Jul 3, 2024
@breagol37
Copy link
Author

Thank you @lucasnetau

@lucasnetau
Copy link
Collaborator

lucasnetau commented Jul 4, 2024

HI @breagol37

The issue occurs because the formRender render() function does not wait for the translation library to be ready.

This patch fixes your issue but render() is not meant to be async and breaks the Jest tests and possibly a BC break.

@kevinchappell Thoughts on this one? formBuilder aways the mi18n library to initialise, formRender does not.

diff --git a/src/js/form-render.js b/src/js/form-render.js
index 8331960..4a79197 100644
--- a/src/js/form-render.js
+++ b/src/js/form-render.js
@@ -67,8 +67,9 @@ class FormRender {
     //Override any sanitizer configuration
     setSanitizerConfig(this.options.sanitizerOptions)
 
+    this.mi18nLoading = null
     if (!mi18n.current) {
-      mi18n.init(this.options.i18n)
+      this.mi18nLoading = mi18n.init(this.options.i18n)
     }
 
     // parse any passed formData
@@ -186,7 +187,7 @@ class FormRender {
    * @param {number} instanceIndex - instance index
    * @return {Object} rendered form
    */
-  render(element = null, instanceIndex = 0) {
+  async render(element = null, instanceIndex = 0) {
     const formRender = this
     const opts = this.options
     element = this.getElement(element)
@@ -197,6 +198,11 @@ class FormRender {
       }
     }
 
+    if (this.mi18nLoading) {
+      await this.mi18nLoading
+      this.mi18nLoading = null
+    }
+
     // Begin the core plugin
     const rendered = []
 

@kevinchappell
Copy link
Owner

@lucasnetau this is a good patch. My only doubt is if we should await all of formRender or just the render method.

Await only render method may have least impact though so let's go with your solution.

@breagol37
Copy link
Author

Thanks for looking into this so quickly @lucasnetau greatly appreciated.

@breagol37
Copy link
Author

@lucasnetau Will that fix be put into a release?

@lucasnetau
Copy link
Collaborator

Hi @breagol37, once I find some time to test this it will land in a release.

@kevinchappell I think the change to render() keeps any possible BC change to a minimum. I'll also look at moving the mi18n.init higher up in the formRender constructor to get the request going ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
custom control Issue relating to a custom control
Projects
None yet
Development

No branches or pull requests

3 participants