Is there a way we can “prompt” the user as in a Yes No Cancel Dialog box?
For example:
Pressing a delete button, you may want to prompt the user to confirm or cancel.
Is there a way we can “prompt” the user as in a Yes No Cancel Dialog box?
For example:
Pressing a delete button, you may want to prompt the user to confirm or cancel.
Perfect, I keep forgetting about the Kitchen Sink.
Thank you
A quick prompt
function that might prove useful to you:
async function prompt(heading, body, buttons=["Cancel", "Ok"], options={title: heading, size: {width: 360, height: 280}}) {
const [dlgEl, formEl, headingEl, dividerEl, bodyEl, footerEl] =
["dialog", "form", "sp-heading", "sp-divider", "sp-body", "footer"]
.map(tag => document.createElement(tag));
[headingEl, dividerEl, bodyEl, footerEl].forEach(el => {
el.style.margin="6px";
el.style.width="calc(100% - 12px)";
});
formEl.setAttribute("method", "dialog");
formEl.addEventListener("submit", () => dlgEl.close());
footerEl.style.marginTop = "26px";
dividerEl.setAttribute("size", "large");
headingEl.textContent = heading;
bodyEl.textContent = body;
buttons.forEach((btnText, idx) => {
const btnEl = document.createElement("sp-button");
btnEl.setAttribute("variant", idx === (buttons.length - 1) ? (btnText.variant || "cta") : "secondary");
if (idx === buttons.length - 1) btnEl.setAttribute("autofocus", "autofocus");
if (idx < buttons.length - 1) btnEl.setAttribute("quiet");
btnEl.textContent = (btnText.text || btnText);
btnEl.style.marginLeft = "12px";
btnEl.addEventListener("click", () => dlgEl.close((btnText.text || btnText)));
footerEl.appendChild(btnEl);
});
[headingEl, dividerEl, bodyEl, footerEl].forEach(el => formEl.appendChild(el));
dlgEl.appendChild(formEl);
document.body.appendChild(dlgEl);
return dlgEl.uxpShowModal(options);
}
const r = await prompt("Upload Large File", "This is a large file (over 100MB) -- it may take a few moments to upload.", ["Skip", "Upload"]);
if ((r||"Upload") !== "Upload") { /* cancelled or No */ }
else { /* Yes */ }
const r = await prompt("Delete File", "Are you sure you wish to delete this file? This action cannot be undone.", ["Cancel", {variant: "warning", text: "Delete"}]);
if ((r !== "Delete") { /* nope, don't do it! */ }
else { /* Do the delete */ }
That’s great !
Might it be possible to display an image below the divider line for instance?
@kerrishotts I’ve noticed a weird behavior with the dialog’s close() function. I have a dialog with a text-input whose value I want to return, but upon form submit the close() fully ignores the parameters:
formEl.addEventListener("submit", () => (dlgEl as HTMLDialogElement).close(textInput.value));
When I await the dialog function, there’s no return value.
This however…
btnEl.addEventListener("click", () => (dlgEl as HTMLDialogElement).close(textInput.value));
…works correctly, so there must be an issue with the submit event. Maybe there are some internal timing issues and the dialog gets closed before the event callback is executed or something like that?
When I console.log the value inside the submit event callback it’s logging correctly. It simply gets lost on the way through the close-function:
formEl.addEventListener("submit", () => console.log(textInput.value));
Any idea what the problem could be?
I do have an idea!
A form’s default action is to close the dialog it finds itself inside, and it does so with close("")
.
Since you want to override this behavior, be sure to call the event’s preventDefault
method so that your return value doesn’t get modified.
Ah, makes sense, I didn’t know about this specific dialog+form behavior.
preventDefault
works perfectly, thanks!
Hello Kerri,
I’ve tried your little code snippet and was wondering: The modal dialog is displayed in front of the main window but it doesn’t block the interaction with the underlying Photoshop application, why not?
Kind regards
Lars