Set Calendly URL dynamically

We are loading a FeatheryForm inside a modal from within a Vue.js web page of an agent’s microsite. In that form, we are storing the value of the current agent’s (whose microsite it is) calendly url.

How could we pass the value from that hidden field as the calendly url used to load the calendly calendar in the next step of that form?

Thank you in advance for any assistance with this.

Hi @troycono ,

Create a hidden field on your feathery form that would hold the calendly url. Then on your embed code, you can add the initialValues prop and pass the value in there (ref: <Form> | Feathery Docs)

Hey @Kenny,

Thanks for the prompt reply. I’ve managed to get that far into the process already. The problem I’m having is that the Calendly embed field needs to receive the value of that field in order to load the appropriate calendar, and, unfortunately, from what I can tell by attached screenshot, attempting to pass that field’s value directly to the calendly url field does not work. That field is expecting a valid, fully formed, static url. So, how can I overwrite the value of that field in the calendly embed with the value of my hidden form field?

For anyone who ends up looking for this same thing, here is the Vue.js solution I came up with for our particular environment/situation:

export default {
  install: (app, options) => {
    app.config.globalProperties.$updateCalendlyWidget = (siteData) => {
      const newUrl = siteData?.calendar_url;

      if (!newUrl) {
        console.error("Calendly URL is missing from the provided site data.");
        return;
      }

      let attempts = 0;
      const maxAttempts = 20;

      const intervalId = setInterval(() => {
        const calendlyWidget = document.querySelector('.calendly-inline-widget');
        attempts++;

        if (calendlyWidget) {
          clearInterval(intervalId);
          calendlyWidget.setAttribute('data-url', newUrl);
          
          const parent = calendlyWidget.parentNode;
          if (parent) {
            parent.removeChild(calendlyWidget);
            parent.appendChild(calendlyWidget);
          }
        } else if (attempts >= maxAttempts) {
          clearInterval(intervalId);
          console.error(`Could not find '.calendly-inline-widget' after ${maxAttempts} attempts.`);
        }
      }, 100);
    };
  }
};

Then, if your Form Component, you’ll need this:

const app = getCurrentInstance();
const feathery = app.appContext.config.globalProperties.$feathery;
const formContext = ref(null);

onMounted(async () => {
  if (!feathery) {
    console.error("Feathery is not available.");
    return;
  }
  try {
    await feathery.init('your_feathery_api_key'); 
    formContext.value = await feathery.renderAt(`form_${props.formId}`, {
      formId: props.formId,
      initialValues: { ...props.fields },
      onFormComplete: () => {
        const calendlyUrl = props.fields.[your_hidden_field_id];
        if (!calendlyUrl) {
          console.error("Calendly URL not found in component props.");
          return;
        }

        let attempts = 0;
        const maxAttempts = 30;

        const intervalId = setInterval(() => {
          const calendlyWidget = document.querySelector('.calendly-inline-widget');
          attempts++;

          if (calendlyWidget) {
            clearInterval(intervalId);
            
            const originalUrl = calendlyWidget.getAttribute('data-url');
            const finalUrl = originalUrl.replace('{{your_hidden_field_idl}}', calendlyUrl);
            calendlyWidget.setAttribute('data-url', finalUrl);
            
            const parent = calendlyWidget.parentNode;
            if (parent) {
              parent.removeChild(calendlyWidget);
              parent.appendChild(calendlyWidget);
            }
          } else if (attempts >= maxAttempts) {
            clearInterval(intervalId);
            console.error(`Could not find '.calendly-inline-widget' on success step.`);
          }
        }, 100);
      },
    });
  } catch (error) {
    console.error('Feathery form failed to load:', error);
  }
});

This should work in Vue, assuming you have a hidden field in your FeatheryForm that’s being dynamically populated with a valid calendly url within the call to the form itself, like so (also in Vue.js):

<FeatheryForm
  form-id="[your_form_id]"
  :fields="{
    your_hidden_field: dynamic_calendly_url
  }"
/>

I hope this helps someone else not spend 3 days on this, like I had to.