Using the Salesforce JSON Generator for quick visualforce translations

Asychronous Javascript (Aj of Ajax)) on Salesforce is easy. Salesforce does a great job of making it simple to have a way on a visualforce page to have an apex class do some processing and return the result to the page without a full page refresh. This is great for some complex operations. There’s even a simple pattern for displaying a loading animation for when the async processing takes awhile.

However, if we want to do something relatively simple or frequent (e.g. onkeydown or onkeyup rather than onchange), the ~1-2 second round trip time becomes rather noticeable and burdensome. We want to see instant changes and reactions on the page, not wait for a round trip to occur. Since our data and the bulk of our business logic is sourced in Salesforce, we need a way to easily retrieve this data and interact with it from javascript without the round trip.

Enter the pattern for serializing an apex data structure into JSON, and interacting with it in javascript. Consider the following example and showcase.

The user would like to see a real-time translation based on data entered into an inputText field. If the user types in “demo” into the field, then in another field we would replace its contents with “replacement.” If anything other than “demo” is typed, we do not do a translation. (Note: there are easier ways to do this problem, but I’m trying to showcase this solution.)

See this apex class:

public class JSONGenController {
  public class JSONGenerator {
    public Map<String, String> translateMap = new Map<String, String>();
  }

  private JSONGenerator generator;
  public String generatedJSON {
    get {
      return JSON.serialize(generator);
    }
  }

  public JSONGenController() {
    generator = new JSONGenerator();
    generator.translateMap.put('demo', 'replacement');
  }
}

and this visual force page:

<apex:page controller="JSONGenController">
  <apex:form id="theform">
    <apex:pageBlock id="block">
      <apex:inputText onkeyUp="translateInput(this)" />
      <apex:inputText id="toReplace" disabled="true" />
      <script>
        var generatedJSON = {!generatedJSON};
        function translateInput(obj) {
          if (generatedJSON.translateMap[obj.value] != null) {
            document.getElementById("{!$Component.theform.block.toReplace}").value = generatedJSON.translateMap[obj.value];
          }
          else {
            document.getElementById("{!$Component.theform.block.toReplace}").value = '';
          }
        }
      </script>
    </apex:pageBlock>
  </apex:form>
</apex:page>

Here are the rendered fields, when typing the translateInput js method is called, and if it finds a match for translation, it will put the translated value into the second field.

Blank fields:
blank fields

Typing in the translated value:
translated

A non-translated value:
non-translated

Like I said, this can be solved much more simply, but this solution provides for a bit more added complexity, and the logic can be easily driven by Salesforce data from apex. Most importantly, this provides instant results, rather than the round-trip as required by an ajax actionFunction. There are a variety of use cases for this, I’d like to hear some more if you have them.

This entry was tagged , , , . Bookmark the permalink.