Blog

Labels
AJAX(112) App Studio(9) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(178) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(184) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(3) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Sunday, October 12, 2008PrintSubscribe
Using Oracle Sequence

Oracle database server provides support for sequences of unique values that are typically used to generate unique IDs for primary key columns or new records. Data Aquarium Framework and Aquarium Express are supporting automatic execution of static SQL statements just before a table record insertion takes place.

Consider the application created from HR demo schema that comes with Oracle database servers. The DEPARTMENTS table has a matching DEPARTMENTS_SEQ sequence that can be used to supply unique values for the primary key DEPARTMENT_ID.

Form createForm1 is displayed below. You can see that the primary key field is visible on the form and can be changed by user.

image

Let's modify the data controller descriptor ~/Controllers/HR_DEPARMENTS.xml to use the sequence for primary key column values.

The first step is a definition of command that executes just before a new record is inserted into database.

<command id="GetSequence" type="Text" event="Inserting">
  <text><![CDATA[select departments_seq.nextval from dual]]></text>
  <output>
    <fieldOutput fieldName="DEPARTMENT_ID"/>
  </output>
</command>

Attribute event tells the framework about the timing of execution, element text defines the actual SQL statement, and element fieldOutput directs the framework to copy the first column in the first row of command result set to the DEPARTMENT_ID field.

The second and last step of modification is to hide the DEPARMENT_ID field from user interface.

<view id="createForm1" type="Form" commandId="command1" 
  label="New Hr Departments">
  <headerText>Please fill this form and click OK button to create 
    a new hr departments record. Click Cancel to return to the 
    previous screen.</headerText>
  <categories>
    <category headerText="New Hr Departments">
      <description>Complete the form. Make sure to enter all 
        required fields.</description>
      <dataFields>
        <dataField fieldName="DEPARTMENT_ID" columns="15" hidden="true"/>
        <dataField fieldName="DEPARTMENT_NAME" columns="30" />
        <dataField fieldName="MANAGER_ID" aliasFieldName="MANAGER_LAST_NAME" />
        <dataField fieldName="LOCATION_ID" aliasFieldName="LOCATION_CITY" />
      </dataFields>
    </category>
  </categories>
</view>

Attribute hidden on the field DEPARMENT_ID does the job.

Here is how the form is changed.

image

The new department is displayed in the list below.

image

Tuesday, September 30, 2008PrintSubscribe
Lookup Item Styles

Data Aquarium Framework pr0vides a variety of presentation styles for lookup items in your grid and form views.

Consider the following screen shot fragment of products form view in application generated by Code OnTime Generator from Northwind database.

image

Supplier company name and category names are allowing user to select SupplierID and CategoryID in a products table row. If user clicks on a link with category name then the following lookup control is presented.

image

The eraser icon will clear up the selected category.

This advanced lookup control is displayed thanks to the following configuration of SupplierID and CategoryID fields in ~/Controllers/Products.xml data controller descriptor.

<field name="SupplierID" type="Int32" label="Supplier#">
  <items style="Lookup" dataController="Suppliers" 
    newDataView="createForm1" />
</field>
<field name="SupplierCompanyName" type="String" readOnly="true" 
  label="Supplier Company Name" />
<field name="CategoryID" type="Int32" label="Category#">
  <items style="Lookup" dataController="Categories" newDataView="createForm1" />
</field>
<field name="CategoryCategoryName" type="String" readOnly="true" 
  label="Category Name" />

Style of items is set to Lookup.

The source of items is identified by dataController attribute that refers to a corresponding data controller descriptor.

You can change the style of items for CategoryID field by replacing Lookup with DropDownList.

This will translate into the following presentation.

image

Notice that N/A option is automatically added to the list since CategoryID field allows null values to be stored in the table column.

Here is how ListBox item presentation style is rendered.

image

Another popular option is to have lookup items displayed as a radio button list.

image

You can provide a more compact radio button list by adding columns property to the data field in editForm1 form view as shown in the snippet.

<dataField fieldName="CategoryID" aliasFieldName="CategoryCategoryName"  
  columns="3"/>

This is how the presentation of categories has changed.

image

Grid view is also sensitive to the item style and automatically displays the data as prescribed in data controller file. Here you can see a DropDownList style of the lookup items of CategoryID field.

image

A common requirement is to have a custom fixed list of values for certain fields in the database tables.

Redefine the items of CategoryID field as shown in the markup example below.

<field name="CategoryID" type="Int32" label="Category#">
  <items style="RadioButtonList">
    <item text="One" value="1"/>
    <item text="Two" value="2"/>
    <item text="Three" value="3"/>
  </items>
</field>

The presentation of the field will change to the following.

image

If you retain the dataController attribute then both static and dynamic items will show up in a list.

image

Note that dynamic and static items are always sorted in alphabetical order regardless of their nature.

Lookup style is not supported for static items.

Additional display style CheckBox is provided to support fields with boolean data type only.

Monday, September 29, 2008PrintSubscribe
DataViewExtender Events: selected and executed

Data Aquarium Framework includes a collection of JavaScript components that are rendering user interface in a web browser and are interacting with the server components of the framework. You can participate in the client-side life cycle by creating JavaScript event handlers that are responding to selected and executed events raised by Web.DataView component instances injected into the page by DataViewExtender server components.

Event selected is fired when a row is selected in the user interface. You can use get_selectedKey() method of Web.DataView component to find a primary key of a selected record.

Event executed is fired when a command has been executed. Event handler is provided with the result of execution on the server including auto-incremental primary key field values and error messages if any.

Let's explore these events by creating master-detail AJAX grid views that link Products to Suppliers in Northwind database.

Generate an Aquarium Express project with Code OnTime Generator from Northwind database and open this project in Visual Studio 2008 or Visual Web Developer 2008 Express Edition.

Add page Events.aspx to the root of the web site as shown in the sample below.

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
    CodeFile="Events.aspx.cs" Inherits="Events" Title="Events Demo" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">

    <script type="text/javascript">
function pageLoad() {
    var dataView = Web.DataView.find('SuppliersExtender');
    if (dataView) {
        dataView.add_selected(onSupplierSelected);
        dataView.add_executed(onSupplierExecuted);
    }
}

var justInserted = false;

function onSupplierSelected(sender) {
    if (justInserted) 
        justInserted = false;
    else
        updateProductsVisibility(sender.get_lastCommandName() != 'New');
}
function onSupplierExecuted(sender, args) {
    switch (sender._lastArgs.CommandName) {
        case 'Insert':
            updateProductsVisibility(true);
            justInserted = true;
            break;
        case 'Delete':
            updateProductsVisibility(false);
            break;
    }
}
function updateProductsVisibility(visible) {
    Sys.UI.DomElement.setVisible($get('ProductsPanel'), visible);
}
    </script>

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Header1Placeholder" runat="Server">
    Client-Side Events
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="Header2Placeholder" runat="Server">
    Northwind
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="BodyPlaceholder" runat="Server">
    <div id="Suppliers" runat="server" />
    <aquarium:DataViewExtender ID="SuppliersExtender" runat="server" 
        Controller="Suppliers" TargetControlID="Suppliers" PageSize="5"/>
    <br />
    <div id="ProductsPanel" style="display:none">
        <div id="Products" runat="server" />
        <aquarium:DataViewExtender ID="ProductsExtender" runat="server" 
            Controller="Products" TargetControlID="Products" PageSize="5"
            FilterFields="SupplierID" FilterSource="SuppliersExtender" />
    </div>
</asp:Content>

Open this page in a browser. You will see that products are not displayed under the suppliers grid.

image

Click on any supplier row and the page will display a list of relevant products.  If you start adding a new supplier then the list of products will disappear. The list of products will show up again when you actually insert a supplier record. The list of products goes away when you delete a supplier.

image

How does this work?

Let's do a quick code walkthrough.

Element ProductsPanel is wrapped around the placeholder for Products. It doesn't matter if the DataViewExtender component is within the boundaries of the panel. Just make sure that the placeholder is hidden.

<div id="ProductsPanel" style="display:none">
    <div id="Products" runat="server" />
    <aquarium:DataViewExtender ID="ProductsExtender" runat="server" 
        Controller="Products" TargetControlID="Products" PageSize="5"
        FilterFields="SupplierID" FilterSource="SuppliersExtender" />
</div>

ASP.NET AJAX Extensions library automatically invokes JavaScript function pageLoad() when the runtime client components are instantiated and initialized. It works very much like Page_Load function in your server code, which is called when ASP.NET is ready to pass your a control over a page with all server components ready for use. Method Web.DataView.find will find an instance of JavaScript Web.DataView component that was injected into the page by SuppliersExtender server component. This is a convenient spot to assign event handlers of selected and executed events.

function pageLoad() {
    var dataView = Web.DataView.find('SuppliersExtender');
    if (dataView) {
        dataView.add_selected(onSupplierSelected);
        dataView.add_executed(onSupplierExecuted);
    }
}

Function onSupplierSelected will be called whenever a supplier record is selected by a user. This method is invoking updateProductsVisibility function and passes true as a parameter if the last executed action command is not New. We are also making sure that visibility of the products grid is not altered if we just have executed an insertion of a new supplier.

var justInserted = false;

function onSupplierSelected(sender) {
    if (justInserted) 
        justInserted = false;
    else
        updateProductsVisibility(sender.get_lastCommandName() != 'New');
}

Actions that cause an insertion or a deletion of a supplier will result in product details being displayed or hidden accordingly.

function onSupplierExecuted(sender, args) {
    switch (sender._lastArgs.CommandName) {
        case 'Insert':
            updateProductsVisibility(true);
            justInserted = true;
            break;
        case 'Delete':
            updateProductsVisibility(false);
            break;
    }
}

The actual update of products grid visibility is very simple. We are using standard JavaScript components of ASP.NET AJAX Extensions library to hide DOM element with ProductsPanel identifier.

function updateProductsVisibility(visible) {
    Sys.UI.DomElement.setVisible($get('ProductsPanel'), visible);
}

You can enhance this code to suit your own needs by interacting with div elements on your page, which will typically result in hiding and showing of arbitrary page fragments to create less cluttered and more intuitive user interface presentation in your AJAX ASP.NET applications created with Code OnTime Generator.