+ Start a Discussion
JNicJNic 

Javascript function on VF page not working

Hey guys,

 

Can anyone tell me why these don't update the status__c field of the record I specify when clicking an outputLink?

 

 

 

<script src="../../soap/ajax/18.0/connection.js" type="text/javascript"> <!-- Testing some simple field updates in jScript rather than using controllers --> function departShp(){ var shp = new sforce.SObject("Shipment__c"); shp.id = "{!Shipment__c.id}"; shp.Status__c = "In transit"; result = sforce.connection.update([shp]); if (result[0].getBoolean("success")) { log("Shipment with id " + shp.id + " updated"); } else { log("failed to update shipment" + shp.id]); } } function updateShp() { try { var shp= new sforce.SObject("Shipment__c"); shp.Id = "{!Shipment__c.Id}"; shp.Status__c = "In transit"; var result = sforce.connection.update([shp]); if (result[0].getBoolean("success") == false ) { alert(result[0].errors.message); return; } window.top.location.href=window.top.location.href; } catch (e) { alert(e); } updateShp(); } </script>

 

The button

 

<apex:form > <apex:outputLink value="/{!Shipment__c.id}" onclick="updateShp()" rendered="{!$Profile.Name = 'System Administrator'}"> Shipit </apex:outputLink> </apex:form>

 

Both of these are pulled from examples I found: one in ajax dev guide, and one in custom button that marks a task as complete provided by Salesforce.com labs for free...

 

Can't quite figure out how to make it work for me.

 

I'd like to avoid using APEX because it goes towards my total apex limit, and I have to build test classes, so it's not very efficient.

 

Thanks!

JNH

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
CaptainObviousCaptainObvious

Instead of an outputlink (which may be the source of your problem), how about this:

 

<apex:outputPanel rendered="{!$Profile.Name = 'System Administrator'}"> <span onclick="departShp('{!Shipment__c.id}')">departShp()</span> </apex:outputPanel>

 

And then, in your javascript...

 

function departShp(sid){ var shp = new sforce.SObject("Shipment__c"); shp.id = sid; shp.Status__c = "In transit"; result = sforce.connection.update([shp]); if (result[0].getBoolean("success")) { log("Shipment with id " + shp.id + " updated"); } else { log("failed to update shipment" + shp.id]); } }

 

Edit: You can also give it the appearance of a link with some inline styling:

 

 

<apex:outputPanel rendered="{!$Profile.Name = 'System Administrator'}"> <span onclick="departShp('{!contact.Name}')"

style="text-decoration:underline;cursor:pointer;">departShp()</span> </apex:outputPanel>

 

Message Edited by CaptainObvious on 03-26-2010 12:08 PM

All Answers

SteveBowerSteveBower

Hi, I'd have a few questions:

 

1. Is the Javascript console of whatever browser you're working with yielding any errors in the Javascript?  (For example, do you need a "var" before the result= in the departShp function? Or anything?)

 

2. Is your Javascript being called at all?  (Throw an alert() message in the beginning of the updateShp() function.)

 

3. Why are you calling updateShp() again at the bottom of updateShp()?   That seems wrong.

 

4. departShp is never being called.

 

The apex controller for this is like four lines long, the test case would also be something like seven lines.  I can perhaps see wanting to avoid Apex because of limits, but not for efficiency.  :-)   Best, Steve.

 

 

 

 

 

 

JNicJNic

Well when you factor in deployment + test classes apex takes too much time for something little like this...

 

It's not that agile for simple things like this - I was hoping I could just get this into production quickly. If I do it thorugh apex, it's gonna double the work...

 

It's also kinda silly that I can create a custom detail button that exectutes on click javascript that does this job and works:

like so:

 

/* This code allows the javascript to access the API and push data into the Org.*/
{!requireScript("/soap/ajax/10.0/connection.js")};
sforce.connection.session = "{!$Api.Session_ID}";

function updateShp( )
{
try
{
var shp= new sforce.SObject("Shipment__c");
shp.Id = "{!Shipment__c.Id}";
shp.Status__c = "In transit";
var result = sforce.connection.update([shp]);
if (result[0].getBoolean("success") == false ) {
alert(result[0].errors.message);
return;
}
window.top.location.href=window.top.location.href;
}
catch (e) {
alert(e);
}
}

updateShp();

 

 

but that I can't even use that button on my VF page... Only on a standard object layout.Our Shpiment view is overridden.

 

 

According to the ajax guide on page7 ( http://www.salesforce.com/us/developer/docs/ajax/apex_ajax.pdf )

To use JS in a VF page you use:

 

<apex:page>
<script src="../../soap/ajax/18.0/connection.js" type="text/javascript"></script>
...
</apex:page>

 

 So then I just threw the code in there... minus the
{!requireScript("/soap/ajax/10.0/connection.js")};
sforce.connection.session = "{!$Api.Session_ID}";

 

But no go.

 

 

 

Message Edited by JNic on 03-25-2010 01:49 PM
SteveBowerSteveBower

I agree that there are good and bad points to both mechanisms.  Either way...

 

Two changes: 

 

set up your VF page with:

 

<apex:page standardController="Shipment__c"> <script src="../../soap/ajax/18.0/connection.js" type="text/javascript"></script> <script> /* This code allows the javascript to access the API and push data into the Org.*/ sforce.connection.sessionId = "{!$Api.Session_ID}"; ... your javascript.... </script> </apex:page>

 


 

 

The Requirescript tag that you removed simply brought in the connection.js script, and you (correctly) replaced that with the script tag.  However now you're establishing a new execution context for the page and you do need to set the session id.    It's "sforce.connection.sessionId" instead of "sforce.connection.session".

 

Also, you're trying to reference "{!Shipment__c.Id}" in your javascript.  When saving it as a VF page, since you weren't using a Controller it doesn't know what you're referring to.  By adding the standard controller reference to the Page tag, it resolves the reference.

 

When you just launch the Javascript from an onclick button, salesforce takes care of making that substitution for you automatically.  With VF you have to do it yourself.  Tradeoffs, tradeoffs, tradeoffs... :-)

 

Best, Steve.

 

 

 

JNicJNic

Thanks Steve. I gave it a shot, but it's still not working. Here's my whole page:

 

 

<apex:page standardController="Shipment__c" extensions="ShipmentController" tabStyle="Shipment__c" > <script src="../../soap/ajax/18.0/connection.js" type="text/javascript"></script> <script type="text/javascript"> sforce.connection.sessionId = "{!$Api.Session_ID}"; <!-- Testing some simple field updates in jScript rather than using controllers --> function departShp(){ var shp = new sforce.SObject("Shipment__c"); shp.id = "{!Shipment__c.id}"; shp.Status__c = "In transit"; result = sforce.connection.update([shp]); if (result[0].getBoolean("success")) { log("Shipment with id " + shp.id + " updated"); } else { log("failed to update shipment" + shp.id]); } } function updateShp() { try { var shp= new sforce.SObject("Shipment__c"); shp.Id = "{!Shipment__c.Id}"; shp.Status__c = "In transit"; var result = sforce.connection.update([shp]); if (result[0].getBoolean("success") == false ) { alert(result[0].errors.message); return; } window.top.location.href=window.top.location.href; } catch (e) { alert(e); } updateShp(); } </script> <apex:form > <apex:outputLink value="/{!Shipment__c.id}" onclick="updateShp()" rendered="{!$Profile.Name = 'System Administrator'}">updateShp()</apex:outputLink> <apex:outputLink value="/{!Shipment__c.id}" onclick="departShp()" rendered="{!$Profile.Name = 'System Administrator'}">departShp()</apex:outputLink> </apex:form> <apex:sectionHeader title="Shipment" subtitle="{!Shipment__c.name}" help="https://thetiowiki.com/index.php?title=Shipment#Managing_Shipments"/> <apex:form id="detailPageBlock"> <apex:pageBlock title="Shipment Detail"> <apex:panelGrid columns="4" rules="rows" styleClass="panelGridClass" title="myPanelGrid" width="100%" > <apex:outputText value="Status"/> <apex:outputField value="{!Shipment__c.Status__c}"/> </apex:panelGrid> </apex:pageBlock> </apex:form> </apex:page>

 Neither updateShp() or departShp() work...

I click the ouput link and it simply refreshes the page (as per the "value" param in the link... I can't figure out how not to have those)

 

CaptainObviousCaptainObvious

Instead of an outputlink (which may be the source of your problem), how about this:

 

<apex:outputPanel rendered="{!$Profile.Name = 'System Administrator'}"> <span onclick="departShp('{!Shipment__c.id}')">departShp()</span> </apex:outputPanel>

 

And then, in your javascript...

 

function departShp(sid){ var shp = new sforce.SObject("Shipment__c"); shp.id = sid; shp.Status__c = "In transit"; result = sforce.connection.update([shp]); if (result[0].getBoolean("success")) { log("Shipment with id " + shp.id + " updated"); } else { log("failed to update shipment" + shp.id]); } }

 

Edit: You can also give it the appearance of a link with some inline styling:

 

 

<apex:outputPanel rendered="{!$Profile.Name = 'System Administrator'}"> <span onclick="departShp('{!contact.Name}')"

style="text-decoration:underline;cursor:pointer;">departShp()</span> </apex:outputPanel>

 

Message Edited by CaptainObvious on 03-26-2010 12:08 PM
This was selected as the best answer
SteveBowerSteveBower

The code below works (At least in the non-error cases.)  (I modified things to work on a Contacts Phone number instead of your shipment object, but it should be the same.)

 

It's a little ugly because the rendering of the page puts your outputLink at the top left of the pagewhere it looks out of place, but that's not stopping it from working.  When it's completed it returns to the Contact's Detail page.

 

You launch it with a Button on the Contact page that executes a VisualForce page.

 

Hope it helps, Steve.

 

 

<apex:page standardController="Contact"> <script src="../../soap/ajax/18.0/connection.js" type="text/javascript"></script> <apex:form > <apex:outputLink value="/{!Contact.id}" onclick="updateShp();">updateShp()</apex:outputLink> </apex:form> <apex:sectionHeader title="Contact" subtitle="{!Contact.name}"/> <apex:form id="detailPageBlock"> <apex:pageBlock title="Contact Detail"> <apex:panelGrid columns="4" title="myPanelGrid" width="100%" > <apex:outputText value="Contact Phone"/> <apex:outputField value="{!Contact.Phone}"/> </apex:panelGrid> </apex:pageBlock> </apex:form> <script> /* This code allows the javascript to access the API and push data into the Org.*/ sforce.connection.sessionId = "{!$Api.Session_ID}"; function updateShp( ) { try { var shp= new sforce.SObject("Contact"); shp.Id = "{!Contact.Id}"; shp.Phone = "123-4567"; var result = sforce.connection.update([shp]); if (result[0].getBoolean("success") == false ) { alert(result[0].errors.message); } } catch (e) { alert(e); } } </script> </apex:page>

 

 

 

 

JNicJNic
Thanks guys, both of these last ones worked!
sruthiforcesruthiforce

Hi im adimistator  using pagination in my page everything working fine but search not at all working  it throus  Exception: invalid ID field: null,

 

public PageReference search(){
        
    String query = 'select Id, Name, stagename,CloseDate,ownerid, Account.name,Account.BillingCountry from Opportunity where Isclosed=false and Sold_To_Partner__c = \''+accId+'\' and Id not in (select OpportunityId from OpportunityTeamMember where userid=\''+userids+'\' ) ';
    
        if(acc != null && acc.length() >= 3)
        {
            String accName = '%'+acc+'%';
            query += ' and account.name like \''+accName+'\'';
        }
        if(stage != null && !stage.equals(''))
        {
            query += ' and stagename = \''+stage+'\'';
        }
        if(opp != null && opp.length() >= 3)
        {
            String oppName = '%'+opp+'%';
            query += ' and name like \''+oppName+'\'';
        }
     
        query += ' LIMIT '+queryLimit+' OFFSET '+offset;
        oppList = Database.Query(query); //System.QueryException: invalid ID field: null

Error is in expression '{!search}' in component <apex:page> in page partnersso_opportunitylist


    
        //if(oppList.size() > 0){           
            showList();
            getTotalPage();        
        //}
        return null;   
            
    }