#Script delay to load

23 messages · Page 1 of 1 (latest)

granite star
#

Hello guys, I have a script inside my NextJS 14 app, that render a form from my CRM (Bitrix24).

bitrix-establishment-form.js

;(function (w, d, u) {
  const s = d.createElement('script')
  s.async = true
  s.src = u + '?' + ((Date.now() / 180000) | 0)
  const h = d.getElementsByTagName('script')[0]
  h.parentNode.insertBefore(s, h)
})(window, document, 'https://cdn.bitrix24.com.br/{{SCRIPT_ID}}/crm/form/loader_14.js')

The only way I found to work is this:

EstablishmentForm.tsx

'use client'

import { useEffect } from 'react'

export const EstablishmentForm = () => {
  useEffect(() => {
    const scriptId = '/scripts/bitrix-establishment-form.js'

    if (document.getElementById(scriptId) != null) {
      return
    }

    const script = document.createElement('script')
    script.id = scriptId
    script.src = scriptId
    script.setAttributeNS(null, 'data-b24-form', 'inline/{{ID}}/{{ID}}')
    script.setAttributeNS(null, 'data-skip-moving', 'true')
    script.defer = true

    const scriptDiv = document.getElementById('script_div')

    scriptDiv?.appendChild(script)

    return () => {
      scriptDiv?.removeChild(script)
    }
  }, [])

  return <div id='script_div' className='w-full' />
}

I put the EstablishmentForm component inside a div. But there is a problem, the form only renders a few seconds after the page finishes loading.

I tried to use Next Script:

<Script
  src='/scripts/bitrix-establishment-form.js'
  data-b24-form='inline/14/vle4l0'
  data-skip-moving='true'
/>

But another problem arises, the form is rendered in the end of the body, after everything in the page, but I read that this is the expected behavior (I think).

I tried to use the strategy='beforeInteractive'. The <script> is loaded in the <head> of the app, but the form is not rendered on the screen.

Could you help me to make this work, the form render when the page load?

zinc sandalBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

granite star
#

Script delay to load

terse timber
#

I have the same problem

granite star
#

Up

granite star
#

up

granite star
#

up

tender harbor
#

you need to check does your form have some distinguishable id
then add some id to div where you want to place it
bitrix24 have custom form event on init you can use it in use effect

  useEffect(() => {
    const handleFormInit = () => {
      const targetDiv = document.getElementById("your_target_div_id");
      const formDiv = document.getElementById("your_FORM_div_id");
      if (formDiv && targetDiv) {
        targetDiv.appendChild(formDiv);
      }
    };

    window.addEventListener('b24:form:init', handleFormInit);

    return () => {
      window.removeEventListener('b24:form:init', handleFormInit);
    };
  }, []);
granite star
#

Maybe I didn't understand the way you suggested

#
'use client'

export const EstablishmentForm = () => {
  return (
    <>
      <script
        src='/scripts/bitrix-establishment-form.js'
        data-b24-form='inline/14/vle4l0'
        data-skip-moving='true'
        defer
        onLoad={() => {
          const formContainer = document.getElementById('establishment-form-container')
          const form = document.getElementsByClassName('b24-form')[0]

          if (formContainer && form) {
            formContainer.appendChild(form)
          }
        }}
      />
      <div id='establishment-form-container' className='flex flex-1' />
    </>
  )
}
#

it worked, but the form is rendered after the page load

tender harbor
# granite star it worked, but the form is rendered after the page load

it's external script, so it basically impossible to load it with your page.
theoretically you can add it directly to layout for your page, but even if it will work, it will be only for direct page open, if you redirect with user with client side rendering it will probably ignore layout file.

granite star
gilded loom
granite star
#

i created 3 components, that is the three ways i tried to work

gilded loom
# granite star i created 3 components, that is the three ways i tried to work

try this

"use client";

import { ComponentRef, useEffect, useRef } from "react";

export default function Page() {
  const formref = useRef<ComponentRef<"div">>(null);

  useEffect(() => {
    if (formref.current) {
      const script = document.createElement("script");
      script.id = "b24form";
      script.innerHTML = `(function (w, d, u) {
            const s = d.createElement("script");
            s.async = true;
            s.src = u + "?" + ((Date.now() / 180000) | 0);
            const h = d.getElementsByTagName("script")[0];
            h.parentNode.insertBefore(s, h);
        })(
            window,
            document,
            "https://cdn.bitrix24.com.br/b25948707/crm/form/loader_14.js"
            );`;
      script.setAttributeNS(null, "data-b24-form", "inline/14/vle4l0");
      script.setAttributeNS(null, "data-skip-moving", "true");
      script.defer = true;

      formref.current.appendChild(script);

      return () => {
        document.getElementById("b24form")?.remove();
      };
    }
  }, []);

  return (
    <div className="grid grid-cols-2">
      <div className="flex justify-center items-center">1</div>
      <div ref={formref} className="min-h-[500px]"></div>
    </div>
  );
}
granite star
gilded loom