3

I have a lightning app, which is embedded inside a visualforce page.

It is a page that is a form. I have given a button "Save Draft" which allows users to save data.

Problem is, some users fill out some info and wait for a long time before clicking "Save Draft" button, and session timeout occurs ... and they lose everything they filled in.

Is there a way that it can be detected (via code) that a session timeout is about to happen and save the draft before that happens.

1
  • Thank you all for your responses. I am practically an illiterate when it comes to front end development, but all these responses have given me something to study and try it out myself. Thank you. And once i have the final solution, i will respond back Apr 15 '17 at 0:22
2

I think Santanu has a great suggestion but if you do not want every attempt being saved, and/or I think that this would renew their session (which seems like a pretty big "No No" for security) I would instead suggest trying to use a local solution like accessing the data via localStorage versus an Apex Controller. localStorage is quite secure and SFDC does a great job of preventing XSS so I would think that something simple that maybe loads the values of the fields into localStorage would be a great solution.

<apex:page>
  <apex:form id="form1">
    <apex:inputField id='field1' />
    <apex:inputField id='field2' />
    <apex:commandButton value="save" action="{!save}"/>
  </apex:form>
  <script>
    // Used to store your values
    var result = {}
    // just to help debounce saving everything into localstorage
    var timer
    // This will be placed on all the 
    function onChangeEvent () {
      if (timer) clearTimeout(timer)
      var key = this.event.target.id
      var value = this.event.target.value
      result[key] = value
      timer = setTimeout(function(){
        localStorage.setItem('autoSaved', result)
        clearTimeout(timer)
      }, 1000)
    }
    var ids = [
      '{!$Component.form1.field1}',
      '{!$Component.form1.field2}'
    ]
    function addAllSavedValues () {
      result = localStorage.getItem('autoSaved') || {}
      ids.map(function(id) {
        // If the value existed in local Storage proceed
        if (result && result[id]) {
          // get the field by the ID
          var field = document.getElementById(id)
          // change the value of the field using the previous ID loaded into storage
          field.value = result[id]
        }
        // Adds the change event listener to the field to make sure that you track all changes
        field.addEventListener('change', onChangeEvent)
      })
    }

    // Set a Timeout to make sure that the Dom is ready
    setTimeout(addAllSavedValues, 1000)
  </script>
</apex:page>

This should allow you to keep your records low and not renew sessions just because somebody forgets to leave a page while at the same time allow them to save the information that they were working on and make them happy.

1
  • I fully agree with the statements made in this post. However, the sample provided appears to be in Visualforce. Do not let this disuade you from using this approach. Access to localStorage is available in lightning even with LockerService. This will allow you to save what the user has entered on the client side and restore that even after a session timeout. Read more at developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
    – dsharrison
    Apr 14 '17 at 4:31
2

Sessions are a fickle thing. There's no reliable way to determine when a session will expire without extending the session, meaning the user will stay logged in perpetually. I'd say that the best solution is to use sessionStorage to temporarily save and restore data within the browser's cache (or localStorage if you want the data to potentially survive something like accidentally closing the browser).

Here's a simple demonstration that uses localStorage. You can close the app and later reload it to restore the values. This is not a pretty app, but it is functional.


.app

<aura:application >
    <aura:attribute name="textValue" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    <ui:inputText value="{!v.textValue}" change="{!c.change}" />
    <ui:button press="{!c.clear}" label="Clear Storage" />
</aura:application>

Controller.js

({
    init: function(component, event, helper) {
        if(localStorage.getItem("lightning.textValue") && confirm("Would you like to restore the previous session?")) {
            component.set("v.textValue", localStorage.getItem("lightning.textValue"));
        }
    },
    change: function(component, event, helper) {
        localStorage.setItem("lightning.textValue", component.get("v.textValue"));
    },
    clear: function(component, event, helper) {
        localStorage.removeItem("lightning.textValue");
    }
})

Other possible scenarios could include using setTimeout to periodically save a snapshot, or even offering to save the draft to the server after reloading/logging in again.

0

You can perform auto saving of page using actionPoller

Find an sample example of auto saving of form with 5 seconds interval.

<apex:page controller="autoSaveController">
  <apex:form id="form1">
    <apex:actionPoller action="{!save}" rerender="form1" interval="5"/>
    <apex:commandButton value="save" action="{!save}"/>
  </apex:form>
</apex:page>

** Controller: **

public class autoSaveController 
{
  public PageReference save()
  {
     System.debug('save is called');
     return null;
  }
}
1
  • 3
    I apologize, I misread the OP. This solution is problematic because the page will continually refresh, thus ensuring the session will never expire.
    – sfdcfox
    Apr 13 '17 at 22:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.