Add button to existing standardController page SalesForce - salesforce

I want to add a button to an existing SalesForce object page that already has a standardController and page built by salesforce.
I have a utility class that I want to call a function by a button on my object.
Currently, I only have seen ways of doing this by a WebService, which I included the code snippets below. I am thinking there has to be another way, due to the fact I want to reuse this code in other places that do not require a webservice, and I want to avoid writing two procedures for same thing. I know I could use a wrapper I guess, but want to see if there is another way of adding a button that is more in line with the new salesforce way of visualpages, and not s-controls/web services.
So, when I add a button on the salesforce page by going to setup-->create-->objects then scroll down to add a button, it requires that the button be an scontrol or javascript. I found this technique
Apex code:
global class class1{
WebService static Integer method1(String iTitle){
Your logic here
}
}
Custom button code:
{!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/14.0/apex.js")}
var result = sforce.apex.execute("class1", "method1",{iTitle : noteTitle});

Related

Call visualforce Page through scheduled apex

I have a scheduled class set up that i would like to work such that it calls a visualforce page that does things to the record. Currently the user has to click the button on the individual record which calls the visualforce page. I would like for the scheduled apex to run and execute this automatically. Here is what i have so far. I put the name of the visualforce page commented out as a place holder for now. Any guidance would be greatly apprecaited!
global class LastLoginUpdate implements Schedulable{
global void execute(SchedulableContext SC) {
List<Case> Cases = [SELECT ID, status, Queue_for_Traccinvoice__c FROM Case WHERE status = 'to be billed'];
for(case c : Cases){
if(c.status == 'to be billed'){
//Call CreateTraccInvoice;
}
}
update cases;
}
}
Instead of 'calling' a page, you should execute the action method in the Controller class that is responsible for that page. If you look at the page you mentioned, at the top you should see something like <apex:page controller="myController" ... where myController is the name of the class that contains logic for that page. Unless the button you were talking about is a standard action (like Save or Delete), there is a custom action defined in that Controller class and it is linked to the button you mentioned via action="..." attribute on the <apex:commandButton> tag.
Now that you know the Controller action that is responsible for handling a button click, you just have to create an instance of that controller in your schedulable class, initialise it with Case ID and call that action programatically.
P.S. to make the solution more future-proof and avoid hitting governor limits, instead of reusing existing action and potentially executing DML statement for each individual case that you loop through, consider modifying replicating the logic of action function in your scheduled class but modifying it so that it can handle a list of cases as an input.
-- Don't know what is purpose of calling VF page. If the VF page in turn calling apex method to do some action/function, you can very well instantiate the Apex class here and call the method.
Also you don't need to check the "if(c.status == 'to be billed')" again in the for loop. You already fetching the records based onthe status 'to be billed only.

Put custom links outside weblinks section

How can I put custom links outside the web links section in a salesforce page?
Or is there a way I can create more than one weblinks section?
If not is there a way I can create a custom field that can call a javascript method ? (my custom links calls a js method that after validation will call a web service to do some work.)
I tried creating a custom field (formula) but I wasnt able to call a js function from there, or put some script.
What I want to do is spread my custom links I have in the weblinks section into different sections on the page.
I have used this method to override link and button actions in the past. You could use the same method for move elements around the page too.
Create a visualforce page and use it to override the standard page for the object you want to modify. The override page needs to use the standardcontroller for that object. You can use an extension controller for adding Apex functionality if necessary.
Use the detail tag to render the guts. Then put in a script tag to select the anchor links you want to move around the page. It will take some inspection with your browsers debugger to find exactly what you are looking for.
<apex:page StandardController="CustomObject__c" extensions="CustomObjectController" >
<apex:detail relatedList="false" inlineEdit="true" id="mydetail" />
<script>
// select your elements you want to move, edit or delete here
</script>
</apex:page>

Show custom pop up warning message when user changes any value (text box/LOV) on page

I have requirement to show custom pop up warning message when user changes any value (text box/LOV) on page and close tab/cancel button by mistake.
Option I tried are:
a) Within application we are using a complex task flow/RegionModel for 7 different scenario's. Also requirement is to display custom message - Hence could not use approach "unsaveddatawarning"
http://www.oracle.com/technetwork/developer-tools/adf/unsaveddatawarning-100139.html
b) Second option I tried was to have custom region controller:
CustomRegionController implements RegionController
Inside validateRegion(RegionContext regionContext) thought to find if page data is dirty
AdfFacesContext.getCurrentInstance().getDirtyPageHandler().isDataDirty();
or
DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCDataControl cDataControl = dcBindings.getDataControl();
boolean dirtyFlag = cDataControl.isTransactionModified();
In both scenario it always gives true (seems due to common set of VO/View Link application module always gets dirty when data is being rendered on page load).
Last option I am left with is to invoke valueChangeListener for each element (textbaox, LOV, Check box). I do not like this option at all. Please suggest if there can be better way to handle this scenario.
Why is using a value change listener a problem? Have each input component call the same VCL method in the backing bean. If necessary you can get the component id from the vcl event object.

Custom Button or Link to a Visualforce page with a custom controller

I have a Visualforce page using a custom controller that is used to edit multiple records under an opportunity.
I'd like to create a custom button or link from Opportunities to this Visualforce page.
Currently the link looks like:
/apex/ExamplePage?oppId={!Opportunity.Id}
This works fine in the development sandbox, but when it is deployed as part of a managed package the link breaks as the page reference doesn't have the namespace prefix.
I found the post Managed Package Redirecting Problem on the Force.com Discussion Boards which implied it should be possible to use $Page to reference the Visualforce page in the URL. E.g.
{!URLFOR($Page.MyExamplePage,'',[objectId = campaign.id])}
But doing so only gives me the syntax error:
Error: Field $Page.MyExamplePage does not exist. Check spelling.
There is another part to the post that suggests using an Apex class and Execute Javascript to work around it. But it appears to me that this has just moved the namespace issue into the Javascript.
How can I safely reference the Visualforce page to work both inside and outside a managed package?
Best to do this from an Apex PageReference return value. Something like this will work:
public PageReference returnPage()
{
return Page.MyExamplePage;
}
Then call this from Visualforce:
<apex:commandButton value="Go To New Page" action="{!returnPage}"/>
The Apex Page call will handle the translation for you.
[EDIT]
Create a bare bones Visualforce page like this:
<apex:page standardController="Opportunity" extensions="TheController" action="{!returnPage}"/>
Add the above returnPage() method to a new TheController (or whatever) class. It doesn't even need a constructor. The class can look like this:
public TheController
{
public PageReference returnPage()
{
return Page.MyExamplePage;
}
}
Then from the Opportunity settings page go to Buttons and Links and create a new custom Visualforce button selecting the new page you just created.
That should do it.
It occurred to me that one less than ideal option would be to create two custom buttons in each case. One with the managed package namespace and one without.
When building the package the correct custom button could be selected.
One issue with this approach is the need to maintain two custom buttons.
It seems the answer is simply /apex/package__Page as provided here by #zachelrath. I can confirm this works in managed packages in production orgs as well as in development.
The post on the developer boards that you've linked to shows the following javascript being used for the button:
{!REQUIRESCRIPT("/soap/ajax/15.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/15.0/apex.js")}
var pageUrl = sforce.apex.execute("mynamespace.PageUrl", "getPageUrl", {objectId:"{!Campaign.Id}"});
window.location.href = pageUrl;
i.e. they're using javascript to call a webservice method in the class they've defined in order to get the page reference. Doing this would allow you to get the URL of the page in apex, where the managed package won't play an impacting part.
That said, the first parameter is the fully-qualified class name, so you could probably check the return value for an error (I don't know the error return value, so I'm assuming it's null here):
// try the namespace first
var pageUrl = sforce.apex.execute("mynamespace.myClass", "getPageUrl", {objectId:"{!Campaign.Id}"});
if (pageUrl == null)
{
pageUrl = sforce.apex.execute("myClass", "getPageUrl", {objectId:"{!Campaign.Id}"});
}
window.location.href = pageUrl;
Obviously you need to check what happens when sforce.apex.execute() fails, and you'll likely want some more error handling.

Salesforce: Launch S-Control in a new window from VisualForce

I'm writing a VisualForce page to replace an old legacy S-Control.
Originally the Custom S-Control was launched from a Custom Button, and it opened in a new browser window (The S-Control is type HTML, and the Custom Button has Behavior: Display in new window)
For certain old records, I want to do a similar thing from VisualForce.
So: Do HTML S-Controls have a URL that I can launch using a link? In which case, how do I figure out the URL?
Or:
Is there a way of embedding 'Custom Buttons' (that is, the buttons defined in "Setup->Customise->Account->Buttons and Links") into VisualForce pages? If so, I can embed the existing button that knows how to open the S-Control
Or:
Can you suggest some other way of doing this? Key features: Open an S-Control in a new window from VisualForce.
Thanks
Got an answer from this forum post courtesy of aballard:
Basically, the !Urlfor() function can be used to get the URL of an S-Control. So, you can use an outputLink like this:
<apex:outputLink value="{!UrlFor($SControl.my_scontrol_name)}"
target="_blank">Show SControl</apex:outputLink>
If you need to pass an object ID to the S-Control, you can add a second parameter that calls a propery on the custom controller, e.g:
<apex:outputLink value="{!UrlFor($SControl.my_scontrol_name, AccountID)}"
target="_blank">Show SControl</apex:outputLink>
... where AccountID is defined on the custom controller as public string getAccountID()
See also this blog post at SalesforceSource for more info on the UrlFor function.

Resources