When Salesforce is life!

Author: Enrico Murru Page 15 of 20

[Salesforce] The Sobject Crusade: AccountFeed

Back to the Sobject Crusade list.

Source: AccountFeed

This represents a single feed item on the Account record detail page (chatter feed).

It tracks different kind of feeds:

ActivityEvent—indirectly generated event when a user or the API adds a Task associated with a feed-enabled parent record (excluding email tasks on cases). Also occurs when a user or the API adds or updates a Task or Event associated with a case record (excluding email and call logging).

For a recurring Task with CaseFeed disabled, one event is generated for the series only. For a recurring Task with CaseFeed enabled, events are generated for the series and each occurrence.

  • AdvancedTextPost: created when a user posts a group announcement
  • ApprovalPost: generated when a user submits an approval
  • CanvasPost: a post made by a canvas app posts on a feed
  • CollaborationGroupCreated: generated when a user creates a public group
  • ContentPost: a post with an attached file
  • CreatedRecordEvent: generated when a user creates a record from the publisher
  • DashboardComponentAlert: generated when a dashboard metric or gauge exceeds a user-defined threshold
  • DashboardComponentSnapshot: created when a user posts a dashboard snapshot on a feed
  • LinkPost: a post with an attached URL
  • PollPost: a poll posted on a feed
  • ProfileSkillPost: generated when a skill is added to a user’s Chatter profile
  • QuestionPost: generated when a user posts a question
  • ReplyPost: generated when Chatter Answers posts a reply
  • RypplePost: generated when a user creates a Thanks badge in Work.com
  • TextPost: a direct text entry on a feed
  • TrackedChange: a change or group of changes to a tracked field
  • UserStatus: automatically generated when a user adds a post. Deprecated

To enable chatter feed tracking, go to Setup > Chatter > Feed Tracking and select the Account object and the fields you want to track.

Let’s take this account:

We have an AccountFeed of type TrackedChange and another one of type TextPost.

By querying for AccountFeed:

Note that the query includes the subquery (SELECT Id, FieldName, NewValue FROM FeedTrackedChanges), that returns, only for the TrackedChange record:

[
    {
        "Id":"0D624000009RROlCAO",
        "FieldName":"Account.Phone",
        "NewValue":"(650) 450-8812"
    },{
        "Id":"0D624000009RROmCAO",
        "FieldName":"Account.Fax",
        "NewValue":"(650) 450-8822"
    }
]

which tracks the fields change that originated the AccountFeed record.

N.B. Note we could have used the FeedItem object as well:

SELECT id, Type, Title, Body, Visibility, likecount, NetworkScope, (Select Id, FieldName, NewValue From FeedTrackedChanges) from Feeditem where ParentId='00124000003vaBu' 

[Salesforce] The Sobject Crusade

Design by Davide D’Annibale
In the past months I hit the severe wall of ignorance at least twice (with all my face), so I decided to start a personal crusade to cover all Salesforce Standard Objects, using the SOAP API Developer’s Guide and its list of Standard Objects.

To support this research, I start by reading the standard guide of an object and then making all actions to use that object in order to query for its records.

Sometimes an object is simple and well known that is quite useless to explore it (I said quite, because sometimes you find unknown features even with the objects you use daily); on the other hand some objects are cool because to use them you have to make configurations and write code and do stuff you haven’t never done, some other times you simply cannot do anything because the object is deprecated (and you are not that old to have a Developer ORG with that feature activated…my first API level is 15 BTW).

Moreover Salesforce Platform releases are not done yet, so I expect the number of objects will increse release after release.

As of Spring ’16 the number of objects is 546: this means that if I post an Object daily (weekends included), I’ll finish the research in the next 2 years….definitely too much!

That’s the reason I’ll try to post group of objects daily or so (ok, this is not a job, so maybe I shouldn’t promise something that I cannot keep, I still have a life…) instead of only one: on the blog sidebar you’ll always see a link of the last objects added.

If you want to partecipate in the crusade you are welcome!

The following list will be updated every time an object is added.

Legend:

[NA] – Un-activable (the feature is an old feature that cannot be activated on recent Dev Orgs)
[SR] – Salesforce.com Support Required (the feature needs Salesforce.com support activation)
[SRP] – Salesforce.com Support Required (Partially) (a part of the feature needs Salesforce.com support activation)

The Sobject Crusade: AcceptedEventRelation

Back to the Sobject Crusade list.

Source: AcceptedEventRelation

This object is available in API versions 29.0 and later.

The AcceptedEventRelation object the info about invitees who have accepted/refused the event.

How to get to it?

Go to an object standard layout where the Open Activities related list is available:

Click on New Event:

On the bottom click “Add Invitees” to add another User to the event.

Save the event.

The users you have invited will see the event in their calendar home page component, and by clicking on the Event subject they can accept/decline the invitation (by clicking the Accept Event or Decline Event buttons):

You will see the new status on the “Accepted” or “Declined” related list of the new event:

Now you have all you need to query this info:

Here is the SOQL to query the object:

SELECT eventId, relationid, type, response, RespondedDate FROM AcceptedEventRelation WHERE eventid=’00U24000002HD19′

[Salesforce / Streaming API / On Demand] Streaming API Notification Lightning Component

UPDATE: With Winter ’15 you no longer can use a lightning context Session ID to make REST API calls, this component no longer works. Read Session Privilege Levels.

Few weeks ago I asked the community this simple question:

The Salesforce Community is awesome and suddenly I had cool answers.

I concentrated on the first one:

I didn’t want to simply explain how Streaming APIs work and at the same time I wanted to do something fun and while I was walking with my dog I thought:

If you have any idea please send me awesome and challenging on demand articles topics!

For TL;DR buddies, here is the complete GitHub repository.

First of all here is the complete guide on Salesforce Streaming APIs.

As usual, this is a “quick and dirty” blog post, so don’t expect me to explain how the magic works.

Streaming API is a cool set of APIs which allow a client to be notified from the server when a specific event occurs.

It works like push notifications and uses long polling, in the sense that the client polls for updates from the server but the server doesn’t answer back till the next event (the connection remains idle), and when the client receives finally the response it usually makes another logn polling request, and so on.

This is what happens:

  1. client connects to the server (handshake)
  2. client subscribes to a specific server event (called channel)
  3. client listens to that event using long polling
  4. server sends event
  5. client consumes the event
  6. back to step 2

This technology is based on the Bayeux protocol and supports the dialect of the CometD 2.0 library (that implements the Bayeaux protocol).

Here is some characteristics of the flow:

  • Maximum “client to server” post body size is 32,768 bytes (e.g. connect or subscribe methods)
  • After an event is received, the client has to reconnect withing 40 seconds or the server closes the connection and a new handshake is necessary
  • In case of network problems, the client should attempt an automatic reconnection and a new subscription
  • Client can subscribe to the meta/handshake channel to receive informations about the connection

Remember that “Streaming API doesn’t guarantee durability and reliable delivery of notifications“: the server does’nt keep any state so it doens’t keep track of what’s delivered.

Here is a simple guide of using Streaming API with Workbech.

Enable a PushTopic

The PushTopic SObject is the mean for creating a Streaming API channel.

It hosts the query that originates the events sent to the subscribers.

These are the PushTopics we are going to use in our project:

PushTopic pushTopic1 = new PushTopic();
pushTopic1.Name = 'Opportunity_Won';
pushTopic1.Query = 'SELECT Id, Amount, Name FROM Opportunity Where StageName='Closed Won'';
pushTopic1.ApiVersion = 36.0;
pushTopic1.NotifyForOperationCreate = true;
pushTopic1.NotifyForOperationUpdate = true;
pushTopic1.NotifyForFields = 'Where';
insert pushTopic1;

pushTopic = new PushTopic2();
pushTopic2.Name = 'Lead_Converted';
pushTopic2.Query = 'SELECT Id, Name,Company FROM Lead Where IsConverted = true';
pushTopic2.ApiVersion = 36.0;
pushTopic2.NotifyForOperationCreate = true;
pushTopic2.NotifyForOperationUpdate = true;
pushTopic2.NotifyForFields = 'Where';
insert pushTopic2;

The drivers of a PushTopic are:

  • Query: this is the query used to create the data pool
  • Operations: when a record has to scanned by the engine, that is on create, update, delete, udelete
  • Fields: the record is scanned when fields change if they are in the WHERE clause, SELECT clause, REFERENCE (where+select) or ALL (all fields changes trigger the PushTopic, if the where clause still apply)

In our examples we are subscribing to the create/update operations on the leads and opportunity when leads are converted and opportunities are closed and won.

Users will receive a notification if FLS (field level security) allow them to view the topic fields, if they have read access to the record and to the PushTopic, visibility on the record based on the sharing rules.

Limitations

The following objects can be used in the PushTopi query:

  • All Custom Objects
  • Account
  • Campaign
  • Case
  • Contact
  • Lead
  • Opportunity
  • Task (with few limitations)

And here you are a list of unsupported SOQL statements.

There are also a number of limits all exposed in this page.

The Lightning playroom

The GitHub repository provides the following components:

  • svg: replicates the svg HTML5 element not currently supported in Lightning components (outputs icons and stuff)
  • UINotification: used to display a alert/toast notification when a specific event occurs. You can choose the style (info, error, success, warning), type (Toast, Alert) and the timer in seconds for auto-hiding, and ofcourse a title and a content detail
  • StreamingAPIEvent: event fired when a specific channel sends an event
  • ShowNotificationEvent: event fired whan a Streaming API event is consumed and allow for displaying a notification
  • StrApiListener: subscribes client to one or several topics (only one component is allowed per app); it fires a StreamingAPIEvent event.
  • StrApiTopicTemplate: (global component) listens to the StreamingAPIEvent event, grabs its content, compile its templates for title and content and fires a ShowNotificationEvent to the unique notification center
  • StrApiNotificationDock: (global component) hosts the StrApiListener component and handles ShowNotificationEvent events, dynamically creating UINotification component

The StrApiTestApp hosts the following components instances:

<aura:application>
    <!-- ... -->

    <c:StrApiNotificationDeck topics="Opportunity_Won,Lead_Converted"
        apiVersion="36" 
        notificationType="Alert" />
    
    <c:StrApiTopicTemplate topic="Lead_Converted"
                                 style="warning" 
                                 title="Created new lead called {{Name}}"
                                 content="Company: {{Company}}"/>
    <c:StrApiTopicTemplate topic="Opportunity_Won"
                                 style="success" 
                                 title="Won $ {{Amount}} !"
                                 content="Name is {{Name}}" />
</aura:application>

The StrApiNotificationDeck subscribes to the Opportunity_Won and Lead_Converted PushTopics using an Alert notification style.

For each channel defines a StrApiTopicTemplate template with a proper notification style, title and content.

Title and Amount attributes can be templates referring to the corresponding SObject’s fields wrapped by the double moustaches ({{Field__c}}).

Run to https://xxx.lightning.force.com/c/StrApiTestApp.app:

Lightning App Builder

The StrApiNotificationDeck and StrApiTopicTemplate components are defined as global and implements the flexipage:availableForAllPageTypes interface so they are good to go with the Lightning App Builder.

Compoments are invisible so you are not expected to see anything on the builder: as far as I know there is not way to create a sort of “default” view for the builder.

And this is your Salesforce 1 brand new app:

Custom Streaming Channels

The Force.com platform allows for custom channels.

They can be access by:

  • Creating a new StreamingChannel object
  • Sending a notification to the channel using the Streaming Channel REST API

To create a new StreamingChannel go to All Tabs > Streaming Channel and create a new streaming channel:

The Name must include the “/u/” prefix. You can specify whichever path you like (e.g. /u/users/alerts, /u/sales/notifications).

The components we have creates supports this new kind of channel:

<c:StrApiNotificationDeck topics="Opportunity_Won,Lead_Converted,/u/CustomChannel"
        apiVersion="36" 
        notificationType="Alert" 
        hideAfter="5"/>
    
    <!-- . . . -->

    <!-- custom streaming channel -->
    
    <c:StrApiTopicTemplate topic="/u/CustomChannel"
                                 style="info" 
                                 title="Message received"
                                 content="{{$}}" />
    

The template component supports the {{$}} value that stands for “the whole data”.

Indeed the StreamingChannel supports only strings.

To execute a REST push call follow the following instructions, or manually execute the following call:

Header:

"method":"POST",
    "uri":"https://[YOUR_DOMAIN].salesforce.com/services/data/v36.0/sobjects/StreamingChannel/[STREAMING_CHANNEL_ID]/push",
    "headers":[
        {
            "key":"Authorization",
            "value":"Bearer [YOUR_SESSION_ID]"
        },
        {
            "key":"Content-Type",
            "value":"application/json"
        }
    ]

Body:

{ 
      "pushEvents": [
          { 
              "payload": "Broadcast message!!!!",
              "userIds": [] 
          },{ 
              "payload": "This message is only for Enreeco!!!",
              "userIds": ["00524000000eaVt"] 
          } 
       ] 
    }

The messages are composed by:

  • payload: the message to be sent (plain text)
  • userIds: leave empty Array for broadcast message, of add one or more user Ids

May the Force.com be with you!

[Salesforce / Apex] Let’s play with Named Credentials and OAuth 2.0

Few days ago I was lurking in the Named Credentials configurations.

What are named credentials?

Here are the official docs.

They are essentially a way to store callout configurations such as:

  • Endpoint (only HTTPs endpoints are supported)
  • Callout certificate (if needed, from the local key store)
  • Authentication protocol (if needed)
  • Authentication settings

With named credentials you don’t need Remote Site Setting configuration anymore: add you credential and the job is done!

The Endpoint stores the callout URL but it could also store a part of the endpoint (e.g. only the domain or a specific piece of path, such as https://na1.salesforce.com/services/Soap/class/).

The Callout certificate grabs a certificate from the Certificate and Key Management setup page, allowing a more secure connection between hosts.

I’m going to focus on the Authentication protocol.

You can choose among the following values:

  • No Authentication
  • Password authentication
  • OAuth 2.0

And you can set the authentication globally (Identity type = Named principal) or per user (Identity Type = Per User): if you don’t need any authentication, just use the value “Identity Type = Anonymous”

The password authentication is pretty straightforward: it uses BASIC authentication (username/password BASE64 encoded sent in the request headers).

But what about OAuth2?

I wanted to test this option using all but the Salesforce platform: there are plenty of services that expose the OAuth 2.0 authentication, but I love Salesforce and that’s how I want to test things!

You need 2 orgs:

  • Remote ORG: this will be the provider of your OAuth 2.0 authentication, it hosts the remote service you want to access (and that you can only access with this ORG’s user)
  • Local ORG: this is the ORG where you want to invoke the remote service and where you are configuring the Named Credentials

Setup the Remote ORG

First let’s setup the remote service.

Create a new SOAP webservice:

global class EchoManager {
    webservice static String echo(String text){
        return 'ECHO FROM ORG '+UserInfo.getOrganizationId()+': '+text;
    } 
}

This service echoes the request text’s returning also the remote ORG ID.

Useful uh?

Go to Setup > Develop > Apex Classes search the EchoManager class and click the WSDL link next to the class name: this way you can download the WSDL file you are going to import in the Local ORG to call the service.

Make sure the remote user you’ll be using (with OAuth2) to consume the service from the Local ORG is enabled to access the Apex Class (from its Profile or assigning a Permission set: if this is an Administrator profile no need to check!).

Last step on this org is to setup a Connected App: this confgiuration will give access to the ORG from outside on behalf of an external application.

Go to Setup > Create > Apps, scroll to the Connected Apps section and click the New button:

Setup a name, a contact Email, a logo image (I choose Master Yoda).

Flag Enable OAuth Setting and set Callback URL to a fake value (e.g. callback://myapp): we’ll be configuring this field later (this hosts the callback url of the Local ORG).

Finally set the full and refresh_token scopes (the last one is necessary to allow for sending refresh token).

Onve you save it can take 5/10 minutes for the changes to be propagated.

This is pretty much what you see now (except for the Callback URL):

Let’s go back to the Local ORG.

Setup the Local ORG

First let’s import the remote service WSDL from Setup > Develop > Apex Classes and click the Generate From WSDL button.

Select the WSDL file just saved from the Remote ORG, use a namespace name (WSEchoManager in my case) and Salesforce will create the Apex Stub.

Let’s create a Visualforce page with a controller to test it:

public class EchoController {
    public String requestText{get;set;}
    public String responseText{get;set;}
    public void sendRequest(){
        this.responseText = null;
        try{
            WSEchoManager.EchoManager stub = new WSEchoManager.EchoManager();
            this.responseText = stub.echo(this.requestText);
        }catch(Exception e){
            this.responseText = 'Unexpected exception :'+e.getMessage();
        }
    }
}

<apex:page controller="EchoController" tabStyle="Account">
    <apex:sectionHeader title="Remote echoes" />
    <apex:form>
        <apex:pageBlock>
            <apex:pageBlockSection columns="2">
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Say something:</apex:outputLabel>
                    <apex:inputText value="{!requestText}" />
                </apex:pageBlockSectionItem>
                <apex:commandButton value="Send request" action="{!sendRequest}" />
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="1" 
                                   title="Server response" 
                                   rendered="{!NOT(ISBLANK(responseText))}">
                <apex:outputText value="{!responseText}" />
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Let’s try it:

As expected we haven’t still enabled anything.

Jump to Setup > Security Controls > Auth. Providers and click the New button and choose the Salesforce provider type:

This is the authentication provider will be using to initiate the OAuth 2 dance with the Remote ORG.

In the Consumer Key and Consumer Secret fields set the values from the Remote ORG connected app (called Consumer Key and Secret as well).

The Authorization Endpoint URL and Token Endpoint URL are setup with the https://login.salesforce.com/services/oauth/… values, but in this case I’ve used the Remote ORG custom domain (you can leave with the default values).

In the Default Scopes set the selected scopes in the Remote ORG connected app separated by a blank space (full refresh_token).

Now click “Save” and get the Callback URL you get in the Salesforce Configuration section:

Go back to the Remote ORG connected app and set the Callback URL with the one just copied.

We are about there, don’t worry!

Go back to your Local ORG and go to Setup > Security Controls > Named Credentials and click New.

Give a fantastic name to your named credential (you’ll be using it in your stub class), set the URL with the service url you find in the WSEchoManager class:

 . . .
    public class EchoManager {
        public String endpoint_x = 'https://eu6.salesforce.com/services/Soap/class/EchoManager';
        public Map<String,String> inputHttpHeaders_x;
    . . .

Set the Named Principal Identity Type and the OAuth 2.0 protocol; select the Authentication Provider just configured and flag the Start Authentication Flow on Save: this way, upon saving the named credential, you are requested to access to the remote provider.

Flag Allow Merge Fields in HTTP Body as well in order to put the OAuth token inside the request in a “non standard” way (we dont’ want to use the Authorication: Bearer XXX header).

Cheers: you have a working connection!

Finally we have to change the stub code to recall the named credential:

 . . .
    public class EchoManager {
        public String endpoint_x = 'callout:Echo_Service';
        . . .
        public String echo(String text) {
            WSEchoManager.echo_element request_x = new WSEchoManager.echo_element();
            request_x.text = text;
            this.SessionHeader = new SessionHeader_element();
            this.SessionHeader.sessionId = '{!$Credential.OAuthToken}';
        . . .

We are using the Echo_Service named credential in the endpoint_x member and adding the SessionHeader parameters in the SOAP request using the named credential merge field {!$Credential.OAuthToken}, which stores the token needed to authorize the call.

Thanks to the Allow Merge Fields in HTTP Body the engine replaces automagically this string with the session ID referenced by the merge field inside the SOAP request…and:

You can find the full code in the following Github repository.

[Salesforce / Trailhead] Presenting the “Navigate the Salesforce Advantage” trail aka What is Salesforce?

This is a technical blog (“Nerd @ work” say it all) and I usually post exclusively technical stuff.

But in the recent trailhead additions there is a special set of modules that basically answer the question “What is Salesforce and what’s the reason of its Success?”

This is the Navigate the Salesforce Advantage trail and it is meant for those who don’t know anything about the platform and for those who want to better understand the reason of the success.

I may say that if I could have read these modules when I first started making the first steps in the Salesforce platform, I would have understood in few minutes why Salesforce is that awesome…but you know, I discovered it by coding and coding and coding…

What I say before presenting the trail,

Here is a walkthrough of the key concepts of the trail.

Salesforce Success Model

Are you new to Salesforce? Not sure exactly what it is or how to use it? Don’t understand what makes Salesforce special? If you’ve answered “yes” to any of these questions, then you’re in the right place. No matter what brought you, we’re glad you’re here.

Salesforce is a platform of connected features that helps you to make your customers love you (I mean not actually you, but your company!)

How do Salesforce do it? It’s success is handled by the following 4 rules:

  • Customer success: “why can’t buying enterprise software be as easy as buying a book on Amazon.com? How can we make it easier for customers everywhere to achieve their goals?
  • Leadership: “Cloud is still the medium for everything we do. This means all our focus is on innovating the best apps and platform technologies for our customers. This is what we do, all day, everyday.
  • Innovation: “Our customers drive us to be more innovative. … Because what they can do with Salesforce is truly amazing.
  • Giving Back: Our 1-1-1 Model: “To us, the business of business is not business. The business of business is to improve the state of the world.

Salesforce Cloud Benefits

To answer to what Salesforce is and what it does truly depends on each customers’ definition of success. … So it’s up to us to be their Swiss Army knife and provide them with a neatly packaged range of tools to choose from. … The aim is for our customers to have the right mix of tools at the right time.

All the platform features help your customers to solve several issues in their business thus increasing their business with super powers:

There’s a Salesforce App Cloud for That“.

And yes, it is all in cloud, Software As A Service (SAAS)!

It means that we maintain the infrastructure and do all the heavy lifting so you can focus on what matters most to your business.

Salesforce Technology Basics

Understand the basics of the Force.com platform.

Security: “At Salesforce, trust is our #1 priority. Data is one of the most valuable assets that each one of our customers possesses.

Multitenancy: “every customer shares the same infrastructure and runs on the same platform. It’s that simple

Metadata driven architecture: “When we talk about metadata at Salesforce, we’re talking about our metadata-driven architecture that allows each customer to customize their own instance of Salesforce. … Salesforce separates our customers’ customizations into a special metadata layer, so we can update and improve our platform in the background without touching any of their data or customizations

Fast app development: “Building an app with Salesforce is different. There is no installation of hardware and software, and there are standard options for defining security and user access, creating reports, and making the app social and mobile. Metadata allows us to have all of this pre-built in a separate layer for our customers, so all they have to do is add any customizations they may want as icing on the cake. … Point-and-Click Configuration for all, Custom Code for developers

Salesfoce Ecosystem

“Our ecosystem was created to help customers get access to whatever they need, whenever they need it.”

It’s the power of the Community that makes the platform so powerfull.

How to keep in touch with all of us?

  • Dreamforce: this is a HUGE event where you’ll meet people from all over the world
  • Attend a local event: join a local User Group or Developer Group
  • Explore the AppExchange
  • Consult with an Implementation Partner

How huge the Community is?

We developed the online Salesforce Success Community as a place where business users, admins, partners, and employees can go to find answers, get synced up with their local user groups, help new customers get started, and get active in a community of enthusiastic and innovative people.

Meet Our MVPs
I’m one of them now, you can catch me and ask wathever you want, we are here to help!

The most incredible thing about our MVPs? Not a single one is an employee. They put in all this time and effort for the good of the Salesforce community, and we recognize them for their leadership, knowledge, and ongoing contributions. These individuals represent the spirit of the community and what it is all about!

[Salesforce / MVP] Yes guys, I’m a Salesforce MVP! And Thank you all!

Today I woke up and… BAAAMM!

I’ve been nominated a Salesforce MVP: read the announcement from the Salesforce MVP blog.

This is an honor and a motivation of pride for my carreer, and I know I have to thank the whole Force.com Community for this awesome achievement!

This post is just to say thank you all!

In the next days I’ll publish a new post to describe my trailhead to the MVP!

The next question is: am I the first Italian Salesforce MVP?

Update 2016-02-29

Yes I am!!

See you in the next posts!

[Salesforce / Visualforce] Handling Viewstate with Dynamic Visualforce components

I’ve written this post thanks to the help of my colleague Ivano Guerini who has found the solution to the problem I’m going to expose and written down the code you’ll see in this post.

This post is about correctly handling the viewstate when dealing with Dynamic Visualforce Components.

For those of you that have never worked with dynamic components, they are a way to create visualforce components using Apex.

For example the following piece of code returns a Page Block Section with 2 input fields on the Account record:

public Account record{get;set;}

public ApexPages.Component getDynamicComponent() {
    Component.Apex.PageBlockSection result = new Component.Apex.PageBlockSection();
    result.columns = 1;
    List sectionItems = new List();

    Component.Apex.InputField input = new Component.Apex.InputField();
    input.expressions.value = '{!record.Name}';
    result.childComponents.add(input);

    input = new Component.Apex.InputField();
    input.expressions.value = '{!record.Website}';
    result.childComponents.add(input);
}

The visualforce should be called as follows:

<apex:pageBlock>
    <apex:dynamicComponent componentValue="{!dynamicComponent}" />
</apex:pageBlock>

The page prints out a page block with a page block section with 2 input fields for the Name and Website Account’s fields.

The following code has been packed up in this Github repository for further testing and improvements.

If you wanna know more about viewstate this article is a good starting point.

Generally speaking, the viewstate is an input hidden field inside your Visualforce forms that contains all page data and that is used to post your form back to the server and forth to the page.

Too many informations, are you still there?

The problem comes when you try to use dynamic components (that can vary between post backs) and the Visualforce block your post back because of (for instance) required fields: in this specific case the dynamic components does not maintain the viewstate because the postback is blocked just before arriving on the server, so the components are created again and their status is lost.

You can test this behavior by calling the /apex/DynamicViewStateExample?id=[ACCOUNT_ID]&skip=1 (the skip parameters calls the page without the fix shown at the end of this post):

To fix this problem we need to replicate the viewstate component to re-apply the values to the different input fields after the postback has been done.

In your page we have added an apex:inputHidden component called viewstate:

<apex:dynamicComponent componentValue="{!DynamicComponent}" invokeAfterAction="true" />
 <apex:inputHidden value="{!viewState}" id="viewState" />

The trick is to use Javascript to serialize/deserialize the view states.

We use the Serialize jQuery plugin to serialize form data but we had to write our own deserialize method (see the jQuery_Deserialize static resource for more details).

This part of the code is called when there is a post back:

var closestForm = jQuery('[id$="{!$Component.viewState}"]').closest("form");
    closestForm.on("submit", function(event) {
        //serialize esch component except the "viewState" component to avoid recursion
        jQuery('[id$="{!$Component.viewState}"]').val(jQuery(this).find(':not([id$=viewState])').serialize());
    });

And this part is the code that actually deserializes the “custom” viewstate and put it in the form fields:

if(closestForm.find('[id$=viewState]').val()) {
        closestForm.deserialize(jQuery('[id$="{!$Component.viewState}"]').val());
    }

This few lines of Javascript actually to the magic!

For more details on the implementation, have a look at the DynamicViewStateExmaple page and the DynamicViewStateCmp component.

Page 15 of 20

Powered by WordPress & Theme by Anders Norén