Wednesday, July 25, 2012

Data Action Notifications

Notifications can be displayed as confirmations after any data manipulation operations.

Let’s implement a code business rule to display a notification after every Update, Insert, and Delete action.

Enable shared business rules. Generate the web app.

Start the Project Designer. On the toolbar, press Develop to open the project in Visual Studio.

In the Solution Explorer, double-click on ~\App_Code\Rules\SharedBusinessRules.cs(vb).

Replace the existing code with the following:

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class SharedBusinessRules : MyCompany.Data.BusinessRules
    {
        protected override void AfterSqlAction(ActionArgs args, ActionResult result)
        {
            base.AfterSqlAction(args, result);
            if (result.Errors.Count == 0 && args.CommandName == "Update" ||
                args.CommandName == "Insert" || args.CommandName == "Delete")
            {
                Result.ShowAlert("The action {0} has been completed.", args.CommandName);
                Result.Continue();
            }
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq

Namespace MyCompany.Rules

    Partial Public Class SharedBusinessRules
        Inherits MyCompany.Data.BusinessRules

        Protected Overrides Sub AfterSqlAction(args As ActionArgs, result As ActionResult)
            If (result.Errors.Count = 0 And Arguments.CommandName = "Update" Or
                Arguments.CommandName = "Insert" Or Arguments.CommandName = "Delete") Then
                result.ShowAlert("The action {0} has been completed.", Arguments.CommandName)
            End If
        End Sub

    End Class
End Namespace

Save the file. Press Ctrl+F5 to run the web application from Visual Studio.

Navigate to any page, edit a record, and save. A popup window will open, displaying a notification.

Data Action Notification displayed in a popup window.

Working with Business Rules in Designer

The framework of a generated application can be extended with custom business rules to handle client- and server-side events. The events are typically raised in response to user interface actions. There are several types of business rules:

JavaScript business rules are executed by the client web browser. All other types of business rules are executed on the server. Business rules have uniform access to field values and application framework facilities. The application framework orchestrates execution of business rules, which allows the developer to implement business logic that is not bound to user interface elements.

Business rules can be found in the Project Browser by clicking on the Rules tab when a controller is selected.

Rules tab for a controller in the Project Browser.

A new business rule can be created by using the New | New Rule action on the action bar.

New Rule action on the action bar.

A business rule can be edited by using the context menu action Open.

Open context menu option in the Project Browser.     Business rule edit form in the Project Browser.

The context menu option Sync will select the relevant business rule node in the Project Explorer.

Sync context menu option the Project Browser.     Synced business rule node in the Project Explorer.

The definition of JavaScript, Email, and SQL business rules can be entered in the Script property.

Script text box allows direct editing of a business rule.

Code business rule files must be edited in an external text editor, such as Visual Studio. The Edit Rule action on the action bar will open the .cs(vb) file in Visual Studio.

Edit Rule action on the action bar will open the business rule in Visual Studio.

The Id of a business rule can be changed in the Project Explorer. Click on the Id property to start editing. The context menu action Rename in the Project Explorer also performs the same function.

Rename Id link in the edit form in the Project Browser.     Rename context menu option in the Project Explorer.

Business rules can be deleted using the context menu option Delete in the Project Explorer.

Delete context menu option in the Project Explorer.

Business rules can be moved to a different controller by dragging the business rule node.

Dragging a business rule onto a controller node.     Update business rule moved under Employees controller.

Overview of Business Rules

Business rules extend the functionality of a web application through SQL, C# or Visual Basic, JavaScript, or Email.

Business Rule Properties:

Property Description
Command Argument Specifies the argument of a command that will trigger the business rule. The property value is a regular expression.
Command Name Specifies the names of commands that will trigger the business rule to fire. The property value is a regular expression.

For example: Update|Insert|Delete
Controller Specifies which controller the business rule will apply to.
Id Specifies the Id of the business rule.
Name Specifies a user-friendly name of the business rule.
Phase Specifies the phase of the command in which the rule will fire. Calculate command can only use “Execute” phase.
Script Specifies the script of the rule. C#/Visual Basic rules can be edited in Visual Studio using the Edit Rule action on the action bar.
Type Specifies the type. Available options are: SQL, C#/Visual Basic, Email, JavaScript.
View Specifies which views will permit the rule to be triggered. The property value is a regular expression.

For example: editForm1|grid1

Learn to work with business rules in the Project Designer.

Learn to drag and drop business rules in the Project Explorer.

Common Tasks:

Task Description
SQL Validation Learn to create an SQL Business Rule to perform validation.
Shared Code Business Rule Learn to use the shared business rules file.
Custom Code Business Rule Learn to use custom business rules.
JavaScript Validation Learn to create a JavaScript Business Rule to perform validation.
Simple Email Notification Learn to create a simple notification using an Email Business Rule.

Tuesday, July 24, 2012

Tooltips

Tooltips, also called hints, are commonly used to clarify application element functions to the end user.

Let’s apply a tooltip to the Unit Price data field in the New Order Details form.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab and double-click on OrderDetails / Views / createForm1 / c1 – New Order Details / UnitPrice data field node.

UnitPrice data field in createForm1 of OrderDetails controller in the Project Explorer.

Change the Tooltip property:

Property New Value
Tooltip Please specify the agreed upon price per unit in this order.

Press OK to save the data field. On the toolbar, press Browse.

Navigate to the Order Details page, and create a new order detail. Mouse over the Unit Price input, and the specified tooltip will appear.

Specified tooltip displayed when user mouses over Unit Price input box.

FileName Action

Actions Export to Spreadsheet, Download, and Report will produce a file when executed on the server. The file name is a concatenation of the data controller and the view.

Customers generated report file named after the controller and view.

Let’s create a business rule that will assign custom names to the output files.

First, enable shared business rules and regenerate the project. Start the Project Designer and click Develop on the toolbar to open the project in Visual Studio.

In the Solution Explorer, double-click on ~\App_Code\Rules\SharedBusinessRules.cs(vb) file.

SharedBusinessRules file in the Solution Explorer.

Replace the default code with the following:

C#:

using System;
using MyCompany.Data;
using System.IO;

namespace MyCompany.Rules
{
    public partial class SharedBusinessRules : MyCompany.Data.BusinessRules
    {

        public SharedBusinessRules()
        {
        }

        // 1. "Actions | Export to Spreadsheet" in any controller
        [ControllerAction(".", "FileName", "ExportRowset")]
        public void AssignFileNameToExportSpreadsheet(string fileName)
        {
            UpdateFieldValue("FileName", String.Format("Live {0} Data Link.iqy", 
                ControllerName));
        }

        // 2. "Actions | Download" in 'Suppliers' controller
        [ControllerAction("Suppliers", "FileName", "ExportCsv")]
        public void AssignFileNameToDownloadCsv(string fileName)
        {
            UpdateFieldValue("FileName", String.Format("{0:yyyy-MM-dd} Supplier List.csv", 
                DateTime.Now));
        }

        // 3. "Report |.." in any data controller
        [ControllerAction(".", "FileName", "Report")]
        [ControllerAction(".", "FileName", "ReportAsPdf")]
        [ControllerAction(".", "FileName", "ReportAsExcel")]
        [ControllerAction(".", "FileName", "ReportAsWord")]
        [ControllerAction(".", "FileName", "ReportAsImage")]
        public void FormatReportFileName(string fileName)
        {
            UpdateFieldValue("FileName", String.Format("{0:yyyy-MM-dd} {1}{2}",
                DateTime.Now,
                Arguments.Controller,
                Path.GetExtension(fileName)));
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.IO

Namespace MyCompany.Rules

    Partial Public Class SharedBusinessRules
        Inherits MyCompany.Data.BusinessRules

        Public Sub New()
            MyBase.New()
        End Sub

        ' 1. "Actions | Export to Spreadsheet" in any controller
        <ControllerAction(".", "FileName", "ExportRowset")>
        Public Sub AssignFileNameToExportSpreadsheet(fileName As String)
            UpdateFieldValue("FileName", String.Format("Live {0} Data Link.iqy",
                                                       ControllerName))
        End Sub

        ' 2. "Actions | Download" in 'Suppliers' controller
        <ControllerAction("Suppliers", "FileName", "ExportCsv")>
        Public Sub AssignFileNameToDownloadCsv(fileName As String)
            UpdateFieldValue("FileName", String.Format("{0:yyyy-MM-dd} SupplierList.csv",
                                                       DateTime.Now))
        End Sub

        ' 3. "Report |.." in any data controller
        <ControllerAction(".", "FileName", "Report")>
        <ControllerAction(".", "FileName", "ReportAsPdf")>
        <ControllerAction(".", "FileName", "ReportAsExcel")>
        <ControllerAction(".", "FileName", "ReportAsWord")>
        <ControllerAction(".", "FileName", "ReportAsImage")>
        Public Sub FormatReportFileName(fileName As String)
            UpdateFieldValue("FileName", String.Format("{0:yyyy-MM-dd} {1}{2}",
                                                       DateTime.Now,
                                                       Arguments.Controller,
                                                       Path.GetExtension(fileName)))
        End Sub
    End Class
End Namespace

Save the file.

The implementation handles FileName action with arguments equal to the action command names that require an output file. For example, Export to Spreadsheet action has it’s command set to “ExportRowset”. The application framework will try to obtain a custom filename from the business rules by raising an internal action with command name of “FileName” and argument of “ExportRowset”. If the business rules are updating the filename, then the new name will be assigned to the output file.

Press Ctrl+F5 keyboard shortcut to run the web application. Navigate to the Suppliers page. On the action bar, click Actions | Download.

Download action in the suppliers grid view.

The name of the file will be the current date followed by “Supplier List”.

Download action produced a file with a custom name.

Report action file output will be named with the date and controller name.

PDF Report produced a file with a custom name.

The Export to Spreadsheet action will name the file “Live Suppliers Data Link”.

Export action also produces a file with a custom name.

Monday, July 23, 2012

Custom Modal Forms with SQL Business Rules

Custom modal forms can be used to collect parameters from the user and pass them to business rules for processing.

A custom data controller without a command can define fields, presentation views, and actions. Such controllers may be used as confirmations for actions for the purpose of collecting input parameters.

Let’s consider the steps involved in the creation of a confirmation data controller using a Northwind sample application.

Child views in a master/detail relationship will automatically hide the foreign key field to prevent duplicate display of the field value. This means that the Supplier Company Name field in the list of supplier products controller is hidden.

Suppliers page with Products child view. Products view does not display the foreign key field.

However, sometimes the user may want to change the foreign key of a child record. This may occur if a product is incorrectly associated with a supplier. One solution is to navigate to the standalone Products page where the supplier lookup is visible. A better alternative would be to create a custom action displaying a modal form that will allow the user to change the foreign key field in the child list of products.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. On the toolbar, press New Controller icon.

New Controller icon on the Project Explorer toolbar.

Give this controller the following name:

Property Value
Name SupplierSelector

Press OK to save the controller. In the Project Explorer, right-click on SupplierSelector / Fields node, and select New Field option.

New Field context menu option for Fields node in the Project Explorer.

Give this field the following properties:

Property Value
Name ProductName
Type String
Length 40
Label Product
Values of this field cannot be edited True

Press OK to save. Create another field:

Property Value
Name SupplierCompanyName
Type String
Length 40
Label Supplier
Values of this field cannot be edited True

Save this field, and create one more.

Property Value
Name SupplierID
Type int32
Label New Supplier
Items Style Lookup
Items Data Controller Suppliers
Items Value Field SupplierID
Items Text Field CompanyName

Save the field. Right-click on SupplierSelector / Business Rules node, and select New Business Rule option.

New Business Rule context menu option in the Project Explorer.

Give this business rule the following properties:

Property Value
Type SQL
Command Name New
Phase Execute
Script
set @ProductName = @Context_ProductName
set @SupplierCompanyName = @Context_SupplierCompanyName

Press OK to save.

SQL Business Rule handling New action in SupplierSelector data controller.

In the Project Explorer, right-click on Products / Actions / ag1 (Grid) node and select New Action option.

New Action context menu option in the Project Explorer.

Give this action the following properties:

Property Value
Command Name Custom
Command Argument CustomModalForm
Header Text Change Supplier
Confirmation

_controller=SupplierSelector
_title=Select a New Product Supplier
_width=500

Press OK to save. Right-click on Products / Business Rules node, and select New Business Rule option.

New Business Rule context menu option for Products controller.

Use the following properties:

Property Value
Type SQL
Command Name Custom
Command Argument CustomModalForm
Phase Execute
Script
--update the product supplier
update Products
set SupplierID = @Parameters_SupplierID
where ProductID = @ProductID
--'forget' the previously selected product
set @ProductID = null
--force the data view to refresh
set @Result_Refresh = 1

Press OK to save.

SQL business rule processing custom action for Products controller in Code On Time Project Explorer.

On the toolbar, press Browse.

Navigate to the Suppliers page, and select a supplier. In the context menu of a product, select Change Supplier.

Change Supplier context menu action in the list of products.

A custom modal form will open, displaying the current Product and Supplier.

Custom modal form allowing user to select a new product supplier.

Use the lookup to select a new supplier.

Suppliers lookup.

Press OK to confirm, and the supplier of the product will change to the new supplier.

Friday, July 20, 2012

Code Formula

The Code Formula field is an expression in the language of your project (C# or Visual Basic) that calculates the value of the field every time the row values are changed in response to Calculate action.

Let’s add an Extended Price field in Order Details that will calculate the extended price of the order item using Unit Price, Quantity, and Discount.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab, right-click on OrderDetails / Fields node, and select New Field option.

New Field for OrderDetails controller.

Give this field the following settings:

Property Value
Name ExtendedPrice
Type Currency
The value of this field is calculated by a business rule expression. True
Code Formula
Convert.ToDecimal(unitPrice) * 
    Convert.ToDecimal(quantity) * 
    (1 - Convert.ToDecimal(discount))
Label Extended Price
Values of this field cannot be edited True
Data Format String c
Context Fields ProductID, UnitPrice, Quantity, Discount

Press OK to save the field.

At the top of the Project Browser window, switch to the Data Fields tab. Create a new data field with the following configuration:

Property Value
View createForm1
Category New Order Details

Press OK to save.

New ExtendedPrice field with data field in createForm1.

On the toolbar, press Browse button. Navigate to the Order Details page, and create a new record. Specify a Unit Price, Quantity, and Discount, and the Extended Price will be calculated when you press Tab or click outside of the changed field.

New Order Details form with a calculated Extended Price.

If you change any of the field values and shift focus to another field, the Extended Price will refresh.

When a value is changed in the other fields, Extended Price value will be recalculated.

The code generator automatically creates a business rule file using the Code Formula expression. The resulting file can be seen below.

C#:

using System;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class OrderDetailsBusinessRules : MyCompany.Data.BusinessRules
    {

        [ControllerAction("OrderDetails", "Calculate", "ExtendedPrice")]
        public void CalculateOrderDetails(int? orderID,
            string orderCustomerID, string orderCustomerCompanyName,
            string orderEmployeeLastName, string orderShipViaCompanyName,
            int? productID, string productProductName,
            string productCategoryCategoryName,
            string productSupplierCompanyName, decimal? unitPrice,
            short? quantity, float? discount)
        {
            UpdateFieldValue("ExtendedPrice", 
                Convert.ToDecimal(unitPrice) *
                Convert.ToDecimal(quantity) *
                (1 - Convert.ToDecimal(discount)));
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System

Namespace MyCompany.Rules
    
    Partial Public Class OrderDetailsBusinessRules
        Inherits MyCompany.Data.BusinessRules
        
        <ControllerAction("OrderDetails", "Calculate", "ExtendedPrice")> _
        Public Sub CalculateOrderDetails(ByVal orderID As Nullable(Of Integer),
                                         ByVal orderCustomerID As String,
                                         ByVal orderCustomerCompanyName As String,
                                         ByVal orderEmployeeLastName As String,
                                         ByVal orderShipViaCompanyName As String,
                                         ByVal productID As Nullable(Of Integer),
                                         ByVal productProductName As String,
                                         ByVal productCategoryCategoryName As String,
                                         ByVal productSupplierCompanyName As String,
                                         ByVal unitPrice As Nullable(Of Decimal),
                                         ByVal quantity As Nullable(Of Short),
                                         ByVal discount As Nullable(Of Single))
            UpdateFieldValue("ExtendedPrice",
                Convert.ToDecimal(unitPrice) *
                Convert.ToDecimal(quantity) *
                (1 - Convert.ToDecimal(discount)))
        End Sub
    End Class
End Namespace

Code Value

The Code Value property is a calculation performed every time the record is inserted or updated. The calculation expression is written in the programming language of your project – Visual Basic or C#.

For example, let’s keep track of the last time an order detail was modified.

Start SQL Server Management Studio. In the Object Explorer, right-click on Databases / Northwind / Tables / dbo.OrderDetails node and select Design.

Design context menu option for Order Details table of the Northwind database.

Add a column to the table:

Column Name Data Type Allow Nulls
ModifiedOn datetime True

Save the table. Switch back to the application generator and refresh the Order Details controller.

Refresh the OrderDetails controller.

Activate the Project Designer. In the Project Explorer, switch to the Controllers tab. Double-click on OrderDetails / Views / editForm1 / c1 – Order Details / ModifiedOn data field node.

ModifiedOn data field in editForm1 of Order Details controller.

Change the following properties:

Property New Value
Text Mode Static

Press OK to save the data field. Double-click on OrderDetails / Fields / ModifiedOn node.

ModifiedOn field of Order Details controller.

Change the following properties:

Property New Value
Code Value DateTime.Now
Data Format String g

Press OK to save. On the toolbar, press Browse.

Navigate to the Order Details page, and edit a record. The Modified On field has no value.

First editing an order detail will reveal that Modified On field has no value.

Change any field value in the record, and save. Open the detail view for the same record – the Modified On field value has been updated.

Opening the same record will reveal that ModifiedOn field value was updated upon insertion.

The field will update on every insert or update.

The web application generator has placed the Code Value formula in an automatically generated business rule associated with the data controller.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class OrderDetailsBusinessRules : MyCompany.Data.BusinessRules
    {
        
        [ControllerAction("OrderDetails", "Insert", ActionPhase.Before)]
        [ControllerAction("OrderDetails", "Update", ActionPhase.Before)]
        public void AssignFieldValuesToOrderDetails(int? orderID, 
            string orderCustomerID, string orderCustomerCompanyName, 
            string orderEmployeeLastName, string orderShipViaCompanyName, 
            int? productID, string productProductName, 
            string productCategoryCategoryName, string productSupplierCompanyName, 
            decimal? unitPrice, short? quantity, float? discount, DateTime? modifiedOn)
        {
            FieldValue ModifiedOnFieldValue = SelectFieldValueObject("ModifiedOn");
            object ModifiedOnCodeValue = DateTime.Now;
            if (ModifiedOnFieldValue == null)
                AddFieldValue("ModifiedOn", ModifiedOnCodeValue);
            else
            {
                ModifiedOnFieldValue.NewValue = ModifiedOnCodeValue;
                ModifiedOnFieldValue.Modified = true;
                ModifiedOnFieldValue.ReadOnly = false;
            }
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports System.Text.RegularExpressions
Imports System.Web
Imports System.Web.Security

Namespace MyCompany.Rules
    
    Partial Public Class OrderDetailsBusinessRules
        Inherits MyCompany.Data.BusinessRules
        
        <ControllerAction("OrderDetails", "Insert", ActionPhase.Before), _
         ControllerAction("OrderDetails", "Update", ActionPhase.Before)> _
        Public Sub AssignFieldValuesToOrderDetails(ByVal orderID As Nullable(Of Integer),
                                                   ByVal orderCustomerID As String,
                                                   ByVal orderCustomerCompanyName As String,
                                                   ByVal orderEmployeeLastName As String,
                                                   ByVal orderShipViaCompanyName As String,
                                                   ByVal productID As Nullable(Of Integer),
                                                   ByVal productProductName As String,
                                                   ByVal productCategoryCategoryName As String,
                                                   ByVal productSupplierCompanyName As String,
                                                   ByVal unitPrice As Nullable(Of Decimal),
                                                   ByVal quantity As Nullable(Of Short),
                                                   ByVal discount As Nullable(Of Single),
                                                   ByVal modifiedOn As Nullable(Of DateTime))
            Dim ModifiedOnFieldValue As FieldValue = SelectFieldValueObject("ModifiedOn")
            Dim ModifiedOnCodeValue As Object = DateTime.Now
            If (ModifiedOnFieldValue Is Nothing) Then
                AddFieldValue("ModifiedOn", ModifiedOnCodeValue)
            Else
                ModifiedOnFieldValue.NewValue = ModifiedOnCodeValue
                ModifiedOnFieldValue.Modified = True
                ModifiedOnFieldValue.ReadOnly = False
            End If
        End Sub
    End Class
End Namespace

This can also be done with SQL Business Rules.

Wednesday, July 18, 2012

Custom Input Controls, Status Bars, and ToolTips

Code On Time release 6.0.0.31 introduces the following features, enhancements, and bug fixes:

  • Custom Input Controls are now supported by the client library.
     
  • It is possible to assign input edit controls at runtime.
     
  • Data fields feature the ToolTip property that allows displaying a standard browser tooltip for each field.
     
  • Data views feature Css Class Name property assigned to the 'div' element that represents the data view on a page.
     
  • New tutorials for the Status Bar are now out: 1)http://codeontime.com/learn/feature-tour/status-bars and 2) http://codeontime.com/learn/data-controllers/status-bar.
     
  • Business rules fully support drag and drop.
     
  • Control and User Control property pages and Project Explorer context menu offer "Edit in Visual Studio" option.
     
  • Data Controller properties integrate "Edit Handler" option on the action bar and in Project Explorer. Selection of an option will open either the business rules handler or a shared business rules handler.
     
  • Option "Edit Rule in Visual Studio" is now available for "Code" Business Rules in Project Explorer and designer.
     
  • Dragging a page node after the parent with children is now correctly inserting the dropped page after the last child page of the target.
     
  • Designer toolbar offers Open button to open the project files in Windows Explorer.
     
  • New designer toolbar option "Develop" will open the Visual Studio solution of the code generator project.
     
  • Data Sheet view will automatically set focus on the first cell of the first row when activated from the action bar menu.
     
  • The bug with the loss of focus in the data sheet view in edit mode is fixed.
     
  • The sync is disabled when editing in the data sheet.
     
  • Improved processing of Read-Only When property in form views.
     
  • Advanced menu will work without membership enabled.
     
  • Application pages are sorted by index to fix the "out-of-order" page indexes in legacy projects and projects with custom baseline.
     
  • Designer correctly saves the Status Bar definition.
     
  • Web Site Factory creates a solution file during "Generate" phase instead of when "Develop" action is requested.
     
  • Blob processor uses case-insensitive methods when detecting the utility fields ending with ContentType, Length, and FileName.
     
  • Virtualization node sets now offer CreateField and StatusBar methods.
     
  • Method BusinessRules.NodeSet() can be invoked when processing data controller actions without raising an exception.

Tuesday, July 17, 2012

Activating Custom Input Controls at Runtime

Client library automatically assigns a calendar behavior to all date-time input elements. This is the example of the calendar displayed next to input elements of Order Date, Required Date, and Shipped Date fields in the Orders form of the Northwind sample.

The example of the built-in calendar provided by the client library.

With a very little effort you can introduce an alternative calendar for all input elements rendered for the fields representing dates.

image

Start by enabling shared business rules in the application settings and re-generate the project.

Create the file [Documents]\Code OnTime\Client\Sample Editors\DatePicker.js and enter this script.

// The "factory" object for DateTime input elements
MyCompany$DatePicker = function () {
}

MyCompany$DatePicker.prototype = {
    // This method is invoked for an input element of a data controller field
    // associated with the editor. Return 'true' if no other editors are allowed.
    attach: function (element, viewType) {
        // hide the "calendar" button next to the input element
        $(element).next().hide();
        // attach a jQuery datepicker to the input element
        $(element).datepicker();
        return true;
    },
    // This method is invoked by the client library before the input element
    // of the field is destroyed. Return 'true' if no other editors are allowed.
    detach: function (element, viewType) {
        // detach the datepicker from the input element
        $(element).datepicker('destroy'); 
        return true;
    }
}

Start the code generator and the script will be integrated in the client library.

Activate Project Designer and click Browse to cause the application to be generated. Hit the browser Refresh button to ensure that the latest version of the client library is downloaded.

Switch to Project Designer and click  Develop button on the toolbar. Visual Studio or Visual Web Developer will start. Open ~/App_Code/Rules/SharedBusinessRules.cs(vb) file and enter the following code.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class SharedBusinessRules : MyCompany.Data.BusinessRules
    {
        
        public override bool SupportsVirtualization(string controllerName)
        {
            return true;
        }

        protected override void VirtualizeController(string controllerName)
        {
            NodeSet().Select("field[@type='DateTime']").Attr("editor", "MyCompany$DatePicker");
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq

Namespace MyCompany.Rules
    
    Partial Public Class SharedBusinessRules
        Inherits MyCompany.Data.BusinessRules

        Public Overrides Function SupportsVirtualization(controllerName As String) As Boolean
            Return True
        End Function

        Protected Overrides Sub VirtualizeController(controllerName As String)
            NodeSet().Select("field[@type='DateTime']").Attr("editor", "MyCompany$DatePicker")
        End Sub
    End Class
End Namespace

The methods of the shared business rules class will adjust the definition of data controllers with the help of virtualization node sets. The method VirtualizeController selects all date-time fields and assigns the custom editor at runtime.

Save the file and browse the application from the generator or directly in development environment. Date-time input elements in the entire app are now featuring a new calendar based on jQuery UI date picker.

Make sure to refresh the app when the first page is displayed in the web browser to ensure that the latest version of the custom scripts has been loaded.

Virtualization node sets allow easy assignment of custom input editors to the specific data controller fields at runtime.

Enhancing Applications with Custom Input Controls

The client library of a generated web application offers a tightly integrated suite of presentation views and input controls with automatic data binding. The library is not designed to replace the popular presentation frameworks such as jQuery or Ajax Control Toolkit. The purpose of the client library is to provide a standard extensible presentation layer of a multi-tier web application.

Consider the following screen of the Northwind sample. The standard input elements lookup, dropdown, and text are rendered in the Products form view. It is possible to replace the standard text input element of the Reorder Level field with a modern input control.

The standard input elements such lookup, dropdown, and text are rendered in the Products form view.

The application client library incorporates the entire jQuery and jQuery UI. This allows using a slider plugin for presentation purposes.

The screenshot shows the slider input control in action.

The input control for 'Reorder Level' field is replaced with a fancy slider from jQuery UI.

Input controls are implemented in JavaScript language.

Custom scripts are combined in a single file _System.js, which is included in each generated application. The code generator will automatically build this file from the scripts located under [Documents]\Code OnTime\Client\Scripts folder. The generator scans the folder every time it starts and tries to detect any changes to scripts located there. If the changes are detected, then the entire set of scripts is combined and stored in the single [Documents]\Code OnTime\Library\Data Aquarium\Scripts\_System.js file. The combined script is copied to the appropriate output folder of the project when the app is generated.

Here is how the scripts may be organized on the hard drive of your computer.

Sample contents of '[Documents]\Code OnTime\Client' folder.

Close the code generator and create the file [Documents]\Code OnTime\Client\Scripts\Sample Editors\ReorderLevelSlider.js using Visual Studio or your favorite text editor. Enter the following content and save the file.

// The "factory" object for Reorder Level input field
MyCompany$ReorderLevelSlider = function () { }
MyCompany$ReorderLevelSlider.prototype = {
    // This method is invoked for an input element of a data controller field
    // associated with the editor. Return 'true' if no other editors are allowed.
    attach: function (element, viewType) {
        if (viewType != 'Form')
            return false;
        // figure the initial Reorder Level
        var reorderLevel = $(element).val();
        reorderLevel = reorderLevel == '' ? 0 : parseInt(reorderLevel);
        // mark the element and its parent with CSS classes and hide the element
        $(element)
            .hide().addClass('reorder-level-elem')
            .parent().addClass('reorder-level-parent');
        // create a 'div' element with a slider
        var slider = $('<div>').insertAfter(element)
            .width(150)
            .css({ marginTop: '4px', marginBottom: '4px' })
            .slider({
                value: reorderLevel,
                min: 0,
                max: reorderLevel < 100 ? 100 : reorderLevel,
                step: 5,
                slide: function (event, ui) {
                    // find the parent element of the ReorderLevel input
                    var parent = $(ui.handle).parents('.reorder-level-parent');
                    // change the value of the ReorderLevel input
                    $('.reorder-level-elem', parent).val(ui.value);
                    // update the label with the value of the slider
                    $('.reorder-level-label', parent).text(ui.value)
                        .css('font-weight', 'bold');
                }
            });
        // create a 'span' to be used as a slider label
        $('<div>').insertAfter(slider)
            .text($(element).val())
            .addClass('reorder-level-label')
            .css('marginBottom', '4px');
        return true;
    },
    // This method is invoked by the client library before the input element
    // of the field is destroyed. Return 'true' if no other editors are allowed.
    detach: function (element, viewType) {
        if (viewType != 'Form')
            return false;
        // detach the slider from the input element
        $(element).siblings('div').slider('destroy'); // mandatory
        $(element).siblings('span,div').remove();     // optional cleanup
        $(element).show();                            // optional call
        return true;
    }
}

The script defines a “factory” object MyCompany$ReorderLevelSlider that will be invoked by the client library to allow attaching and detaching custom input enhancements at runtime for the designated data controller fields. Methods attach and detach must return true if no other enhancements are allowed to be associated with the input field. The client library will create a single instance of a “factory” object and use is it as needed when the presentation interface of a web app is changed in response to user actions. If input elements are rendered then the factory object will be asked to attach to the inputs associated with it. If the input elements are not needed anymore then the client library will ask the “factory” object to remove any enhancements it may have created previously.

Start the web application generator. The new script will become a part of the _System.js file. It can now be used in any project that you are working on.

Activate Project Designer and select Controllers / Products / Fields / ReorderLevel field node on the Controllers tab of Project Explorer.

Field 'Reorder Level' selected in Project Explorer of Code On Time web application generator.

Change the field as follows.

Property New Value
Editor MyCompany$ReorderLevelSlider

Save the changes, click Browse button on the designer toolbar.

Make sure to refresh the application as soon as any of its pages in displayed in the browser to ensure that the most recent version of the _System.js file is downloaded.

Navigate to the Products page, select a product and start editing in a form view. The new input control will be displayed.

You can find more about Code OnTime Generator, Data Aquarium Framework, and other great products here.


© 2010 Code OnTime LLC. Intelligent code generation software for ASP.NET. Visit us at http://codeontime.com