How to get Query data within onSuccess

I'm trying to get the the url data from uploadPDF and use it in within onSuccess. uploadPDF.data.url returns the previous result from uploadPDF instead of the new one. addAVDeviceWithPDF should only run once the uploadPDF is successful.

const cutsheet = fileInput1.value.length
const newCategory = form1.data.category;
const newModel = form1.data.model;
const newWatts = form1.data.watts;
const newMake = form1.data.make;
if (cutsheet == 0) {
  addAVDevice.trigger();
  return false;
} else {
  uploadPDF.trigger({
    onSuccess: function() {
      console.log(uploadPDF.data.url)
      addAVDeviceWithPDF.trigger({
        additionalScope: {
          deviceData: {
            category: newCategory,
            model: newModel,
            watts: newWatts,
            make: newMake,
            pdf_url: uploadPDF.data.url
          }
        }
      });
    }
  });
  return true
}

Does the data only get returned after the trigger?

const cutsheet = fileInput1.value.length
const newCategory = form1.data.category;
const newModel = form1.data.model;
const newWatts = form1.data.watts;
const newMake = form1.data.make;
let success = false;
if (cutsheet == 0) {
  addAVDevice.trigger();
  return false;
} else {
  uploadPDF.trigger({
    onSuccess: function() {
      success = true;
    }
  });
  if (success) {
    addAVDeviceWithPDF.trigger({
      additionalScope: {
        deviceData: {
          category: newCategory,
          model: newModel,
          watts: newWatts,
          make: newMake,
          pdf_url: uploadPDF.data.url
        }
      }
    });
  }
  return true
}

This wouldn't work because trigger runs asynchronously.

Is there a better way to upload a pdf to retool storage, get the url and pass it to a insert record query?

Hi @lpearl,

You can leverage async calls to make this a little cleaner and easier to debug. Try this.

const cutsheet = fileInput1.value.length
const newCategory = form1.data.category;
const newModel = form1.data.model;
const newWatts = form1.data.watts;
const newMake = form1.data.make;
if (cutsheet === 0) { // ** Almost always recommended to use === instead of == in JS
  // I don't know what this section is for in general, so update as needed
  await addAVDevice.trigger();
  return false;
} else {
  // Using await prevents the next line from running until the trigger is resolved.
  // You can add try/catch blocks if you need error handling
  await uploadPDF.trigger()
  await  addAVDeviceWithPDF.trigger({
               additionalScope: {
                 deviceData: {
                 category: newCategory,
                 model: newModel,
                 watts: newWatts,
                 make: newMake,
                 pdf_url: uploadPDF.data.url
               }
             }
           });
  return true
}
1 Like

Thanks @MikeCB that looks to be exactly what I need!

I got stuck on trying to use onSuccess. What is the correct use case for onSuccess when you can just use try/catch? Would it mainly be for running queries that don't rely on the previous trigger?

EDIT:

Sadly i'm still having issues with uploadPDF returning the previous url instead of the file url that was just uploaded.

const cutsheet = fileInput1.value.length
const newCategory = form1.data.category;
const newModel = form1.data.model;
const newWatts = form1.data.watts;
const newMake = form1.data.make;
if (cutsheet === 0) {
  await addAVDevice.trigger();
  return false;
} else {
  try{
    await uploadPDF.trigger()
    console.log(uploadPDF.data.url)
    await addAVDeviceWithPDF.trigger({
                 additionalScope: {
                   deviceData: {
                   category: newCategory,
                   model: newModel,
                   watts: newWatts,
                   make: newMake,
                   pdf_url: uploadPDF.data.url
                 }
               }
             });
    return true
  } catch {
    throw new Error("Upload failed")
  }
}

Hi @lpearl,

Strange, you can try this though, which should capture the result of the most recent execution in a variable.

const cutsheet = fileInput1.value.length
const newCategory = form1.data.category;
const newModel = form1.data.model;
const newWatts = form1.data.watts;
const newMake = form1.data.make;
if (cutsheet === 0) {
  await addAVDevice.trigger();
  return false;
} else {
  try{
    const uploadData = await uploadPDF.trigger() // <-- Change here
    console.log(uploadPDF.data.url)
    await addAVDeviceWithPDF.trigger({
                 additionalScope: {
                   deviceData: {
                   category: newCategory,
                   model: newModel,
                   watts: newWatts,
                   make: newMake,
                   pdf_url: uploadData.data.url // <-- And change here
                 }
               }
             });
    return true
  } catch {
    throw new Error("Upload failed")
  }
}

See if that works.

Hi @MikeCB,

This works and returns the correct url, although I needed to remove the data part for it to work.

const cutsheet = fileInput1.value.length
const newCategory = form1.data.category;
const newModel = form1.data.model;
const newWatts = form1.data.watts;
const newMake = form1.data.make;
if (cutsheet === 0) {
  await addAVDevice.trigger();
  return false;
} else {
  try{
    const uploadData = await uploadPDF.trigger()
    console.log(uploadPDF.url)
    await addAVDeviceWithPDF.trigger({
                 additionalScope: {
                   deviceData: {
                   category: newCategory,
                   model: newModel,
                   watts: newWatts,
                   make: newMake,
                   pdf_url: uploadData.url
                 }
               }
             });
    return true
  } catch {
    throw new Error("Upload failed")
  }
}

I have no idea why the other way does not work as expected.

2 Likes

Glad to hear you got everything working, @lpearl! I'm pretty sure the previous implementations weren't behaving as expected because variable references within a query don't automatically sync with the global context in order to improve performance. To override this default behavior, you can toggle on the "Keep variable references inside this query in sync with your app" setting:

Hope that helps!

1 Like

Hi @Darren,

I'm confused as this option does not exist. Are you looking at the Retool Storage query?

No, it's an advanced option for JS code queries. I assumed that's where you were writing the above code but maybe I misunderstood!

1 Like

Thanks @Darren makes total sense! I can see this option for the JS code, I thought the issue was within the storage query.

1 Like