Showing posts with label save. Show all posts
Showing posts with label save. Show all posts

Wednesday, November 13, 2013

A Bug!

It's not often that I come across a real bug with Salesforce's apex or visualforce platform.  Most often there are limitations or shortcomings that you have to workaround.  Recently, I had to make an urgent change to a trigger and it's associated test class.  However, when I attempted to comment out a line in my test class, I got the following error in the editor when I tried to save:

java.lang.reflect.InvocationTargetException

When I attempted to make the same change in the developer console, I got another error:

 An unexpected error has occurred. 421011484-16071 (1420197083) for deploymentId=1drJ00000002FDxIAM If this persists, please contact customer support.


Fortunately, I was able to still deploy my code without the test class change but I opened a case anyway and after waiting a few days for a reply, was told that it was a known issue.  The instructions from developer support were:
  • Please clear Test results and try to save the code:
    • From Setup, click Develop | Apex Test Execution |View Test History | Clear test results. 

However, even before I did these actions, I tried to update the test class again and surprise!  no errors. So, something fishy is going on... Support wants to close the case but I'm inquiring for additional details.  Will keep you posted.


**Update Nov 13**

Salesforce has responded and indicated that it was a bug but has been fixed.  Details here: https://success.salesforce.com/issues_view?id=a1p30000000T17j

Friday, August 9, 2013

Auto save with TinyMCE and Salesforce

I'm on a project where our users have large numbers of long text areas and are often working on old-ish computers.  One common complaint was that they'd spend a good amount of time typing something only to find that they'd lost it when they clicked Save.  We explored some options with some features within HTML 5, like local storage, but settled on trying auto-save.  Auto save is a common feature in most online services like blogger or gmail, so this seemed like a good model to follow.  Additionally, it seemed less browser dependent, which is also good.

The system is composed of a Visualforce page using TinyMCE as the rich text editor.  TinyMCE has a (somewhat buggy) function that will tell you if an editor instance "is dirty".  We set a timer to check this attribute every few seconds.  If the attribute returns true, we can execute a controller method via javascript remoting.

Putting it all together:

A visual indicator (to show the user that the auto save ran):

<div id="saving" class="minitext" style="color:#666; font-style:italic; display: none">AutoSaving...</div>

The timer:
var $j = jQuery.noConflict();  
// First we tell this to run when the page is loaded
$j(document).ready(function()
{
  $j(function()
  {
    setInterval("auto_save('{!$Component.theform.thepageblock.thepbs.somefield}')",5000);
  });

});


The auto_save function referenced in the timer:
function auto_save(inputs)
{
  // First we check if any changes have been made to the editor window
  if(tinyMCE.getInstanceById(inputs).isDirty())
  {
    $j('#saving').show();
    var content = tinyMCE.get(inputs);
    var notDirty = tinyMCE.get(inputs);
    saveTestField('Some_Field__c', content.getContent());

    notDirty.isNotDirty = true;
   }
else
  {
    $j('#saving').hide();
    return false;
  }


The saveTestField function:
function saveField(fieldName, fieldValue) 
{
    Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.AutoSave.updateFieldValue}', recId, fieldName, fieldValue, 
        function(result, event){
            if (event.status) {
            } else if (event.type === 'exception') {
                console.log(event.message);
            }
        }, 
        {escape: true}
    );


The Apex method:
@RemoteAction
public static Boolean updateFieldValue(Id recordId, String fieldName, Object fieldValue)
{
String sObjectName = recordId.getSObjectType().getDescribe().getName();
String queryString = 'Select Id, ' + String.escapeSingleQuotes(fieldName) + ' From ' + String.escapeSingleQuotes(sObjectName) + ' Where Id = \'' + String.escapeSingleQuotes(recordId) + '\'';
Sobject record = Database.query(queryString);

record.put(fieldName, fieldValue);
update record;

return true;

}


Observations:

  • UI validations are completely ignored.  If you have a required field in your UI, the field will still commit, without error.
  • The auto save only commits the field passed to the controller.  No other field is saved.

Issues

  • One issue that I observed while assembling this was that the isDirty attribute wasn't always reliable.  It turns out that you have to tell TinyMCE to save at some point for the attribute to reset itself.  You can do it by adding this line: tinyMCE.get(inputs).save();
  • Another issue: this recipe works well for existing records (records with Id).  If you're inserting a new record, you'll need to modify accordingly.

Credits
This was assembled with some helpful tips and tricks from other folks sharing their solutions.  Thank you for sharing!
https://github.com/pbattisson/Visualforce-Autosave/
http://webnv.net/2008/02/10/autosaving-with-jquery-and-tinymce/