Visualforce Inline Editing – I’m In Love

I’m totally addicted to the new Visualforce inline editing feature. It all started with this post by Josh Birk at Developerforce. I liked it, but as a “standardstylesheets” specialist, I wanted a bit more.

Then I looked at the Visualforce apex:inlineEditSupport documentation, and I was hooked.

Okay, so you’re probably wondering why this is so neat. I’ll show you how to enable fields for inline editing, and then I’ll show you why the apex:inlineEditSupport tag is completely unnecessary!

Here’s a simple example. You’ll notice that inline edit support has only been given to the contact.phone field.

<apex:page standardController="Contact" standardstylesheets="true"
	showheader="true">
	<apex:form >
		<apex:pageBlock mode="maindetail">
			<apex:pageBlockButtons >
				<apex:commandButton action="{!edit}" id="editButton" value="Edit" />
				<apex:commandButton action="{!save}" id="saveButton" value="Save" />
				<apex:commandButton onclick="resetInlineEdit()" id="cancelButton"
					value="Cancel" />
			</apex:pageBlockButtons>
			<apex:pageBlockSection >
				<apex:outputField value="{!contact.lastname}"/>
				<apex:outputField value="{!contact.accountId}" />
				<apex:outputField value="{!contact.phone}">
					<apex:inlineEditSupport showOnEdit="saveButton, cancelButton"
						hideOnEdit="editButton" event="ondblclick"
						resetFunction="resetInlineEdit" />
					</apex:outputfield>
			</apex:pageBlockSection>
		</apex:pageBlock>
	</apex:form>
</apex:page>
  1. resetInlineEdit() is referenced in the code, but the actual Javascript isn’t shown anywhere. PLEASE don’t be fooled by the bad code in the documentation: It works perfectly for that “undo” arrow by the inline edit field, but it doesn’t work on the cancel button.
  2. changedStyleClass is optional. Omitting it uses the standard style we’re all used to. And referring to a style that isn’t included anywhere just defaults to the system default.
  3. PageBlock here has no “mode” attribute. This means that we can specify only the fields we want for inline editing. However, if we place the inlineEditSupport tag as an immediate child of the PageBlock, it will apply to every field in that PageBlock (or dataList, dataTable, form, outputField, pageBlockSection, pageBlockTable, repeat).

Here’s my next step: Find a way to hide the Cancel button on pageload, but show it when any field is inlineEdited. Javascript gurus have a solution?

(An aside: In Josh’s code sample, he uses a standard method called “quicksave.” It’s not in the Apex or Visualforce documentation, but we find here that “The quickSave() method on the standard controller performs the same database operation as the save() method but returns the user to the same page rather than navigating away.”)

Want to know why this is unnecessary?

It is undocumented, but is shown in the code sample in the Visualforce guide: use
<apex:PageBlock mode="inlineEdit" >

to set every field to inlineEdit and use default styles, etc. I don’t know how it will affect buttons shown/hidden, but give it a shot.

The attributes for inlineEditSupport are pretty simple:

Attribute Name My Description
changedStyleClass can refer to a style class included in the page or in a referenced CSS sheet in Static Resources
disabled disables inline editing. This is really cool because you can put any logic in here. (On a separate note, inline editing respects field-level security, so if the user can’t edit a field, this attribute is basically set to TRUE.
This is also a good tag because it lets you avoid using the rendered attribute with a plain outputtext/outputfield component to do your “can the user edit this” logic.
event What makes the field switch from output to input. This is the usual list of Javascript events. (ondblclick, onmouseover, onmousedown, etc)
hideOnEdit This one is cool. Give every commandButton on the page an id (because you do that anyway, right?) and then list the ones that should only be shown when this field is in input mode.
id Seriously, folks, always give your elements ids. Not only is it good practice for adding Javascript to your page, but it avoids that silly “j_40″ style id automatically generated… which shows when I view the source of your page, making you look bad.
rendered We all know how to use this. I admit: I can’t think of a reason to use this as a child of outputfield, but I can certainly think of reasons to use it when it’s a child of apex:repeat, as those don’t necessarily respect field-level security when used with custom controllers.
resetFunction This one is addressed below. It’s the Javascript function that resets the field, undoing all non-committed inline edits.
showOnEdit Buttons to show when the field is edited. See hideOnEdit.

What are your next steps? Planning to add this to your page layouts? Looks like anyone with cool tools to convert regular page layouts to Visualforce layouts is going to have a lot of work to do!

 

System Replacement For isTest Apex Method

February 23, 2011 by David Schach · 1 Comment
Filed under: Apex, Development, salesforce.com, Winter 11 

Sometimes we have to write code that executes differently if the Apex is being tested. For a great example, check out Scott Hemmeter's blog post on testing webservice callouts at http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/.

Scott's example works well, and he uses a Boolean isApexTest, running certain code if this is true or false. I used to do something similar.

The disadvantage is that one has to declare one more variable, assign a new value to it from the test code (or call a special method from the test code which, in my opinion, negatively impacts code readability), and (if you put your test code in a separate class) declare it as public. My Java professor would not like this, as he preferred to declare all variables private unless absolutely necessary. Sure, I could make a private Boolean and a getter, but now we're splitting hairs.

Salesforce has come to the rescue, though, with a test.isRunningTest() method. Basically, you can use this interchangeably with your isApexTest variable.

Here's a snippet of code (from Scott's blog post) with the old and new methods:

public static boolean isApexTest = false;
public String main(){
    // Build the http request
    // Invoke web service call
    String result = '';
    if (!isApexTest){
        // Make a real callout since we are not running a test
    } else {
        // A test is running
        result = FakeXMLReturnToSimulateResponse;
    }
    return result;
}
And now with the new method:
public String main(){
    // Build the http request
    // Invoke web service call
    String result = '';
    if (!Test.isRunningTest()){
        // Make a real callout since we are not running a test
    } else {
        // A test is running
        result = FakeXMLReturnToSimulateResponse;
    }
    return result;
}
Some among you may want to switch the two so that we don't put a negative method response in the if evaluator, and that's okay too.
 

New Opportunity Page Layout – With Highlights Panel!

Yesterday, I enabled the new Opportunity page layout in my Developer Spring ’10 Preview org, and it took a few steps, so I thought I’d share them with you.

Firstly, you’ll need to contact salesforce.com to get this feature enabled.

Then be patient. It takes a minute or two for the update to propagate. Clearly, something was churning in the Force.com platform background!

Now we’ll navigate NOT to the Setup | Customize | User Interface screen (where this should be enabled). Instead, we’ll go to the Opportunity Page Layout screen.

Follow the cool prompts. They make it so easy, a … well, you know what I mean.

Step 1: Enable the Highlights Panel

Step 1: Enable the Highlights Panel


Opportunity Layout Setup page

Opportunity Layout Setup


Step 2: Edit the Page Layout

Step 2: Edit the Page Layout


Choose Fields to Display

Choosing Fields to Display

Note: You can only show fields in the Highlights Panel if they are in the page layout. (I have a feeling this has to do with Professional Edition or printable layouts, but I’m just guessing.)

Once you’ve done this for each page layout, click on the big button.

Confirmation

Confirmation - You're (mostly) done!

At this point, each user can enable the bar. I have no idea why the admin can’t just force this on all users – or maybe I missed something – but it seems to be an opt-in feature.

Enable User Opt-In

Step 3: Enable User Opt-In

Here’s the link to enable the feature. Of course, you may wish to watch a video as well!

The link to enable this setting

The link to enable this setting

And here it is!

The new layout!

The new layout!

View from the bottom of the page

Return to top from the bottom of the page

It’s interesting that if you have this enabled, certain user interface settings (yes, at Setup | Customize | User Interface) cannot be changed:

When this is enabled, you cannot turn off two settings

When this is enabled, you cannot turn off two settings

Here’s my prediction: We will start to see two major mistakes during Salesforce demos:

  1. We will continue to see the link asking if we want more information on inline editing (after more than a year, it’s time to turn that off, people).
  2. At the top of the Opportunity detail page, we will see this link.

And I will continue to think less of all demonstrators who make these mistakes.

Happy Spring 2010!

 

Get Documents and Attachments out of Salesforce

As Content will be included in all Salesforce licenses (for completeness, I'll add 'to some degree') with the Spring '10 release, orgs will be faced with the daunting prospect of getting their documents and attachments out of Salesforce and into Content.

I had this problem when Content was first released and I was asked to be one of the first SysAds to use it. At the time, we used Solution 1 (below), but since then, other products have been released to help with this.

Why is it even an issue?

  • Surely we can download each file? Yes, but who wants to?
  • Can't we do a Data Export and then upload those to Content? Yes, but all the files are renamed with their 15-character Ids, making renaming them all-but-impossible.

salesforce.com and DreamFactory to the rescue!

Solution 1

Summary: Use a script to rename all exported files. A (wonderful!) salesforce.com employee, Nick Marcantonio, wrote a Perl script to perform the transformation. Here it is, in all its glory:
# Nick Marcantonio
# nmarcantonio at salesforce.com
# 08/07

$file = 'Attachment.csv';

open (F, $file) || die ("Could not open $file!");

$line = <F>; #read first line which is nothing but column headers
while ($line = <F>)
{
  ($id,$name) = split ',', $line;
  chomp($id);
  $id =~ s/"//g;
  chomp($name);
  $name =~ s/"//g;
  
  #print "$id : $namen";
  
  $result = rename($id, $name);
  #print "$resultn";
}

close (F);
The instructions:
If you've done a data export you've noticed that all attachments are placed in the Attachments subfolder and named with their salesforce ID, not the actual file name or extension. One must then consult the Attachment.csv file included in the data export to find the name associated with the ID and rename the file. Attached to this solution is a Perl script that will rename all of the exported attachments to their proper names. Please follow these steps to run this:

1. Perform a data export and unzip the resulting zip file
2. Launch the data loader and export from the Attachments table ONLY the Id and Name column. This file must be named Attachment.csv.
3. Install ActivePerl. This will allow perl scripts to be run on a Windows machine. ActivePerl is available here (http://www.activestate.com/activeperl).
4. Copy the Attachment.csv file and the attached AttachmentParser.pl file to the Attachments subdirectory of the data export.
5. Double-click on AttachmentParser.pl.

All of the files named with their salesforce IDs will be renamed with their proper names and file extensions.

(This solution will work for documents as well. Follow the same procedure and be sure to name the extract from the Documents table Attachment.csv) 

Note: This will not preserve folders, as far as I know. You may be able to recreate this by exporting the Folder table and doing some work on that, as the Document table does include a FolderId column.

A heartfelt thank-you to Nick Marcantonio for his help!

Solution 2

Install DreamFactory's FREE DreamTeam Document Management application from the AppExchange to drag-and-drop your Documents to your desktop.
This doesn't work with Attachments, though, so you may need to use another method for them.

Please let us know how it goes - good luck and enjoy Content!

 

Next Page »

  • Recent Posts

  • Subscribe

  • Post Categories