TJSDialog how to use buttons and callback or return value?

I'm planning to use TJSDialog to act as an intervening Application. So... player clicks a button that would normally generate a ChatMessage. However, a flag causes instead a dialog to appear with several options for the player. Once the decision is made between the options, that information needs to be used by the component that opened the dialog to allow the ChatMessage to be generated at that point. Option 1 I can see that TJSDialog has a mechanism for something along these lines, but I haven't been able to figure out how to use it - managedPromise - seems to be a private property of TJSDialog without a setter. Option 2 It seems that using the prompt function is one way... but a simple binary choice won't be sufficient for my case. It will be more like a radio button with multiple options of which one must be selected. Option 3 Another option would be the onClose callback, provided that I could write a value to return from the dialog, which sounds plausible, except that I'm not sure how to provide buttons to the TJSDialog. It tells me that I can provide them as TJSDialogButtonData types but I can't find that type definition in the runtime codebase. Option 4 I suppose I could write the value to a svelte store, provide a custom button in the content, which writes to that store, then close the dialog when an option is clicked and trigger the onClose callback from there.
4 Replies
Wasp
Wasp2y ago
Have you used TJSDialog.confirm()? Here's an example: https://github.com/fantasycalendar/FoundryVTT-ItemPiles/blob/master/src/API/trade-api.js#L70-L87 You could quite easily implement something similar with your own extension of the TJSDialog class, returning the result you want to have from your own overwritten method of prompt or such
TyphonJS (Michael)
"Option" 3 & 4 are no good. I don't have any visibility on what the content of your dialog is like, but it sounds like it has multiple options that may not be buttons. IE checkboxes or something else. You can set up a form and when the user clicks a submit button you can process the form and return the results through the "ManagedPromise" and then manually close the dialog. However, I want to try and provide the least difficult way for you to accomplish your goal. Can you post a pict of the dialog content / component that you would like to display? TJSDialog gives you significantly more flexibility to design advanced dialogs than the core Dialog implementation. "ManagedPromise" is something unique to TJSDialog. As the documentation states you get access to it in your content component through const managedPromise = getContext('#managedPromise'). This allows you to do any complicated async processing you want and return the results through the normal dialog flow. Re: TJSDialogButtonData. That is a typedef or description of the object data that you can pass for dialog buttons. It's defined at the bottom of TJSDialog. You'll notice that you can set onPress to a callback function or give it a string name of a function in the content component to invoke when the button is pressed. When you do this you also want to set autoClose to false. For form processing this is where you can invoke form.requestSubmit() and then if the form validates the form has a processing function it invokes. That is where you can process the form and return any results through the ManagedPromise. I hazard to point you to an example of this as they are complex async oriented dialogs handling the standard CRUD document actions, but here is a section of a dialog to examine for more involved form processing: https://github.com/typhonjs-fvtt-lib/svelte/blob/main/src/component/dialog/document/TJSDocumentCreate.svelte#L46-L75 Here is where the requestSubmit function in the content component is hooked up to the button (note that autoClose is also set to false): https://github.com/typhonjs-fvtt-lib/svelte/blob/main/src/application/dialog/document/TJSDocumentCreate.js#L57 Depending on how complex your dialog is you may want to extend TJSDialog, but it's possible to do all sorts of things in a data derived manner as well, but for code cleanliness sometimes it's easier to extend TJSDialog. ------------------------- The above is for a full involved async form processing example. Don't just copy code. There may be a much easier solution, so please post a pict of the content of your dialog.
geoidesic
geoidesicOP2y ago
It will be something like this. These are li elements in a ul with click event listeners attached. Clicking one will select it and deselect the others. UI will highlight selection. Then there will be a Roll button below to confirm. The row selected will have some data associated with it that the component that created the dialog will need to process. You mentioned documentation... are you referring to comments within the code? Please could you point out where getContext('#managedPromise'). is documented? As I didn't see that.
No description
TyphonJS (Michael)
In this case there is no form per se as you'll be tracking whatever data the user manipulates in the content Svelte component. It probably should be an async dialog though. // dialog content Svelte component
const { application } = getContext('#external');

const managedPromise = getContext('#managedPromise');

export function requestSubmit()
{
// Verify that user filled out things; maybe post a core UI notification; maybe have an error indication in your component GUI.
if (!verified)
{
// post message / update GUI
return;
}

// Create data to return...
const data = {};

managedPromise.resolve(data);
application.close();
}
const { application } = getContext('#external');

const managedPromise = getContext('#managedPromise');

export function requestSubmit()
{
// Verify that user filled out things; maybe post a core UI notification; maybe have an error indication in your component GUI.
if (!verified)
{
// post message / update GUI
return;
}

// Create data to return...
const data = {};

managedPromise.resolve(data);
application.close();
}
// Invoking the dialog via data.
const result = await TJSDialog.wait({
title: 'some title', // or lang key
// Other TJSDialogOptions
content: {
class: <YOUR_COMPONENT>
},
buttons: {
requestSubmit: {
autoClose: false,
icon: 'fas fa-check',
label 'Submit', // or lang key
onPress: 'requestSubmit'
}
}
}
const result = await TJSDialog.wait({
title: 'some title', // or lang key
// Other TJSDialogOptions
content: {
class: <YOUR_COMPONENT>
},
buttons: {
requestSubmit: {
autoClose: false,
icon: 'fas fa-check',
label 'Submit', // or lang key
onPress: 'requestSubmit'
}
}
}
You may also want to extend TJSDialog and include all of the above data in the constructor passing it on to TJSDialog. Then you would do...
const result = await new MyFancyDialog().wait();
const result = await new MyFancyDialog().wait();
There are two versions of wait; an instance and the prior shown static version shown above. And yes documentation in the source file itself.
Want results from more Discord servers?
Add your server