1

I'm trying to delete selected doc from viewPanel1. The view is categorized ( can be > 1 category ) and is listing documents from 2 different datasources, let say: Cdoc and Pdoc. These docs. are linked by a common field.

my scenario: If the users select a Cdoc => the delete action will take place to the respective Cdoc but also for the all Pdoc being in the same category. If the user selects a Pdoc => delete just the Pdoc. Also, I would like to add some confirmation text with some information ( Value fields ) from the selected documents.

enter image description here

I tried the following

    var viewPanel=getComponent("viewPanel1");
var docIDArray=viewPanel.getSelectedIds(); 
for(i=0;i < docIDArray.length;i++){

    var docId=docIDArray[i];
    var doc=database.getDocumentByID(docId);
    var formName = (doc == null)? null : doc.getItemValueString("Form");


if( formName =="fmPersContact" ){
     .....
   } // in this case, it works OK.

else if ( formName =="fmCompanie" ){ // here if I selected > 1 Cdoc, it deletes just one Cdoc + the respective PDocs.

var doc:NotesDocument = null;
doc=database.getDocumentByID(docId);
var ky:java.util.Vector = new java.util.Vector();
ky.add(doc.getItemValueString("txt_NumeCompanie"));

... // delete method }

Could you tell me what I did wrong and what am I missing in the above code? thanks for your time!

Florin M.
  • 2,159
  • 4
  • 39
  • 97
  • I'mn not sure I'm getting the exact question. It seems a little vague. My recommendation is to not use a view control. Use a repeat control. You get a LOT more power and flexibility with that. – David Leedy Aug 11 '14 at 19:53
  • I have asked this a few times already, but what exact part of the deletion process are you having issues with? Is it comparing the form names to see what sort of deletion process is necessary? Is it deleting in a loop? This question is too vague for anyone to really help you. – Greg Aug 13 '14 at 07:44
  • As for the confirm message, I know that it is possible to do it via CSJS, but my quick and dirty response to that in my own recent app was to make my own server side confirm dialog. The text was calculated to see if the user selected 1 and only 1 document, if not then the text was an error message and the ok button was hidden, or else displayed the proper text. The ok button event was the delete function. Whether or not this is best practice, I cannot say and I am therefore not putting it in the answer. -- and I am trying to help you, not hurt or attack you. We cannot answer vague questions. – Greg Aug 13 '14 at 08:22
  • I see a few things. 1. when getting all documents from one category, you do not need to use a vector. the rest ill put into answer – Greg Aug 13 '14 at 11:08
  • you are not swallowing exceptions, are you? Are you checking if your routine threw anything? – Greg Aug 13 '14 at 11:16
  • check out my edit and remember that you should probably add a check to see if the collection is empty – Greg Aug 13 '14 at 11:26
  • are checking whether the string you are adding to the key vector is empty? Since you are only getting the docs in one category, you do not need a vector. Also, does the view have more sub categories? This has no check if the key is empty and will only work with a view with one category. – Greg Aug 13 '14 at 11:56
  • I see. So if my view had 2 categoriez it won't work even if I create that array with the respective categories? – Florin M. Aug 13 '14 at 11:58
  • if you have a view with a category and sub category and you want to get all the documents in that sub category, then you must use a vector to get at it. If you include a simple string or a vector with only one value, then the documents in the sub category will not be returned. The vector can be thought of as "cat1", "subcat", "furtherSubCat". – Greg Aug 13 '14 at 12:06
  • I edited the answer to give you a hand with the stuff you added. Also, with deleting all docs that the user selects, you are going to run into issues with going through the list, if the user selects the top level document, you delete all that are under them, then you move to the second document in the array of selected documents which is the sub document of the top layer you just deleted, the document is already gone. – Greg Aug 13 '14 at 13:12
  • I think your getSelectedDoc is returning only one doc., omitting the fact that the user can select multiple documents for deletion. – Florin M. Aug 14 '14 at 05:30
  • OF COURSE IT IS! I have been saying that many times! I am giving you the tools to complete the work on your own! SO is not a site to have someone write the function for you, but to ask for help with it. Now I have shown you how to get at the documents, you could write the delete function directly in a loop using that code, or not, it is your choice, but the answer I gave with the following comments gives you all the tools you need to get this done. I am not sorry if that also means that you have to think a little for yourself! – Greg Aug 14 '14 at 06:26
  • I verified myself using view.postScript("alert('"+doc.getItemValueString("txt_NumeLocalitate")+"')"); for the key and it seems it is null. I must see why. I created my own mechanism for getting the selected docs. I'm not using a function for the selected docs. Me happy! I'm close to finish. – Florin M. Aug 14 '14 at 06:59

1 Answers1

0

The first thing you want to do is confirm. Unlike Lotusscript, you cannot use a function in the middle of a script to open the confirm dialog and get the answer. To do this, I recommend using the confirm simple action before going into an execute script simple action.

<xp:button
        value="delete"
        id="button1"
    >
    <xp:eventHandler event="onclick" submit="true" refreshMode="complete">
        <xp:this.action>
            <xp:actionGroup>
                <xp:confirm message="Are you certain?"></xp:confirm>
                <xp:executeScript
                    script="#{javascript:doSomething();}"
                >
                </xp:executeScript>
            </xp:actionGroup>
        </xp:this.action></xp:eventHandler></xp:button>

EDIT
In the past, I have also used built my own dialogs with the extension library, filled the text in with SSJS and then called the doWhatever() or close() from the dialog itself. This is not the best solution as it requires an update from the server to get the string. The best solution would be, as Paul Withers says, to use CSJS to perform the confirmation. I have yet to do this though.
/EDIT

For your delete function, I recommend getting the document you want to delete, then tell whether it is a P- or C- doc, either by the form name or whatever mechanism you use, and then either delete the single document or by getting a documentcollection from the view by using getAllDocumentsBykey(), then iterating through them all, deleting them one by one.

var ky:java.util.Vector = new java.util.Vector();
ky.add("MainCat");
ky.add("subCat");
ky.add("subCat2");
var vw:NotesView = database.getView("vw_myView");
var docs:NotesDocumentCollection = vw.getAllDocumentsByKey(ky);
//... delete stuff...
//dont forget to recycle

Post Question Edit
I recommend the following to get the form name:

    var getSelectedDoc = function(){
        var vwPnl = getComponent("viewpanel");
        var ids = vwPnl.getSelectedIds();
        var id = null;
        var doc:NotesDocument = null;
        if(ids.length > 0){ //could use for loop var i = 0; i < ids.length;i++
            id = ids[0]; //could pack all ids into java.util.ArrayList and return that list to work on further
//be warned that if the user selects a parent doc and those automatically deleted by it that you need a mechanism to check if the document was already deleted!
        }
        if(id != null){
            doc = database.getDocumentByID(id);
        }
        return doc;
    }

    var doc = getSelectedDoc();
    var formName = (doc == null)? null : doc.getItemValueString("form");
    if(PDOC_FORM_NAME.equalsIgnoreCase(formName)){
        deleteFunctionComplete(doc);
    } else if (CDOC_FORM_NAME.equalsIgnoreCase(formName)){
        deleteFunctionTwo(doc);
    } else {
       // uh-oh
    } 

this also allows you to have the document in case you want to delete it right away.

Edits for comments If Cdoc should delete more than one document, then yes. You should be using the getAllDocumentsBykey keeping in mind that the view needs to be built for it. By that I mean if you have a view with one single category, there is no issue, just plug in the string and you are fine. If you have a view with three categories, you cannot feed a vector into the getalldocs function with only two values, it must be all three. So, you want to delete all for "mycomp" with the underlying pdocs "Greg" "Sally "Bob", just use alldocsbykey("mycomp"), if the view looks like:

mycomp
---Greg
---Sally
---Bob

but if the view looks like

Poland
---mycomp
------Greg
------Sally
------Bob

then the a vector with poland and mycomp must be used. "poland" does not get the correct documents. --just an fyi and pitfall that is sometimes had.

Edit after further question clarification
I prefer this loop style to remove docs

 var doc_temp:NotesDocument = null;
var doc_toDelete:NotesDocument = null;
var coll_docs:NotesDocumentCollection = ...; //get document collection

var doc_nextDoc = coll_docs.getFirstDocument();
while(doc_nextDoc != null){
    doc_temp = doc_nextDoc; //set document to delete
    doc_nextDoc = coll_docs.getNextDocument(doc_nextDoc);  // set next document before deletion
    try{
        doc_temp.remove(true);//lots of errors can happen here, such as ACL settings
    } catch(e) {
    //handle, or just break
    } finally{
        if(doc_temp != null) try{doc_temp.recycle()} catch(e){}// try to recycle, could also cause errors
        doc_temp = null;// for the sense of completeness 
    }
}

Even further edit based on the question edits
of course you are only deleting one Pdoc, the way you have that set up, you are only ever returning one document. You could expand the getSelectedDoc() to put all selected documents into an java.util.ArrayList or something, and then use that arraylist to delete more than one at a time, but that could be dangerous depending on what you do because NotesDocuments are not serialisable. In that case, I recommend using the same code that you use for getSelected doc, use a for loop to get the document IDs, get the document, if the document is not null, then delete.

apropos getAllDocumentsByKey(with a vector)

The way this is currently set up, no Vector is necessary.
If you have a view with a category and sub category and you want to get all the documents in that sub category, then you must use a vector to get at it. If you include a simple string or a vector with only one value, then the documents in the sub category will not be returned. The vector can be thought of as "cat1", "subcat", "furtherSubCat"

Furthermore, there is no check here to see if the string returned from the document is empty. This should be done. There is also no check to see if the DocumentCollection is empty. This should also be done. My expectation is that there is an issue retrieving the collection based on above mentioned reasons.

Greg
  • 714
  • 4
  • 16
  • 2
    Bear in mind that any SSJS that you push to a confirm prompt has to be calculated before the confirm prompt is written to the browser, because it's run as CSJS. So it will not take account of any changes made by the user between the page or portion of the page being written to the browser and the confirm being presented. It will be the value as at the last time the page was rendered. If you want to use anything updated by the user after the page was last rendered, you will need to use the Client Script area, not a Confirm simple action. – Paul Stephen Withers Aug 11 '14 at 13:01
  • @Greg Thanks for your tips. I create the first if case ( the easy one ... when the doc is PDoc ), but I'm having some troubles if the doc is Cdoc. So in this case, I should use the getAllDocumentsByKey method and going through documents one by one ... ? – Florin M. Aug 13 '14 at 10:43
  • my comment is too long, I will edit the question. Please also include your errorhandling code in the question so I can take a look at it for the "deletion automatically taking place" issue. – Greg Aug 13 '14 at 10:44
  • Sorry, that was my mistake. Currently I'm working * thanks to your tips and help * at the 2nd case when I select a Cdoc => I must delete all the Pdocs as well, which have the same key... Is it possible to concatenate some fields values to the confirmation text? like: "Hey, you selected a Cdoc which has the form called >bla bla<. Are you sure you want to delete"? – Florin M. Aug 13 '14 at 10:45
  • There is a way to do it with CSJS (I cannot be helpful there), but I normally do it with SSJS, as per the comment I made to the question with additional functionality and purpose than a simple confirm dialog. The string is calculated and put into a scopedVariable and then presented to the user, I also perform checks to make sure that certain criteria are met and present any issues to the user in the same confirm dialog. Maybe not a best case, but it works for me. – Greg Aug 13 '14 at 10:52
  • @Greg I get: Exception occurred calling method NotesDocumentCollection.getNextDocument(lotus.domino.local.Document) null at doc_toDelete = coll_docs.getNextDocument(doc_temp); // set for the next iteration .. must be done here in finally in case of errors. no endless loops – Florin M. Aug 13 '14 at 11:41
  • I also noticed if I select 2 docs ( of Pdoc type ) only one is deleted. – Florin M. Aug 13 '14 at 11:55
  • of course you are only deleting one Pdoc, the way you have that set up, you are only ever returning one document. You could expand the getSelectedDoc() to put all selected documents into an java.util.ArrayList or something, and then use that arraylist to delete more than one at a time, but that could be dangerous depending on what you do because NotesDocuments are not serialisable. – Greg Aug 13 '14 at 11:59