Hey @Benioff, can you do something about this? Maybe next year, a little more dream and a little less force. pic.twitter.com/fqqrHJB7g4
— dick costolo (@dickc) November 20, 2013
Wednesday, November 20, 2013
Traffic Nightmare @ Dreamforce
This is incredible..last year, the SF Giants were in the playoff hunt so downtown was already jamming. I can't even imagine trying to drive anywhere with over 140k registered attendees this year:
Monday, November 18, 2013
Drink the Kool Aid, It's DreamForce Season Again!
Salesforce1 appears to be the big announcement this year. I just watched this video that Salesforce published and while the music and voice over are great, I don't understand a thing about what is being announced. If you can make sense of this video, please share in the comments.
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:
When I attempted to make the same change in the developer console, I got another error:
**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
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, November 8, 2013
Workflow and User Permissions
Q: Do workflow rules run as the user or do they run as the system? For example, if you had a sales team associate update an opportunity and there was a workflow that fired on any opportunity edit, would the workflow update a field that the user did not have profile (or permission set) permission to update?
Q: If the workflow action reassigned ownership to another user, would it execute the ownership change despite the user's system permission of Transfer Records as false?
Q: If the workflow action changed the record type to a value, would it change the record type if the user's profile did not have access to the specific record type value?
***
My initial reaction was that workflow would run as the logged in user and would obey the user's profile and permission sets. However upon testing, what I found was that workflow runs as the system and does not honor the user's profile or permission. So, for the 3 questions above:
Q: If the workflow action reassigned ownership to another user, would it execute the ownership change despite the user's system permission of Transfer Records as false?
Q: If the workflow action changed the record type to a value, would it change the record type if the user's profile did not have access to the specific record type value?
***
My initial reaction was that workflow would run as the logged in user and would obey the user's profile and permission sets. However upon testing, what I found was that workflow runs as the system and does not honor the user's profile or permission. So, for the 3 questions above:
- Workflows run as the system and would update a field that the user did not have profile/permission set access to update
- Workflows will execute ownership changes on behalf of users who do not have permission to directly change the ownership
- Workflows will change record types in spite of profile-specified record type access.
Wednesday, October 30, 2013
JQuery Tablesorter, Meet PageBlockTable
I am definitely late to the jquery party. In the last year or so, I've been able to harness jquery to make pages more usable and functional and just finished a poc for another beautiful jquery solution for a recurring visualforce requirement: sortable tables.
A colleague and I were doing a peer review on a visualforce page he had built. The page had a sortable pageblocktable, which he had enabled with a custom compare function he had built in his controller. Now, I've seen all kinds of ways of doing sorting in the controller and have done some suboptimal server-side sorting, but I never really thought about trying to keep it client-side. I figured there'd be a way with javascript but I just didn't have it in me to try to code it up. So, I poked around the google and sure enough, there's a jquery plugin already built to do it. And, sure enough, another Salesforce developer, shared her solution using the tablesorter plugin years ago.
So, a few years late to the party :)
Anyway, I wanted to share my variation since I was able to get the tablesorter to work w/ the standard apex component pageblocktable. Again, with jquery, the solution is basically the following:
1. Import your library as a static resource
2. Reference your resource in your vf page
3. Bind your jquery function and your component
So, applying the parts to my poc, I have a page that looks like this:
*******
<apex:page standardController="Opportunity" tabStyle="Opportunity" extensions="myext" id="thepage">
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/>
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"/>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
<apex:includeScript value="{!URLFOR($Resource.tablesorter, 'jquery.tablesorter.min.js')}"/>
<script type="text/javascript">
$j = jQuery.noConflict();
$j(document).ready(function () {
$j("[id$=theaddrs]").tablesorter();
});
//some other unrelated js
</script>
<!-- some other visualforce stuff then the heart of the proof of concept: -->
<apex:pageBlock id="theaddrsblock">
<apex:pageBlockTable value="{!Addrs}" var="a" id="theaddrs" styleClass="tablesorter" headerClass="header">
<apex:column>
<apex:facet name="header">
<apex:outputText styleClass="header" value="{!$ObjectType.Address__c.Fields.Street__c.Label}" />
</apex:facet>
<apex:outputText value="{!a.Street__c}" />
</apex:column>
<!-- the other columns, closing tags, and that's it -->
******
There is nothing to share about the controller because the sorting is being done w/out a callback to Salesforce.
The sections highlighted in yellow show how little is needed to modify your standard pageblocktable into a sortable table. Not much, right?
I suggest looking at the documentation or online discussions about optional parameters that can be specified in the tablesorter library but if you just have a few fields in a table that you need to sort, the tool will do a great job of figuring out the data magically. It's really awesome.
Now, this is only a proof of concept and so there is at least one issue resolve: the icons to indicate sort direction are displaying on top of the column labels. Should be able to modify the css to offset the icons. Worst case, we just remove the styleClass attribute on the outputtext of the column facet. Anyway, if you don't have to send it back to the controller for some logic or because the dataset is too large, just use the plugin to sort!
A colleague and I were doing a peer review on a visualforce page he had built. The page had a sortable pageblocktable, which he had enabled with a custom compare function he had built in his controller. Now, I've seen all kinds of ways of doing sorting in the controller and have done some suboptimal server-side sorting, but I never really thought about trying to keep it client-side. I figured there'd be a way with javascript but I just didn't have it in me to try to code it up. So, I poked around the google and sure enough, there's a jquery plugin already built to do it. And, sure enough, another Salesforce developer, shared her solution using the tablesorter plugin years ago.
So, a few years late to the party :)
Anyway, I wanted to share my variation since I was able to get the tablesorter to work w/ the standard apex component pageblocktable. Again, with jquery, the solution is basically the following:
1. Import your library as a static resource
2. Reference your resource in your vf page
3. Bind your jquery function and your component
So, applying the parts to my poc, I have a page that looks like this:
*******
<apex:page standardController="Opportunity" tabStyle="Opportunity" extensions="myext" id="thepage">
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/>
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"/>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
<apex:includeScript value="{!URLFOR($Resource.tablesorter, 'jquery.tablesorter.min.js')}"/>
<script type="text/javascript">
$j = jQuery.noConflict();
$j(document).ready(function () {
$j("[id$=theaddrs]").tablesorter();
});
//some other unrelated js
</script>
<!-- some other visualforce stuff then the heart of the proof of concept: -->
<apex:pageBlock id="theaddrsblock">
<apex:pageBlockTable value="{!Addrs}" var="a" id="theaddrs" styleClass="tablesorter" headerClass="header">
<apex:column>
<apex:facet name="header">
<apex:outputText styleClass="header" value="{!$ObjectType.Address__c.Fields.Street__c.Label}" />
</apex:facet>
<apex:outputText value="{!a.Street__c}" />
</apex:column>
<!-- the other columns, closing tags, and that's it -->
******
There is nothing to share about the controller because the sorting is being done w/out a callback to Salesforce.
The sections highlighted in yellow show how little is needed to modify your standard pageblocktable into a sortable table. Not much, right?
I suggest looking at the documentation or online discussions about optional parameters that can be specified in the tablesorter library but if you just have a few fields in a table that you need to sort, the tool will do a great job of figuring out the data magically. It's really awesome.
Now, this is only a proof of concept and so there is at least one issue resolve: the icons to indicate sort direction are displaying on top of the column labels. Should be able to modify the css to offset the icons. Worst case, we just remove the styleClass attribute on the outputtext of the column facet. Anyway, if you don't have to send it back to the controller for some logic or because the dataset is too large, just use the plugin to sort!
Thursday, October 24, 2013
Custom Button to Run Your Entry Criteria before Approval Submission
A sorely lacking feature with Salesforce approvals is the entry criteria rejection message. If your record does not meet the entry criteria for a given approval process, you get a very generic
Unable to Submit for Approval
This record does not meet the entry criteria or initial submitters of any active approval processes. Please contact your administrator for assistance.
with no indication of what is missing! Users hate this. I mean, HATE this. They did not configure the approval process and so they've got no idea why they can't submit for an approval. If the organization is large enough, the sales ops and/or IT help desk gets involved. This to me is total lunacy and I see it everywhere. Imagine the productivity you could restore if you provided your users with some meaningful information. There is an idea you can vote up, if you agree.
There are some options to work around this limitation in the product. One that I've been playing with is the idea of moving the entry criteria rules into one or many validation rules that only run when a field is set. For example, you could have a Validated__c flag and create "entry criteria" validation rules to only allow it be set if your entry criteria are met. The flag could then be used by the approval process entry criteria and moves the logic back to the object where it can be surfaced. Depending on your business, you could use workflows/triggers to uncheck the flag, should something change prior to approval submission.
It was pretty easy to move the entry criteria into validation rules but where I struggled was getting a button to set the field for me and still display the validation rule errors on the standard layout. I was thinking that a "Validate" button would be more intuitive than setting the flag manually, so here's what I tried:
With options 1 and 2 the javascript is only able to surface the errors with an alert. If your rules are simple, this is probably viable and acceptable for your users. However, if you have 10 fields that are required for an approval process, your users are probably not going to write down each of the fields they need, then dismiss the alert, then fix the fields and submit.
With option 3, I was looking around to see if there were any non-visualforce options when I came across this article. The idea was simple: use a custom button to invoke the edit mode for the record and prepopulate the Validate__c flag. Additionally, if you add Save=1 to your url, Salesforce could automatically save the record! It only took a few minutes to configure and everything worked beautifully except the auto-save. Apparently, Salesforce has disabled the Save parameter, so for now, our users have to click the Validate button, then Save. Not bad.
The bottom line is that there are options to improve the usability of the entry criteria in your approval process. You do not have to live with the generic error and you can certainly improve the productivity of your team by moving some of the logic into validation rules.
Unable to Submit for Approval
This record does not meet the entry criteria or initial submitters of any active approval processes. Please contact your administrator for assistance.
with no indication of what is missing! Users hate this. I mean, HATE this. They did not configure the approval process and so they've got no idea why they can't submit for an approval. If the organization is large enough, the sales ops and/or IT help desk gets involved. This to me is total lunacy and I see it everywhere. Imagine the productivity you could restore if you provided your users with some meaningful information. There is an idea you can vote up, if you agree.
There are some options to work around this limitation in the product. One that I've been playing with is the idea of moving the entry criteria rules into one or many validation rules that only run when a field is set. For example, you could have a Validated__c flag and create "entry criteria" validation rules to only allow it be set if your entry criteria are met. The flag could then be used by the approval process entry criteria and moves the logic back to the object where it can be surfaced. Depending on your business, you could use workflows/triggers to uncheck the flag, should something change prior to approval submission.
It was pretty easy to move the entry criteria into validation rules but where I struggled was getting a button to set the field for me and still display the validation rule errors on the standard layout. I was thinking that a "Validate" button would be more intuitive than setting the flag manually, so here's what I tried:
- Button click -> javascript to set field and save
- validation rule errors only captured in js but raised through an alert box
- Button click -> apex class to set field and save
- validation rule errors only captured in js, again, raised in alert box
- Button click -> url params to set field and auto-save(?!)
- almost there!
With options 1 and 2 the javascript is only able to surface the errors with an alert. If your rules are simple, this is probably viable and acceptable for your users. However, if you have 10 fields that are required for an approval process, your users are probably not going to write down each of the fields they need, then dismiss the alert, then fix the fields and submit.
With option 3, I was looking around to see if there were any non-visualforce options when I came across this article. The idea was simple: use a custom button to invoke the edit mode for the record and prepopulate the Validate__c flag. Additionally, if you add Save=1 to your url, Salesforce could automatically save the record! It only took a few minutes to configure and everything worked beautifully except the auto-save. Apparently, Salesforce has disabled the Save parameter, so for now, our users have to click the Validate button, then Save. Not bad.
The bottom line is that there are options to improve the usability of the entry criteria in your approval process. You do not have to live with the generic error and you can certainly improve the productivity of your team by moving some of the logic into validation rules.
Friday, October 18, 2013
Draggable and Resizable Modal Popup
One common visualforce solution that I've built for several clients is a modal popup. At it's core, it is nothing but a hidden outputpanel that is dynamically rendered. With some styling, you can display the panel "above" your current page, with the current page grayed out. There are hundreds of blog posts out there covering how to do this: here's one, another, yet another.
These blog posts are incredibly helpful and have inspired me to pass it forward and share the incremental bits that I can. One thing that I've wanted to do that I just got working in my sandbox was to make these modal popups draggable and/or resizable. As I've come to learn, jquery makes this ridiculously easy.
If you look at the source code for the draggable example on jquery's site, you'll see that it's 3 parts:
1. A reference to the jquery libraries. You should probably use static resources, but if you're just testing it out, something like this needs to be on your page:
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/>
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"/>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
These blog posts are incredibly helpful and have inspired me to pass it forward and share the incremental bits that I can. One thing that I've wanted to do that I just got working in my sandbox was to make these modal popups draggable and/or resizable. As I've come to learn, jquery makes this ridiculously easy.
If you look at the source code for the draggable example on jquery's site, you'll see that it's 3 parts:
- The references to the jquery library
- The jquery function
- The div that you want to make draggable
1. A reference to the jquery libraries. You should probably use static resources, but if you're just testing it out, something like this needs to be on your page:
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/>
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"/>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
2. Add the jquery script and don't forget the noConflict() requirement. In my example, I have a div called "pop" that I want to make draggable and resizable.
<script type="text/javascript">
$j = jQuery.noConflict();
$j(function() {
$j( "[id$='pop']" ).draggable().resizable();
});
</script>
3. The div/outputpanel becomes something like this:
<apex:outputPanel id="popupBackground" styleClass="popupBackground" layout="block" rendered="{!displayPopUp}"/>
<apex:outputPanel id="custPopup" layout="block" rendered="{!displayPopUp}" >
<div id="pop" Class="custPopup">
<!-- your form/pageblock/fields/tables go here-->
<apex:outputPanel id="custPopup" layout="block" rendered="{!displayPopUp}" >
<div id="pop" Class="custPopup">
<!-- your form/pageblock/fields/tables go here-->
Part 3 depends on your styling but it should be pretty easy to apply to your modal popup. If all goes well you should be able to move your panel around and resize it. Enjoy!
Labels:
div,
draggable,
jquery,
modal,
popup,
resizable,
salesforce,
sfdc,
visualforce
Subscribe to:
Posts (Atom)