Xpages how to get CSJS confirmation in SSJS

2019-08-01 06:37发布

问题:

I have a repeat control that contains a button that will process documents that a user selects. My first use case is for deletions. I detect whether or not the user selects at least one document and post an error message if they do not, using view.postScript.

I want to add a confirmation dialog box, confirming that the user wants to take the action on the documents (like delete them) but cannot find a way to do it.

Ideally I want to do this all in my current SSJS.

My code is below, with a stub in for where I want to ask the user for confirmation.

Any help would be greatly appreciated.

//Did the user select a document
var hasSelected:Boolean = false;
for (var id in SelectedDocs.getSelectedIDs()) {     
        hasSelected = true;
        break
}

//If false then set a warning
if (hasSelected == false)
{
x="alert('Error\\n\\nPlease select one or more documents to delete.\\n\\n');";
view.postScript(x)
return
}

//If true then ask confirmation
if (hasSelected == true)
{
}

var rspView:NotesView = database.getView("(dbAllRpPCTasks)")

for (var id in SelectedDocs.getSelectedIDs()) {     

        //Get each selected doc
        var doc:NotesDocument = database.getDocumentByID(id);

        //Get child docs and delete them
        var key:String = doc.getItemValueString("ID");
        var dc:NotesDocumentCollection = rspView.getAllDocumentsByKey(key);
        if (dc.getCount() != 0) 
            {dc.removeAll(true);}

        //Delete the selected doc
        doc.remove(true)
        doc.recycle();
        SelectedDocs.setSelectedState(id,false);
}

Thanks for all the suggestions. I am responding to Frank's answer. Trying to write CSJS that will determine if the user selected docs and then proceed or not.

In the on click event of my button in the CSJS I have the following:

var dtList = document.getElementsByName("#{id:dataView1.getSelectedIds()}");
confirm("What is the length?" + dtList.length);
confirm("Can I get an item?" + dtList.item(0));

It returns a length of zero and the item is undefined.

回答1:

Unlike LotusScript, XPages code cannot wait for user input. Think of it like calling an agent to run on server and adding a UIWorkspace.prompt() in there (which will throw an error, because user interaction is not allowed).

The best recommendation would be to add the confirmation prompt as CSJS to the button the users are initially clicking, e.g.

return confirm("Are you sure?");

If they've selected documents, they'll be prompted before they continue. If they have not, it might prompt some users to select the documents anyway. It's hard to have sympathy with complaints from a user who didn't select any documents, clicked that they wanted to continue, then complains at getting another dialog.



回答2:

Have you tried using Simple Actions for the buttons? I use Confirm Action to verify the user didn't hit a button by accident (a common issue unfortunately). Next, I validate my form and display any messages in a custom message area (Thanks to Tommy Valand) but you can use a normal Message area.

Create an Action Group and place your SSJS expression (or EL) to execute conditionally. Display the message within the page instead of a popup.



回答3:

A bit of theory - every action can have these combinations:

  • CSJS
  • CSJS + SSJS
  • CSJS + SSJS + CSJS
  • SSJS
  • SSJS + CSJS

So you have to combine one or more actions to accomplish what you want to do. Techniques usable to chain calls:

  • XSP.partialRefreshGet/Post
  • view.postscript (combined with the above)
  • onComplete event's property
  • inline CSJS computed at render phase
  • hidden button initiated by CSJS (postscript/onComplete)
  • ExtLib RPC call

My advice to your use-case is to detect in event's CSJS (before execution) whether user selected any document (DOM operations). If not, use return false; to stop event execution (with proper explanation in CSJS prompt).

Edit: exact use case Divide your use cases to two problems: condition and execution.

1. Condition

Do you REALLY need to call SSJS to get that information? It depends on what you use to select documents - what is your SelectedDocs object? In some cases, you can render (literally) number of selected docs to DOM (assuming selection fires partial/full refresh) and use it in CSSJ before SSJS is called. So rethink your needs/approach.

2. Execution

Does it really need to be SSJS + CSJS + SSJS combination? I doubt so.

Here's example for your use case based on SSJS(+CSJS). It simulates 50:50 chance to show the prompt or delete documents. You get the idea, just update the first action group to get the selected count.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    xmlns:xp_1="http://www.ibm.com/xsp/coreex">
    <xp:button
        value="Label"
        id="button1">
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="partial" refreshId="button1">
            <xp:this.action>
                <xp:actionGroup>
                    <xp:actionGroup>
                        <xp:executeScript
                            script="#{javascript:requestScope.docnum = @Integer( @Random() * 2 );}">
                        </xp:executeScript>
                    </xp:actionGroup>
                    <xp:actionGroup
                        condition="#{javascript:requestScope.docnum == 0;}">
                        <xp:executeScript>
                            <xp:this.script><![CDATA[#{javascript:view.postScript('alert("No documents selected...");');}]]></xp:this.script>
                        </xp:executeScript>
                    </xp:actionGroup>
                    <xp:actionGroup
                        condition="#{javascript:requestScope.docnum != 0;}">
                        <xp:executeScript
                            script="#{javascript:// delete documents}">
                        </xp:executeScript>
                    </xp:actionGroup>
                </xp:actionGroup>
            </xp:this.action>
        </xp:eventHandler>
    </xp:button>
</xp:view>