About Me

My photo
Dhaka, Dhaka, Bangladesh
✔4x Salesforce Certified ✔Web Application Developer ✔Database Developer with DWH/ETL/BI • Successful solution engineer and developer with 16+ years of experience multiple technology and in different countries. Proficient in implementing business requirements into the technical solution. Experience handling all phases of the project lifecycle from discovery through to deployment. Worked as technical lead for a team of junior developers to make sure code stayed in line with requirements and standard best practices. Skilled at integrating disparate systems with Salesforce.Experience implementing Salesforce Community Cloud at two previous companies.
Showing posts with label My Learning-Iron Speed Designer. Show all posts
Showing posts with label My Learning-Iron Speed Designer. Show all posts

Saturday, September 4, 2010

Creating a Custom Large List Selector

Creating a Large List Selector

Solution Approach
In some applications, end users may have to choose a value from a list of thousands or perhaps millions of values.  These values cannot be realistically displayed in a dropdown list or a listbox on a web page.  When the number of values exceeds 500, Iron Speed Designer automatically creates a default Large List Selector.  The number of items before a large list selector is displayed can be changed by modifying the MaxGeneratedItems pass-through attribute property.  However, the default large list selector may not be ideal in all situations because you may want to display additional columns, or provide different searching and filtering capabilities than provided by the default large list selector.  This is fairly easy to accomplish in Iron Speed Designer.  You can create a custom Show Table page and use this as a custom large list selector by making slight modifications to the layout.
This example shows how to create a “Customer Selector” page that can be displayed in a popup window, and that contains links that populate a text box in the opening page when clicked.  This example is part of the AcmeOMS sample application included with Iron Speed Designer.
To create a custom large list selector, modify the page to display a Lookup link.  This link will open the large list selector and pass the associated textbox field as a “target” to receive the selected value.  The large list selector page is a standard Show Table page modified to display a Select link.  When the user clicks on the Select link, a small Javascript function sets the selected value in the target textbox.  The following step-by-step instructions walk through each modification.
The Add Order page below was modified to display a Text Box for the Customer field followed by a Lookup hyperlink.  The Lookup hyperlink will allow the end user to search and select a customer from a popup window.

Procedure
Step 1:  Select the page in Iron Speed Designer’s Application Explorer where you would like to display the Lookup link, and select the Design  tab, e.g.:
…\ Sample Applications\AcmeOMS\Orders\AddOrdersPage.html
Step 2:  Change the CustomerID field on the page to a textbox from a dropdown list.  Double click the field to display the Page Properties dialog and change the Display Style on the Display tab to Textbox.
Step 3:  Switch to the HTML tab and add the following client script code inside the page’s layout.  This script can be added right below the line containing the link to the style sheet.  Change the URL if appropriate.
The above Javascript defines a function called OpenCustomerSelector that takes a parameter called “target”.  The function opens a browser window for a URL passing the “target” URL parameter.  The “target” URL parameter is the ClientID of the textbox that will receive the selected value.  In the AcmeOMS example, this would be the CustomerID textbox displayed on the Add Orders page that will receive the selected value.

Step 4:  Add the following HTML/DHTML inside the page’s layout immediately after the CustomerID textbox to display a Lookup hyperlink.  The following code will call the OpenCustomerSelector Javascript function defined above with a ClientID of the CustomerID textbox field.  The ClientID is the Microsoft .NET Framework ID of the CustomerID textbox.
C#:
Visual Basic .NET:
Note that C# pages refer to the page class as “this” and Visual Basic .NET refers to them as “Me”.  Also note that C# is case sensitive, so ClientID must be specified with ID in upper case.
If your CustomerID textbox is inside a table, then you need to use an alternate way to retrieve the Client Id since there are multiple rows on the page containing the CustomerId field.  To find the unique CustomerId for the row which was clicked, use Container.FindControl("CustomerId").ClientId as follows:
C#:
Visual Basic .NET:
Step 5:  Create a new show table page that will be displayed when the end user clicks the Lookup hyperlink.  The easiest way to create this page is to select File, New Page menu and select the Empty Page template since no header, footer or menu is required on the popup window. 
Step 6: Drag and drop a Show Table panel on the page and press the Configure button to display the Panel Wizard.  Select the Customer table and the desired set of fields to display on the page.  Select the set of fields to be searched by the Search control on the page and any filters to display.   Press Finish to configure the table panel.  Using the Design tab, change the layout to your satisfaction.

Step 7:  Switch to the HTML tab and add a Select link to the row.  When the user clicks this link, the CustomerID of this row will be inserted into the CustomerID textbox on the underlying page and the popup window is then closed.
When the end user clicks the Select link, the UpdateTarget function will be called with the CustomerID of the current row.
Step 8:  Add the following client script code inside the page’s layout.  This script can be added right below the line containing the link to the style sheet.  Change the URL if appropriate.
C#:
Visual Basic .NET:
The above Javascript defines a function called UpdateTarget that takes a parameter called “selectedValue”.  The function retrieves the “target” URL parameter from the URL and sets the .value to the selectedValue parameter passed to the function.
Once the value for the target variable is set, the current popup window is closed.
Step 9:  Bind the CustomerID field value to display the ID of the customer for each row.  Launch the Page Properties dialog from the Tools menu, navigate to the CustomerID field in the tree on the left.  Go to the Bindings tab and select the CustomerID field.  On the Display tab select the Literal Display Style.
Step 10:  By default all pages displayed will be added to the session navigation history so that pressing the Cancel button on the page will go back to the previous page.  To ensure that the popup window is not added to the session navigation history, override the UpdateSessionNavigationHistory function and do not call the underlying base function that would add this page to the history.
This should be added in the code-behind file for the CustomerLargeListSelector.aspx page.  In C# this would be CustomerLargeListSelector.aspx.cs and in Visual Basic .NET it would be CustomerLargeListSelector.aspx.vb.
C#:
protected override void UpdateSessionNavigationHistory()
{
     // do nothing
}
Visual Basic .NET:
Protected Overrides Sub UpdateSessionNavigationHistory()
     'Do nothing
End Sub
Step 11:  Build and run the application.  The Customer Large List Selector page is now ready to use.

Monday, August 30, 2010

Learning:Restore Focus after TextBox Automatic Postbacks

Restore Focus after TextBox Automatic Postbacks



Introduction

Postbacks triggered by a DropDownList or a Check Box are hardly noticeable. However it’s a different story when an UpdatePanel refreshes its content after a partial automatic postback. Specifically, two side-effects will occur.
  • Loss of focus: None of the controls on the page will have the focus unless it is explicitly set in the server-side code.
  • Loss of data: Any data changes made between the moment when the postback is triggered and the moment when the postback is finished are wiped out.
For example, a user enters data in a Text Box and presses the Tab key to move to the next field and begins typing. Seconds later, the content in this text box disappears and the user is forced to reenter the data. In this article, I will show you how to save time and prevent the above scenario from happening.

Solution

The root cause of these issues is derived from the way an UpdatePanel is refreshed on partial postback. When an ASP.NET page receives the result of a partial postback, it clears out the current content on the UpdatePanel and resets the inner HTML to a newly received result. All of the DOM objects within the UpdatePanel are destroyed and recreated, resulting in the loss of focus and data. The best solution, of course, is to avoid postbacks in the first place. However, there are times when developers use postbacks for convenience instead of business logic. If the business logic of the postbacks requires no new data from database, (i.e., all information is already available on the client-side), then it can and should be handled with client-side JavaScript code.
However, if new data is required, there is an alternative solution in PageMethods, which is used by Iron Speed Designer’s popup text and image. PageMethods sends to and receives from the server much less data than partial postbacks. They apply the results to existing DOM objects instead of destroying and recreating them, thus preserving the focus and data.
If the two solutions above are not applicable to your page and postback is your only option, there is not much you can do to prevent data loss. The best you can do is to make the server process as fast as possible. However, you can prevent focus loss, or more precisely, restore focus with some JavaScript code.

Implementation

The following JavaScript code is modified from Yuriy Solodkyy’s blog.... Append it to the end of ~\ApplicationWebForm.js for existing projects. You may also append it to a code template in Iron Speed Designer’s installation folder here: \ProjectTemplates\vs200x\cs(vb)\ApplicationWebForm.js. This will ensure that changes are applied to future projects. JavaScript

var lastFocusedControlId = "";

function focusHandler(e) {
    document.activeElement = e.originalTarget;
}

function appInit() {
    if (typeof (window.addEventListener) !== "undefined") {
      window.addEventListener("focus", focusHandler, true);
    }
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(pageLoadingHandler);
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler);
}

function pageLoadingHandler(sender, args) {
    lastFocusedControlId = typeof (document.activeElement) === "undefined"
                ? "" : document.activeElement.id;
}

function focusControl(targetControl) {
    if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
      var focusTarget = targetControl;
      if (focusTarget && (typeof (focusTarget.contentEditable) !== "undefined")) {
        oldContentEditableSetting = focusTarget.contentEditable;
        focusTarget.contentEditable = false;
      }
      else {
        focusTarget = null;
}
try {
          targetControl.focus();
          } catch (err) {}
      if (focusTarget) {
        focusTarget.contentEditable = oldContentEditableSetting;
      }
    }
    else {
        targetControl.focus();
    }
}

function pageLoadedHandler(sender, args) {
    if (typeof (lastFocusedControlId) !== "undefined" && lastFocusedControlId != "") {
      var newFocused = $get(lastFocusedControlId);
        if (newFocused) {
        focusControl(newFocused);
        }
    }
}
Next, in ~\App_Code\Shared\BaseApplicationPage.cs (vb), find the method Control_ClearControls_PreRender() and insert the commented code block “Register RestoreFocus.”
C#

protected void Control_ClearControls_PreRender(object sender, EventArgs e) {
    this.ClearControlsFromSession();

    // Register RestoreFocus
    if(!IsPostBack)
      ScriptManager.RegisterStartupScript(this, GetType(), "RestoreFocus",
        "Sys.Application.add_init(appInit);", true);
}
VB .NET

Protected Sub Control_ClearControls_PreRender(ByVal sender As Object, ByVal e As EventArgs) Me.ClearControlsFromSession()

    ' Register RestoreFocus
   If Not IsPostBack Then
    ScriptManager.RegisterStartupScript(Me, [GetType](), "RestoreFocus", _
        "Sys.Application.add_init(appInit);", True)
   End If
End Sub
Now all pages will return the focus to the previous owner before postbacks.

Conclusion

Text Box automatic postbacks may cause loss of focus and data. The best solution is to avoid them. But if using automatic postbacks is necessary, try restoring focus with JavaScript code.