Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Hopefully I can explain my question clearly here.

I want to change the behavior of this button that appears on our Opportunity page: New Payment Button

The Opportunity object has a custom rollup field that counts the number of products associated with the opportunity. If the number of products associated with the opportunity = 0, then pressing the "New Payment" button should pop-up a message box that says something like "Eror: Cannot process a payment for an opportunity with no associated products".

The Payment object is managed, from the PaymentConnect package by Linvio. (Not sure if this impacts what I'm trying to do)

I can edit the button to override its functionality or create a custom button, but I'm having trouble. I don't want to change the overall functionality of the button. I just want to add that simple check before allowing it to continue.

Is it possible for me to write a simple override for this button that does the check I mentioned above before it punts it to the (managed) VisualForce page that the button now goes to?

I tried to create my own VisualForce page to duplicate the functionality of the one that the button currently directs to, but since it is in a managed namespace I cannot do it.

Any ideas or help would be much appreciated.

share|improve this question
add comment

2 Answers

up vote 4 down vote accepted

Try creating a new Javascript button, type should be "list button" (last option, without checkboxes). Call it "New Payment".

Implement your check there, something like

if({!Opportunity.Product_Rollup__c} == 0){
    alert('Uh oh');
} else {
    location.href = '(url to make new Payments here)';
}

Finally go to the Opportunity page layout (all of them if you have several?), edit related lists, untick the checkbox next to standard "New" button and add your custom one.

As this is managed and in future the package devs might decide they need new parameters passed to this VF page or something crazy like that I'd advise you to try not to make the url /apex/SomePage... and even not /a07/e?someParams (which format is OK for normal "new" pages) but rather try using URLFOR function.

P.S. Make no mistake - I'd recommend preventing saving by adding a Validation rule or some other "hard check" (trigger?) to the object anyway. It's a bit of security by obscurity, Salesforce power user might be able to hand-craft the link, access the Payments tab and hit "New" there or he'll use a mobile device with an app ;) This is valid visual client-side helper/reminder but such logic should be replicated server-side.


EDIT to include comparison of old & new URLs:

Original URL:

https://(instance).salesforce.com/setup/ui/recordtypeselect.jsp?
ent=01Id0000000jpap&
retURL=%2F006K00000069AnT&
save_new_url=%2Fa0B%2Fe%3FCF00Nd0000004bboJ%3DTest%2BPerson-Conference%2BRegistration-%252410-2013-01-18%26CF00Nd0000004bboJ_lkid%3D006K00000069AnT%26scontrolCaching%3D1%26retURL%3D%252F006K00000069AnT

Custom "new":

https://(instance).salesforce.com/setup/ui/recordtypeselect.jsp?
ent=01Id0000000jpap&
retURL=%2F006K00000069AnT&
save_new_url=%2Fa0B%2Fe%3FretURL%3D%252F006K00000069AnT

So the only difference is in the content of form prepopulation to be performed when user cicks "Save & New". Let's urldecode it:

/a0B/e?
CF00Nd0000004bboJ=Test+Person-Conference+Registration-%2410-2013-01-18&
CF00Nd0000004bboJ_lkid=006K00000069AnT&
scontrolCaching=1&
retURL=%2F006K00000069AnT

So - the package developers just made sure that Opportunity Id & Name will be prefilled in "Save & New" too. But this works for me already (I have custom object under Account, not Opportunity and the Account Name is prefilled on subsequent "save & new" without problems).

Long story short - experiment but I doubt you need it ;)

share|improve this answer
    
Thank you very much! I am having a little trouble implementing your solution, and I was wondering if you could help with one more aspect: I used the URLFOR function as advised. I used: location.href = '{!URLFOR($Action.pymt__PaymentX__c.New)}'; However there are more parameters being passed in the URL generated by the original button than the one I created. How do I determine what those parameters are so I can include them in my button as well? Do I decode it from the URL or is there a better way? –  Aaron P. Jan 18 '13 at 23:56
    
Would help if you can show us sample link (there might be some stuff specific to this package I'm not familiar with, especially since it's VF page and can take any kind of params). Standard stuff: retUrl is target if you'll hit cancel but most likely what you see there is the form prepopulation trick to set Opportunity lookup and other Payment fields. Start with salesforce.stackexchange.com/questions/937/… and experiment? Also comments in salesforce.stackexchange.com/a/4582/799 ;) –  eyescream Jan 19 '13 at 0:08
    
Sure. The URL that the standard 'New' button generates looks like this: Original URL. Looking through those links, it looks like my button URL has all the same parameters, but is shorter for some reason. URL generated by my button –  Aaron P. Jan 19 '13 at 0:32
    
Eyescream you are a life saver. Can I buy you a beer somehow? –  Aaron P. Jan 23 '13 at 3:47
    
Sadly I don't plan to go to US anytime soon ;) But you're more than welcome to jump over the pond for Cloudforce/Cloudstock London, approx. June I believe! –  eyescream Jan 23 '13 at 5:49
add comment

I think I would create a custom Javascript button (or edit the existing button's Javascript) and in the button's Javascript, reference a static resource containing a small autoexec Javascript function that will do the initial check.

Then, add this Javascript to the button's body with a $RequireScript tag. As a result of the initial Opportunity check in the autoexec function, you can select and change the text of the button, or even disable it if you don't want the users to be able to invoke its functionality based on the initial query's result. Upon clicking the button, having added custom dialog code to popup based on the results of the initial Opportunity query or based on the text of the button if you changed it, is easily done as well, but will mean maintaining two sets of code (the static resource and the button's code). I think it makes a better user experience for your question to disable the button if the user shouldn't click it.

However, invoking the same function as the original button is easily done by inspecting it in Chrome or FireBug, which is likely just a url to a standard controller or the package's page. Even if you have to invoke your own VF page from your custom button, your VF page is easily redirected to the managed code's page as an alternative. But if all you do is enable or disable the button, you won't have to add processing logic to the button at all, just include the script that gets loaded as part of the page and determines the button's usability.

Since the static resource Javascript (by virtue of being loaded by $RequireScript and being an autoexec function) will execute as part of the page load (not when the button is clicked), you can essentially change the functionality of the page just as it is being rendered, including dynamically adding or changing the button's code if you wish (DOM manipulation). In this way, the static resource Javascript kind of functions like a GreaseMonkey script or a browser plugin whenever the page is rendered.

share|improve this answer
    
Thank you for this advice. I wanted to keep the button active in this case so that I could display a popup instructing the user as to why they could not add a payment. However, I did not know that I was able to do what you described here and I can see this being useful information in the future. I will be saving this answer to add to my personal knowledge repretoire for the future. –  Aaron P. Jan 19 '13 at 0:43
    
+1 It's interesting and I'll think about it next time I'll have to work on similar req. I found the JS in resources to be a bit limited (for example it's not parsed server side so you can't have {!...} merge fields, you need to query for everything. And so far I was embedding them only in section names, not as new buttons (and since section will be rendered before any rel. list & DOM won't be complete yet - useless). Nice trick, worth playing with later :) –  eyescream Jan 19 '13 at 9:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.