Appframe Knowledge Base

50 hits

Loading data asynchronous in Appframe

In release Appframe 430 there are support for loading data, forms, reports and executing procedures asynchronously. The framework takes care of loading forms, opening reports and loading data in child datasource. But when it comes to dataobjects that doesn't have a master object, dataobjects that you would like to manually, procedures or fetching data outside dataobject, there are some changes required in order to load async.

'Example 1: Loading dataobject async

'Example 2: Loading dataobject async and working with data
Private Async Sub LoadTestData()
     Dim vTask = aviw_Testing_Async.refreshDataSourceAsync()
     Await vTask
     'do your stuff
End Sub

'Example 3: Executing procedure
Private Async Sub ExecuteTestProcedure()
     Dim vProc = new afProcedureCall("astp_Teting_Async")
     Dim vDataSet as DataSet = Await vProc.ExecuteAsync()
     'do your stuff
End Sub

'Example 4: Executing procedure
Private Async Sub LoadTestData()
     Dim vRec= new afRecordSource("aviw_Testing_Async")
     vRec.MaxRecords = -1
     Dim vDataTable as DataTable = Await vRec.GetDataAsync()
     'do your stuff
End Sub

'Adding status in statusbar for tasks
 Dim vTask = aviw_Testing_Async.refreshDataSourceAsync()
CR3.AddStatus("Loading data",vTask)
' or

'Locking form using a task
Dim vProc as new afProcedureCall("astp_CRM_Test");
Dim vTask = vPro.ExecuteAsync();

win · Perma link post comment Posted by: Peter Øren (02-sep-2014)

Tomas Dambrauskas :
A step forward... (12-sep-2014)

Web-Templating: data-templating="item-list" or data-templating="current-item"

<!--   Databinding attributes:

	data-object-id="dsRecords" (defining the scope)

   	data-templating="item-list" (will look for data-item-template and then render 
	 one copy of the relevant template per record)
	data-templating="current-item" (will look for data-item-template and render one copy 
	 of the relevant template for current record only)

   	data-item-template="default" (root element for the default item template)
	data-item-template="no-data" (rendered if there are no data returned from database)
	data-add-class-if="test:className" //test must be a javacript condition: data.fieldName === 'Test':MyClass
	data-remove-class-if="test:className" //test must be a javacript condition: data.fieldName === 'Test':MyClass
   	data-field="FieldName"	(used in elements to bind data)
   	data-datepicker="date" / "datetime" / "time"
   	data-action="save" (used in button elements: click button will save record to database)
   	data-action="new" (used in button elements: set dataobject.currentRow to -1 and fire beginEdit)
   	data-action="clear"  (used in dropdowns to clear fieldvalue)
   	data-action="done"  (saves if dirty, cancel if not dirty)

   	data-show-newitem (in item-list: allways shows UI for new record, if not present or "false"
	you will need to use an action to show new record UI)
	data-edit-focus (used in current-item-edit and new-item-edit for choosing a specific element that should have focuse when entering edit mode)
	data-template-function (used if custom template is needed. Return name of custom template and this will be used insated of current active template. Must be located on rootelement)
	data-function (can be used on any element and will be executed for each row-rendering)

<!-- Simple bound list of items (all records using same template)-->
<div data-templating="item-list" data-object-id="dsPersons">
  <div data-item-template="default">
    <h4 data-field="Name"></h4>
	<span data-field="Address"></span>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>

<!-- Simple bound list of items, highlighting current-item by introducing a second template -->
<div data-templating="item-list" data-object-id="dsPersons">
  <div data-item-template="default">
    <h4 data-field="Name"></h4>
	<span data-field="Address"></span>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>
  <div data-item-template="current-item" class="active">
    <h4 data-field="Name"></h4>
	<span data-field="Address"></span>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>

<!-- Simple bound list of items, editing current-item -->
<div data-templating="item-list" data-object-id="dsPersons">
  <div data-item-template="default">
    <h4 data-field="Name"></h4>
	<span data-field="Address"></span>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>
  <div data-item-template="current-item" class="active">
    <h4 data-field="Name"></h4>
	<input type="text" data-field="Address"></input>
	<input type="text" data-field="ZipCode"></input>
	<input type="text" data-field="City"></input>

If you need a list of editable items: put inputs in the "default" template.

If you want a popup form for editing, make a "current-item-edit" template with a bootstrap
modal element (you need to trigger the edit by calling the beginEdit on the dataobject.

To trigger an edit, use a button with data-bind="edit"

If you would like to allways show a "new blank record" (enabling the user to input a new item)
just set the "data-show-newitem" attribute (in the data-list root element).

dataobject web web-templating · Perma link post comment Posted by: Sigmund Lunde (07-nov-2014)

Robert Vinkovic :
Solution, not the only one but the only one I have managed to make work: parent div must have data-list="manual-edit" with 2 child divs one with data-item-template="read-only" and one with "edit" (22-jan-2015)
Peter Butt :
Martin Vaaden :
Tried using data-remove-class-if some time ago, but seems like it's not in use any more (?) Seems like data-add-class-if will add class if check == true and remove if check == false (12-jun-2015)

Web-Templating: data-field, data-attr, src, href, crop , null-image, ratio, file upload

<!-- Simple bound form-->
<div data-object-id="dsPersons">
    <h4 data-field="Name"></h4>
	<input type="text" data-field="Address"></input>	
	<button data-action="save" class="btn btn-default">Save</button>
	<button data-action="cancel" class="btn btn-default">Save</button>

<!-- Binding image to img
	 - data-attr="src:url"
	 - data-null-image: will use this image when data is null
<img class="img-responsive thumbnail pull-left" 

<!-- Binding url anchor
	 - data-attr="href:url"
<img class="img-responsive thumbnail pull-left" 
	 data-attr="href:/file/db/info/dsKommentarer/Bilde/<%=PrimKey%>/<%=Bilde%>?height=35" >

<!-- Binding crop with save
	data-crop: enables crop for img. If empty, filestore will be used. If not the value should be varbinary field from table.
	data-ratio: sets the crop ratio (width/height)
<img data-object-id="dsPerson" 
		data-null-image="/static/graphics/camera-icon.svg" >

<!-- Binding fileuploader: Provides drag & drop and fileupload
     - data-object-id
	 - data-upload
<div data-upload class="file-upload-control col-xs-12" data-object-id="dsFiler" id="arkivUploader">
	<!-- put your markup here -->

<!--Upload link to trigger filechooser-->
<a href="#" class="pull-right text-muted" data-upload-target="arkivUploader">velg fil(er) for opplast...</a>

dataobject web web-templating · Perma link post comment Posted by: Sigmund Lunde (09-nov-2014)


Web-Templating: Lookup, lookup-bindings

<!-- To connect a lookup to an input add attribute   
	data-lookup-id="idOfYourLookup" and 
	data-lookup-bindings="field1=field2, field3=field4" 
	field1 and field3 are fields in base (host/target) data-object
	field2 and field4 are fields in lookup data-object  -->
<input type="tel" 
		data-lookup-bindings="Postcode=Postcode, Location=Location">
<!--  To define a lookup add attributes as shown below. -->
<div id="lookupPostCode"
		data-display-fields="Postcode, Location">  <!-- creates lookup markup automatically -->
<!-- If you don't like the instant search (automatic search after 3 charachters) add attribute data-disable-instant -->

<!-- If you would like to use your own custom markup leave out the data-display-fields and provide a template instead-->
<div data-templating="lookup"
		data-limit-to-list="true"> <!-- Remove this attribute to get automatic search after 3 charchters -->
	<div data-item-template="default">
		<div class="list-group-item">
			<span data-field="Postcode"></span>,
			<span data-field="Location"></span> 
			<span data-field="Country"></span>

<!-- If you would like to have the lookup unbound you should leave out the data-lookup-bindings and data-field attributes -->
<input type="tel" 
<div id="lookupPostCode"
		data-display-fields="Postcode, Location">  <!-- creates lookup markup automatically -->
<!--In order to get the selected value you need to use event in javascript-->
<!-- Custom items -->
<div id="lookupHosts"
        data-display-fields="HostName, Title"
        data-object-id="dsMyTestItems"><!--dsMyTestItems should not be defined as dataobject, must be named unique-->
/*function that returns static items as json*/
function myTestItems(){
    return [{HostName:"HostName 1", Title:"Title 1"},{HostName:"HostName 2", Title:"Title 2"}]

dataobject web web-templating · Perma link post comment Posted by: Sigmund Lunde (18-des-2014)


VB.NET Naming Conventions - Windows Forms

''' <summary>
''' This class demonstrates the naming conventions to be followed when writing
''' Windows GUI applications
''' </summary>
''' <remarks>
''' Forms should always have meaningful names, and should never have names
''' like Form1 or Dialog1!
''' For cases not covered by the example and the general naming convention guideline
''' on this site, refer to the official .NET Guidelines for Names found at
''' </remarks>
Public Class ManagePeople

    Private gEditor As CustomEditorControl

    Public Sub New()


        ' Controls and components created using the visual designer should
        ' use a c prefix for names
        cEditButton.Enabled = False

		' Controls and components created in code should follow general naming
		' conventions for variable names
        gEditor = New CustomEditorControl()

    End Sub

    Private Sub ManagePeople_Load(pSender As Object, pArgs As EventArgs) Handles MyBase.Load

        ' Names of data objects should always match the view name

        ' If you have multiple data objects referencing the same view,
        ' use a meaningful suffix but be careful of collisions with
		' names of actual database object!

    End Sub

End Class

win · Perma link post comment Posted by: Jarl Erik Schmidt (08-mar-2012)


VB.NET Naming Conventions - General

''' <summary>
''' This class demonstrates the naming conventions to be followed when writing Appframe
''' libraries and applications
''' </summary>
''' <remarks>
''' For cases not covered by the example, refer to the official .NET Guidelines for Names
''' found at
''' </remarks>
Public Class Person
    Inherits DomainObject

    ' No prefix on constants
    Private Const FormatNameMask As String = "{1}, {0}"

    ' g prefix on class-level static variables
    Private Shared gDatabaseTable As String = "Persons"

    ' Also g prefix on class-level instance variables
    Private gFirstName, gLastName As String

    ' p prefix on parameters
    Public Sub New(ByVal pFirstName As String, ByVal pLastName As String)

        ' v prefix on local variables
        Dim vIsNameValid = String.IsNullOrEmpty(pFirstName) AndAlso Not String.IsNullOrEmpty(pLastName)

        gFirstName = pFirstName
        gLastName = pLastName

        AddHandler MyBase.AfterDataUpdated, AddressOf HandleSomeEvent

    End Sub

    ' Event handlers are technically functions, thus best practice is to rename
    ' the parameters to follow naming conventions. Leaving them as "sender" and "e"
    ' is permissable if they are not referenced within the method body
    Private Sub HandleSomeEvent(ByVal pSender As Object, ByVal pArgs As EventArgs)
        ' TODO: Add some important logic here
    End Sub

    ' We also capitalize the first letter of private method names
    Private Sub DoSomethingRisky()
            Dim vMagicValue As Integer = Integer.Parse("FortyTwo")
        Catch ex As Exception ' Use ex as exception names
            Console.WriteLine("Something blew up: {0}", ex.Message)
        End Try
    End Sub

    Public Function FirstNameIsInList(ByVal pNames As List(Of String)) As Boolean

        ' One letter variable names is ok for indexers, but should be reconsidered
		' if there are several nested for-loops
        For i As Integer = 0 To pNames.Count - 1
            If pNames(i) = gFirstName Then 
				Return True
			End If
		' One-letter variable names is ok for lambda expression parameters
		Dim vUnused = pNames.Where(Function(n) n.StartsWith("p"))

        Return False

    End Function

    Public Overrides Function ToString() As String
        Return String.Format(FormatNameMask, gFirstName, gLastName)
    End Function

End Class

win · Perma link post comment Posted by: Jarl Erik Schmidt (08-mar-2012)


How to get access information about current user

var login = af.userSession.login;
var name =; // Surname, Firstname
var emailAdress =;
var currentDomain = af.userSession.domain;

common web · Perma link post comment Posted by: Jarl Erik Schmidt (10-mai-2012)


Passing Filers to Subreports

' This snippet goes into the parent report.
' It copies the parent's filter into the subreport's Tag member
' Tag member will be automatically assigned as FilterString
Private Sub xtraReport1_BeforePrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs)
	arpt_ModuleFoo_Subreport.Tag = CType(xtraReport1, Appframe3.Reporting.afReport).Filter
End Sub

reporting win · Perma link post comment Posted by: Kevin Becker (29-apr-2013)

Karl Stroud :
This does not appear to have any affect on filtering of subreports? (20-jun-2016)
Kevin Becker :
Sorry this doesn't seem to do anything--I presume it did at one time. (24-jun-2016)

Using Rest API to execute a procedure in Pims

Example of how to use the RestAPI to execute a procedure in Pims: function execProcOnAPI(){ var vData = { "Timeout": 30, "AwaitResult": true, "@DocumentType": "AA", "@Title": "Sample Doc", "@DocGroup": "Administrative", "@FacilityID":"A", "@OriginatorCompany":"AOGD", "@Discipline": "A", "@NewDocumentID":"", "@AddSheetNo":false, "@ContractNo":null, "@WorkPackID":null, "@SubProjectID":null, "@System":null, "@Area":null, "@PONumber":null }; jQuery.ajax({ url: "", data: JSON.stringify(vData), contentType: "application/json", dataType: "json", type: "POST", beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa("UserName" + ":" + "Password")); }, success: function(resultData) { //here is your json. console.log(resultData); }, error : function(jqXHR, textStatus, errorThrown) { console.log(errorThrown); }, timeout: 120000 }); }

rest api web · Perma link post comment Posted by: Johnny Vik (10-jun-2015)


Using Rest API to return result a API resource

Example of how to retrieve documents in Pims Document Control function getDocuments(){ jQuery.ajax({ url: "", type: "GET", beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa("Username" + ":" + "Password")); xhr.setRequestHeader("Accept","application/json"); }, success: function(resultData) { //here is your json. console.log(resultData); }, error : function(jqXHR, textStatus, errorThrown) { }, timeout: 120000, }); }

rest api web · Perma link post comment Posted by: Johnny Vik (10-jun-2015)


Service list definition

This article is outdated. <WebLogin> service setting is no longer used. To enable web login you should include <add key="ForceRemotingWebLogin" value="true" /> in your web.config.

Service list xml defines Appframe services available in login form. You can define them as built in service list or as a url. Recommended way is to have service list url with fall back service list embeded in login executable. Below is minimal example.

service list xml definition

    Service list minimal definition

Building this project would result in no services defined just (manual), but UseWindowsAuthByDefault and UseLocalization would still be used. If UseWindowsAuthByDefault is set to true then authentication will be set to windows authentication on first lauch. If UseLocalization is set to true, current culture and current UI culture will be set acordingly to UserSession.User.Culture and UserSession.User.UICulture.

You can define multiple Client nodes in your service list xml, but keep in mind that your login builder project name and Client name must match (see first image). This is so we can have single service list xml for multiple clients (like "MarketMaker" and "MarketMaker Dev").

Below we define service list xml with most options.

extended service list xml definition

    Extended service list definition

If you want to preselect specific service on first login launch, make sure DefaultService and Service/Name match. Same goes for FallbackServiceName and Service/Name.

<client> node elements explained below.

  1. <Name> - Should directly map to login executable name. Login executable is named after login builder project name. This is important to get right!
  2. <DefaultService> - Should maps to <service> element <Name> value. When login for suns for the first time (or user session can not be loaded from registry) service defined here will be preselected and used first.
  3. <UseWindowsAuthByDefault> - Accepts "true" or "false" values. When set to "true" and <AuthenticationMode> service setting is not set to SQLServer login form will use windows credentials to log in.
  4. <UseLocalization> - Accepts "true" or "false" values. When set to "true" clinet application will apply culture and culture UI settings based on user settings from manage users.
  5. <DisableSplashScreen> - Accepts "true" or "false" values. Only used when building core launcher. When set to "true" user will not be greeted with regular core launcher splash screen.
  6. <WebLogin> - Accepts "true" or "false" values. When set to "true" user will be greeted with web login form as oposed to built in login screen. To load login screen <RemotingHost> setting will be used. Make sure your remoting works before enabling web login.

<service> node elements explained below.

  1. <Name> - Used to identify service from the list of others. Will be displayed in service selection dropdown.
  2. <ClientName> - Name to be displayer when your main form launches (see no. 2 in image below). Also UserSession.Service.ClientName is filled with that value.
  3. <Server> - Server part in your connection string to connect to your service. Also UserSession.Service.Server is filled with that value.
  4. <Database> - Database or "Initial Catalog" part in your connection string to connect to your service. Also UserSession.Service.Database is filled with that value.
  5. <WebUrl> - Used to fill UserSession.Service.WebUIUrl. that in turn is used when you use CR3.OpenAppframePage(), Web UI Url is also used in password reset and two factor authentication functionality. This url should point to valid Appframe web site.
  6. <RemotingHost> - Used to fill UserSession.Service.RemotingHost. Should point to valid remoting host. Remoting in turn should be able to connect to your sql server instance.
  7. <WinAuthRemotingHost> - Used to fill UserSession.Service.WinAuthRemotingHost. Should point to valid windows authentication remoting host.
  8. <WebAPIHost> - Used to fill UserSession.Service.WebAPIHost. Will be used more in the future.
  9. <MainProjectName> - This form will be opened when login succeds. Should be used when you are using custom "Sys.WinClient.Main" that is maintained by your self.
  10. <ImproveApp> - Used to fill UserSession.Service.ImproveApp. Application that will be opened when you press improve button (see no. 10 in image below).
  11. <DocHost> - Used to fill UserSession.Service.DocHost. This in turn is used to display help page when pressing "Help -> View Help" (see no.11 in image below).
  12. <Responsible> - When reset password fails user will be advised to contact responsible via message box.
  13. <AllowRememberPassword> - Accepts "true" or "false" values. When set to "true" and user logs in, he will be prompted to store password in windows credential store.
  14. <AllowAutoLogin> - Accepts "true" or "false" values. When set to "true" and user checks "auto login" check box when prompted to save password, next time he will be logged in automatically. And he will have to use "File -> Log out" in main form to stop logging in automatically.
  15. <FallbackServiceName> - When supplied should point to any other service name. If this service login fails it then tries switching to fallback service and then tries loggin in again.

    When <WebLogin> is set to "true" <FallbackServiceName> functionality will no longer work. To fall back to regular login when web login is enabled hold [Ctrl] + [Alt] when launching client.

  16. <AuthenticationMode> - can be set to "SQLServer" or "IntegratedSecurity". Using this setting will override <UseWindowsAuthByDefault> setting, and will be used per service. This setting should be used together with <FallbackServiceName> to enable fallback to differnt authentication mode.

  17. <LoginProjectName> - used by core launcher. That is the application name (from Win Projects) that will be launched by core launcher. If setting is not present defaults to "App.WinClient.Login". When this setting is present and building "Sys login to app login" that name will be used when preparing project to be inserted as Win Project.

Below is the picture showing how values form service list xml flow to actual usages.

complete picture

    Service list xml value flow.

  • Edited on #2016-05-12# (client node elements explained, web login description)
  • Edited on #2016-06-13# (added missing AuthenticationMode setting description)
  • Edited on #2016-06-15# (added missing LoginProjectName setting description)

Login ServicesXml · Perma link post comment Posted by: Tomas Dambrauskas (02-feb-2016)


Windows client progress indicator

In old times to indicate something is being loaded one could use CR3.SetStatus(String, Boolean, Boolean) and CR3.ClearStatus() to remove indicator. Those do not work well with asynchronous paradigm. That is why ClientExtensions.AddStatus(Task, String) and afForm.SetIsLoading(Object, Boolean) have been introduced. AddStatus can be used directly on task because it is extension method.

Adding progress indication when refreshing data object:

Await stbv_WinClient_ProjectsVersions.RefreshDataSourceAsync.AddStatus(CR3.TaskType.Data)

The result:

loading indicator

    loading indicator invoked with AddStatus

Similarly one can await result from task, adding progress indication at the same time:

Dim sp = New afProcedureCall("sstp_WinClient_WhatsUp")
Dim dataSet = Await sp.ExecuteAsync.AddStatus("What is up ...")

The result:

loding indicator

    loading indicator invoked for stored procedure execution

Former example does not spin loading indicator in the MDI form tab. How come refreshing data object did spin it?..

That is because refreshing any afDataObject will spin that loading indicator automatically.

To spin it by your self you have to use afForm.SetIsLoading.

Dim t = Task.Delay(3000).AddStatus("аккордеон ...")
SetIsLoading(t, True)
    Await t
    SetIsLoading(t, False)
End Try

The result after calling above code 3 times slightly one after another:

loading indicator

    loading and spining indicator invoked for delay task

When using SetIsLoading be sure to call SetIsLoading(t, False) in Finally block. That way it is going to be called no matter what happens in Try block.

AddStatus and CR3.SetStatus do not interact with each other, so CR3.ClearStatus will not affect any loading indicators invoked using other means.

progress win · Perma link post comment Posted by: Tomas Dambrauskas (26-feb-2016)

Vadim Naroznij :
Moving GIFs in the middle of a text are horrible, looks like a boiling soup. It distracts from reading. Also names like "Formidigus, Uogenojus and аккордеон" are not funny - they are confusing. Please try to keep texts also in examples in English. (24-mar-2016)

How to toggle insert, save and delete buttons on the afDataNavigatorControl

' The buttons will be automatically enabled or disabled based on the state of
' the associated afDataObject and does not need to be modified directly.
' Examples:

atbv_Testing_MyStuff.AllowNew = True ' Enables the New button
atbv_Testing_MyStuff.AllowUpdate = False ' Disables the Save button
atbv_Testing_MyStuff.AllowDelete = False ' Disables the Delete button

win · Perma link post comment Posted by: Jarl Erik Schmidt (25-apr-2012)


How to insert data using afAccessLayer

Dim vList As New List(Of KeyValuePair(Of String, Object))
vList.Add(New KeyValuePair(Of String, Object)("Title", "Testing1233"))
vList.Add(New KeyValuePair(Of String, Object)("Status", "Open"))
Dim vColumnsToRetreive As New Appframe3.Common.Data.Columns.afSelectColumnCollection()
Dim vData As DataTable
vData = Appframe3.Common.Data.afAccessLayer.AddData("atbv_RiskMgmt_Risks", vList, vColumnsToRetreive, "atbv_RiskMgmt_Risks")

win · Perma link post comment Posted by: Peter Øren (12-jan-2012)


How to update data using afAccessLayer

Dim lstList As New List(Of KeyValuePair(Of String, Object))
lstList.Add(New KeyValuePair(Of String, Object)("UseRBS", IIf(Me.RadioGroup1.SelectedIndex = 0, True, False)))
lstList.Add(New KeyValuePair(Of String, Object)("Level1Title", Me.txtLevel1.Text))
lstList.Add(New KeyValuePair(Of String, Object)("Level2Title", Me.txtLevel2.Text))
lstList.Add(New KeyValuePair(Of String, Object)("Level3Title", Me.txtLevel3.Text))
Dim objColumnsToRetreive As New Appframe3.Common.Data.Columns.afSelectColumnCollection
Dim dt As DataTable
dt = Appframe3.Common.Data.afAccessLayer.PutData("atbv_RiskMgmt_Constants", lstList, Me.atbv_RiskMgmt_Constants.CurrentRow("Primkey").ToString, "", objColumnsToRetreive, "atbv_RiskMgmt_Constants")

win · Perma link post comment Posted by: Peter Øren (12-jan-2012)


Guidelines for creating afDataObject in code

' It is recommended that you only create afDataObject instances
' through the Windows Forms designer. If you for some reason have to
' do it programatically, it is important that it is disposed correctly.
' Otherwise it will remain identifitely in memory and cause various
' performance issues in the client. Two ways to do this:

' 1. Add the data object to the form's components collection. This will
'    dispose it automatically when the form is closed (recommended):

Public Sub New()
    gDataObj = New afDataObject();
End Sub

' 2. Handle the .Disposed event of the enclosing form/control and dispose
'    the data object manually (not recommended):

Private Sub MyForm_OnDisposed(pSender As Object, pArgs As EventArgs) Handles Me.Disposed
    If gDataObj IsNot Nothing Then
    End If
End Sub

' If the instance is only used within the scope of a single function,
' always enclose it in a Using block like the following:

Using vDataObj As New afDataObject()
    ' Insert code here...
End Using

dataobject win · Perma link post comment Posted by: Jarl Erik Schmidt (08-jun-2012)


Multiple recipients in sstp_Mail_MessageSendImmediateSmtp

-- sstp_Mail_MessageSendImmediateSmtp supports multiple recipients 
-- by using the XML parameters.


SET @ToRecipientsXML = '<Recipients>' 
  + (SELECT Name, EMail FROM atbl_Blah_Blah FOR XML RAW) 
  + '</Recipients>'
EXEC sstp_Mail_MessageSendImmediateSmtp  
  @FromLogin = '',
  @ToXML = @ToRecipientsXML,
  @Subject = 'Example',
  @TextHTML = 'This is a sample text'

sql · Perma link post comment Posted by: Torgeir Fredriksen (17-aug-2012)


How to enable service broker on database

--If you have two databases on the same server (i.e. backup of dev as test). The databases will have the same 
--broker identifier. Then run this statement before enabling the broker:

--Enable Service Broker (run separately to ensure db is in single user mode)

sql · Perma link post comment Posted by: Jan Leon Sandslett (03-sep-2012)


Use CTE and ROW_NUMBER() to mark the først record in a given sortorder

ROW_NUMBER() OVER(Partition by PersonID ORDER BY StartDato) AS Ranking
FROM atbl_CRM_Medlemskap M
WHERE ISNULL(M.Avsluttet,GETDATE()+1) > '2011-12-30')

SET Tellende=1, CUT=0
WHERE Ranking =1

sql · Perma link post comment Posted by: Sigmund Lunde (01-okt-2012)


How do you truncate all tables in a database using TSQL?

/*What is the best way to remove all the data from all the tables using TSQL? Are there system stored procedures, views, etc. that can be used? I do not want to manually create and maintain truncate table statements for each table - I would prefer it to be dynamic.

It would make sense to add filters to i.e. just clean up tables starting with atbl_ and/or those that contains the Domain field. But this can easily be added.

exec sp_MSforeachtable 'ALTER TABLE ? DISABLE TRIGGER ALL'  
exec sp_MSforeachtable 'DELETE FROM ?'  
exec sp_MSforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'  
exec sp_MSforeachtable 'ALTER TABLE ? ENABLE TRIGGER ALL' 
exec sp_MSforeachtable 'IF NOT EXISTS (SELECT *
    AND OBJECTPROPERTY(OBJECT_ID(''?''), ''TableHasIdentity'') = 1

sql · Perma link post comment Posted by: Trygve Haaland (08-nov-2012)


Execute a stored procedure and output html for each row in razor

	var vProcedureCall = ProcedureCall("astp_Some_Procedure");
	var vDataSet = vProcedureCall.Execute();

@foreach (var vRow in vDataSet[0])

razor web · Perma link post comment Posted by: Peter Øren (15-jan-2013)

Arild Røksund :
Should vCategories be vDataSet ? (17-feb-2015)
Peter Øren :
Yes (23-feb-2015)

How to execute SQL from SQLCMD window

How to run a large script (typically from project-upgrader). Add USE <your db> in the top of the script and then it can be executed via: sqlcmd -S <server\instance> -U <username> -P <password> -i <pathToFile>

sql · Perma link post comment Posted by: Nils Arne Ramsvik (24-apr-2013)


Miscellaneous razor functions

Site language: @Language → EN
Localize string: @Localize("hello") → hello
Breadcrumb: @Breadcrumb() → Web > Web 4 > Razor documentation
Link to another page on the site: @Link("login") → Article not found: login
Start a HTML element: @Begin("li") → 
End a HTML element: @End("li") → 
HTML-encode a string: @HtmlEncode("<") → <
URL-encode a string: @UrlEncode("?") → "%3f"
Javascript-encode a string: [" '] → "\" and \u0027"

User-info: Login → @User.ShortName
                Name → @User.FullName
                Authenticated → @User.IsAuthenticated

razor web · Perma link post comment Posted by: Peter Øren (23-aug-2013)


How to make a URL column into a link to that url

gridSomething.attachEvent("onFormatCellValue", function(pCell) {
    if (pCell.fieldName === "URL") {
        var vEscapedURL = af.common.htmlEscape(pCell.dataRow.URL);
        pCell.value = '<a href="' + vEscapedURL  + '">' + vEscapedURL + '</a>';

components web · Perma link post comment Posted by: Jan Henrik H. Meling (21-okt-2013)


Summary of percent field in pivots

        If e.DataField Is fieldExternalShare Then
            Dim vDS As PivotDrillDownDataSource = e.CreateDrillDownDataSource
            For i = 0 To vDS.RowCount - 1
                vTotal = vTotal + CDec(vDS.GetValue(i, fieldTotal)) 
                vExternal = vExternal + CDec(vDS.GetValue(i, fieldExternalManhours))
            If vTotal > 0 Then
                e.CustomValue = vExternal / vTotal
                e.CustomValue = Nothing
            End If
        End If

win · Perma link post comment Posted by: Johnny Vik (27-nov-2013)


Repeater / Template Syntax

<!-- Everything inside <% %> is JavaScript, so you can use variables and if statements.
     If you want to use values from the current row, you can use the variable "row".
     If you want to have logic based on the row index, "i" is the zero based index.
     If you want to have logic based of the previous or next row, "data" is the array of rows. -->

<%if (row.SomeBitField === true) {%>
	<p>The variable is true</p>
<%} else {%>
	<p>The variable is not true</p>

<!-- Normally if you just want the escaped value of a field, you use this syntax: -->


<!-- If you need to replace something or process the value, you need to prefix the field name
     with "row.", as the un-prefixed version is only a shorthand that escapes for you.
     Make sure you escape the value before outputting it when using row.FieldName: -->

<p><%=af.common.htmlEscape(row.SomeField.replace("foo", "bar"))%></p>
<p><%=af.common.stringifyValue(row.FieldA || row.FieldB)%></p>

components web · Perma link post comment Posted by: Martin Vaaden (11-jun-2014)


Declarative Bound Filter Panel

<!--Declartive Filter Panel is an extension to declartive databinding. Look at related kb articles for declartive binding-->
<!--Currently you need to specify an empty edit-template (compability issue)-->

<!-- Each filter section requires [data-filter-type] (multiple, single or search) and [url-pos].  -->
<!-- Depending on data-filter-type optional attributes are: 
       action (search), 
       data-filter-default (multiple), 
       data-filter (multiple and single), 
       data-filter-field(multiple and single)  

<!-- If you have data-filter-type="search" you specify the data-filter-for to specify related textbox and action (remove or search)  and specify action (remove. search) -->
<!--If you have data-filter-type="single" or "multiple" and data is dynamically rendered you need to specify [data-filter-field] attribute to the field that will be used when filtering. -->
<!--If you have data-filter-type="single" or "multiple" and you are going to use static data,  [data-filter] attribute is required on the subelements. This will be used to filter related dataobjects. -->

<!--Specify all dataobjects that will be included in filterpanel using the [data-filter-target] attribute -->
<div data-filter-target="dsIssues,dsInvolved,dsIssueType,dsAreas,dsSeverity,dsCategory,dsActionsAssigned,dsToBeClosed, dsToBeVerified,dsToBeReviewed,dsStarred,dsAwaitingResponse">

<!--Example of [data-filter-type="search"] -->
	<h4>Free text</h4>
	<div class="input-group">
		<input type="text" name="search" id="search" class="form-control" placeholder="Search for..." data-filter-type="search" url-pos="0">
		<span class="input-group-btn">
			<button class="btn btn-default" name="removeBtn" type="button" data-filter-for="search" action="remove"><span class="glyphicon glyphicon glyphicon-remove"></span></button>
			<button class="btn btn-default" name="searchBtn" type="button" data-filter-for="search" action="search"><span class="glyphicon glyphicon-search"></span></button>

<!--Example of [data-filter-type="mulitple"] and static list-->
	<div data-filter-type="multiple" url-pos="1" data-filter-default="Closed IS NULL">
        <div class="checkbox">
            <label><input type="checkbox" data-filter="1=1">
                <span>Include Closed</span>
		<div data-item-template="edit"></div>

<!--Example of [data-filter-type="single"] and static list-->
	<div class="list-group" data-filter-type="single" url-pos="2">
		<a class="list-group-item data-filter-default" data-filter="" >All Issues</a>
		<a class="list-group-item" data-filter="Status = 'Awaiting Response'">Awaiting response</a>
		<a class="list-group-item" data-filter="(Status IN('Completed','Cancelled','Duplicate') AND Closed IS NULL)">To be closed</a>
		<a class="list-group-item" data-filter="(Status = 'Action Assigned' AND Closed IS NULL)">Actions assigned</a>
		<a class="list-group-item" data-filter="(Status = 'To Be Reviewed')">To be reviewed</a>
		<a class="list-group-item" data-filter="AreaResp = SUSER_SNAME()">Area resp is me</a>

		<a class="list-group-item" style="display:none;" data-filter="(AwaitingResponseFromMe > 0)">Awaiting response from me (<span data-object-id="dsAwaitingResponse" data-field="IssueID"></span>)</a>
		<a class="list-group-item" style="display:none;" data-filter="(ToBeClosedBy=SUSER_SNAME() AND Status IN('Completed','Cancelled','Duplicate') AND Closed IS NULL)">To be closed by me (<span data-object-id="dsToBeClosed" data-field="IssueID"></span>)</a>
		<a class="list-group-item" style="display:none;" data-filter="(OpenActionsAssignedToMe > 0)">Actions assigned to me (<span data-object-id="dsActionsAssigned" data-field="IssueID"></span>)</a>
		<a class="list-group-item" style="display:none;" data-filter="(AreaRespIsMe = 1 AND Status = 'To Be Reviewed')" >To be reviewed by me (<span data-object-id="dsToBeReviewed" data-field="IssueID"></span>)</a>
		<a class="list-group-item" style="display:none;" data-filter="(ToBeVerifiedBy = SUSER_SNAME() AND Verified IS NULL And Closed IS NOT NULL)" >To be verified by me (<span data-object-id="dsToBeVerified" data-field="IssueID"></span>)</a>
		<a class="list-group-item" style="display:none;" data-filter="Involved = 1">My Involvement (<span data-object-id="dsInvolved" data-field="IssueID"></span>)</a>
		<a class="list-group-item" style="display:none;" data-filter="Starred = 1">Starred (<span data-object-id="dsStarred" data-field="IssueID"></span>)</a>

<!--Example of [data-filter-type="multiple"] and dynamic list-->
	<h4>Issue Type</h4>
    <div data-filter-type="multiple" url-pos="3" data-object-id="dsIssueType" data-list="manual-edit" data-filter-field="IssueType">
        <div class="checkbox" data-item-template="read-only">
            <label><input type="checkbox">
                <span data-field="IssueType"></span>
		<div data-item-template="edit"></div>


<!--Example of [data-filter-type="multiple"] and dynamically rendered list -->
    <div data-filter-type="multiple" url-pos="4" data-object-id="dsAreas" data-list="manual-edit" data-filter-field="Area">
        <div class="checkbox" data-item-template="read-only">
            <label ><input type="checkbox" >
                <span data-field="Area"></span>, <span data-field="AreaRespFirsName"></span> (<span data-field="IssueID"></span>)
		<div data-item-template="edit"></div>

<!--Example of [data-filter-type="single"] and dynamically rendered list-->
	<div data-object-id="dsCategory" url-pos="5" data-filter-field="Category" data-filter-type="single">
		@Render("Repeater", ID:"repCategories")

<!--Example of [data-filter-type="multiple"] and dynamically rendered list-->
    <div data-filter-type="multiple" url-pos="6" data-object-id="dsSeverity" data-list="manual-edit" data-filter-field="SeverityLevel">
        <div class="checkbox" data-item-template="read-only">
            <label ><input type="checkbox" >
                <span data-field="SeverityLevel"></span> (<span data-field="IssueID"></span>)
		<div data-item-template="edit"></div>


                 new af.url.DataFilter();

web web-templating · Perma link post comment Posted by: Peter Øren (28-jul-2014)


Date date-picker web-templating

<!-- To activate the datepicker use an input with type="text" and add attribute data-datepicker -->

<input type="text" 
		data-format="Short Date">

<!-- data-startmode is optional, default is dates, you can set it to years or months -->
<!-- data-format is optional, default for date is "Short Date" and default for datetime is "General Date Short Time" -->

web web-templating · Perma link post comment Posted by: Sigmund Lunde (19-des-2014)


Select, web-templating, add options from datasource

	To create options in a select element use data-options="dataSource" and specify data-option-text="field" (and data-option-value if different from data-option-text)
<select class="form-control" 

	<!-- Generated options (from data-options datasource) will not replace any options allready in your markup -->
	<option class="text-muted">(choose a category)</option>	

dataobject web web-templating · Perma link post comment Posted by: Peter Øren (23-des-2014)


Change file in a filetable with web4

<div class="modal fade" id="fileupload">
	<div class="modal-dialog">
        <div class="modal-content" style="min-height:300px;">
			<div class="modal-header">
                <h4 class="modal-title">Change file</h4>
            <div class="modal-body">
                    <input id="fileInput" name="fileInput" type="file" /><br />
                    <button type="button" class="btn btn-default btn-lg fileChange" data-inputfileid="fileInput">Upload File</button> <!-- inputfileid it used to know where the file input is. -->


//**** Edit file without edit and upload plugin (update File)
function ChangeFile(pFileInputID) {
    var pFileInput = $('#' + pFileInputID);
    var vFileUploader = new af.components.Uploader({
		url: "/file/upload/" + + "/dsFiles/" + dsFiles.currentRow("PrimKey")
    var hideIndicator = af.controls.working("Uploading file...");
	vFileUploader.upload(pFileInput[0], function() {

$('.fileChange').click(function() {

web · Perma link post comment Posted by: Erik Skagen Vindenes (16-apr-2015)


Setting default values when moving to a new record in data object

/* To set default values when focusing "new row",
   attach an event to the data object's onCurrentIndexChanged event
   and set the default values using this.currentRow(pFieldName, pValue); */

dsDataObject.attachEvent("onCurrentIndexChanged", function(pIndex) {
    if(pIndex === -1) { // index is -1 when "new row" is active
        // "this" is a reference to the data object inside this scope
        this.currentRow("FieldName", "My Default Value");

components dataobject web · Perma link post comment Posted by: Jan Henrik H. Meling (14-mai-2012)


Using af.controls.Dialog - Accessing a Form or Grid inside a designer created dialog

/* Lets assume you have a dialog named MyDialog defined in your article, 
   and that dialog has a Form inside it. If you need to do something with the
   form when the dialog is shown, you can access the javascript object like this: */ {
    var vForm = this.content; // "this" is a reference to MyDialog when inside the show callback
    // Now you can do whatever you want to the form via the vForm reference


components web · Perma link post comment Posted by: Jan Henrik H. Meling (14-mai-2012)


Using af.controls.Dialog - Showing an article or an external page in a dialog

var vDialog = new af.controls.Dialog({
    overlay: { clickCloses: true }, // does what you'd expect
    buttons: { close: true }, // enables the close button in the header
    title: "Omega", width: 1200, height: 650,
    content: "",
    destroyOnClose: true // will dispose of the dialog after it closes


common web · Perma link post comment Posted by: Jan Henrik H. Meling (14-mai-2012)


Using af.controls.Dialog - Create via code with custom buttons and content

var vContent = $('<label style="display: inline-block; padding: 10px 20px 20px 20px;">First name:<input style="display: block;"></label>');
var vDialog = new af.controls.Dialog({
    overlay: { clickCloses: true }, // does what you'd expect
    buttons: { close: true }, // enables the close button in the header
    title: "My Test Dialog",
    content: vContent,
    destroyOnClose: true, // will dispose of the dialog after it closes
    buttonbar: [
        { text: "I have entered my first name", highlight: true,
            click: function() {
                alert("Your name is: " + $(vDialog.getElement()).find("label > input").val());
        { text: "Get me out of here", click: function() { vDialog.close(); } }

components web · Perma link post comment Posted by: Jan Henrik H. Meling (14-mai-2012)


Using af.common.localStorage to save UI state

/* If localStorage is not supported by your browser,
   the settings will be kept in memory and reset on reload.
   If you need to check if your settings will be persisted,
   you can use this command to test for support: */

// > true

/* When getting a setting and the value does not exist
    you can specify a default value as the second parameter
    and that value will be returned if no data is in the localStorage */

af.common.localStorage.get("mySetting", "myDefaultValue");
// > "myDefaultValue"

/* Values that are stored in localStorage gets stored per article
    by reading the value, so make sure this is correct */

af.common.localStorage.set("mySetting", "someOtherValue");
// > undefined

/* You can also remove individual keys */

// > true

/* Or you can clear everything beeing stored for the active article */

// > undefined

common web · Perma link post comment Posted by: Jan Henrik H. Meling (14-mai-2012)


How to show busy indicator

// Shows a "busy" indicator and returns a function that hides it:
var hideIndicator = af.controls.working("Doing lengthy operation...");

// Normally you'd call hideIndicator() in the complete/error function
// of jQuery.ajax, pCallBack/pOnError in, etc.
// Here we just call it after 3000 milliseconds:

var afterWorkComplete = function() {

setTimeout(afterWorkComplete, 1000);

common web · Perma link post comment Posted by: Jarl Erik Schmidt (10-mai-2012)


How to attach event on current-row changed in data object

dsDataObject.attachEvent("onCurrentIndexChanged", function (pIndex) {
	var row = this.currentRow();

components dataobject web · Perma link post comment Posted by: Torgeir Fredriksen (09-mai-2012)


How to open report launcher with prefilled values

Dim vArgs As New OpenReportArgs("arpt_MyModule_ProjectStatus")

vArgs.AddParameter("ProjectName", GetType(String), "Installation Step 3")
vArgs.AddParameter("Milestone", GetType(Integer), "40")

vArgs.HeaderText = "Status  for milestone 40"
vArgs.FooterText = "Status report prepared by department 4"

vArgs.HideFilterString = True


win · Perma link post comment Posted by: Jarl Erik Schmidt (08-mai-2012)


How to open form while passing optional values

' Sometimes you might want to accept optional values in a CR4 form. The
' assembly loader provides a facility to pass constructor arguments, but
' this may be too rigid. The OpenProperty facility allows you to pass
' and read optional values of any type without depending on constructor
' signatures.

' The following code shows how to open a form while passing values to it:

Public Sub cOpenSetup_Click(pSender As Object, pArgs As EventArgs) handles cOpenSetup.Click

	Dim vProjectName = cProject.SelectedValue

	Dim vArgs As New OpenFormArgs("App.Example.ProjectManagement", "ProjectSetup")
	vArgs.AddProperty("ProjectName", vProjectName)
	vArgs.AddProperty("SummaryVisible", False)


End Sub

' The following code shows how to access the passed values in the newly
' opened form defined in another project:

Private Sub MyForm_Load(ByVal pSender As Object, ByVal pArgs As EventArgs) Handles Me.Load

    If HasOpenProperty(Of String)("ProjectName") Then
        cProjectChooser.EditValue = GetOpenProperty(Of String)("ProjectName")
    End If

    If HasOpenProperty(Of Boolean)("SummaryVisible") Then
        cSummaryPanel.Visible = GetOpenProperty(Of Boolean)("SumamryVisible")
    End If

End Sub

win · Perma link post comment Posted by: Jarl Erik Schmidt (08-mai-2012)


Concatenating reports

	Dim vCollection As Appframe3.Reporting.afReport
    Dim vDataTable As DataTable = afAccessLayer.GetData(vRecordSource)

    For Each vRow As DataRow In vDataTable.Rows
        Dim vReport As New Appframe3.Reporting.afReport("arpt_CRM_Test", "TestId = " + vRow("TestId").ToString())

        If vCollection Is Nothing Then
            vCollection = vReport
        End If

    Dim vMemoryStream As System.IO.MemoryStream = New System.IO.MemoryStream()
    vMemoryStream.Seek(0, System.IO.SeekOrigin.Begin)
    Dim vFileStoreLayer As New Appframe3.Common.Data.afFileStoreLayer
    vFileStoreLayer.InsertFile(vMemoryStream, "test.pdf", "atbv_CRM_Tests", pPrimKey)
Catch ex As Exception
End Try

reporting win · Perma link post comment Posted by: Peter Øren (08-mai-2012)


Show a link in a grid that triggers a Javascript function when clicked

// Attach to onFormatCellValue to produce an anchor element with a class
gridName.attachEvent("onFormatCellValue", function(pCell) {
    var vEscaped = af.common.stringifyValue(pCell.dataRow.Name);
	pCell.value = '<a class="myLink" href="#">' + vEscaped '</a>');

// You can abstract out the things you want to do when you click the link
// in a separate function that takes the arguments you need
function sayHi(pName) {
	alert('Hello there from row with name ' + pName + '!');

// Create a jQuery delegate/event on the root element of the grid
// and have the selector for the anchor element with that class
$(gridName.getElement()).on("click", "a.myLink", function(e) {
    // Go from the triggering element up to the nearest <tr>, and determine the index
    var vTr = $(this).closest("tr"),
        vDataIndex ="index"),
        vDataObject = myGrid.getDataObject(),
    // If you only need one field it is adviced to use getData(index, fieldName)
    sayHi(vDataObject.getData(vDataIndex, "Name"));
    // If you need many fields, you can exclude the fieldName parameter and get the whole row object
    vRowData = vDataObject.getData(vDataIndex);
    sayHi(vRowData.Name, vRowData.SomeOtherColumn);    
    return false; // Prevents browser from following the link

components web · Perma link post comment Posted by: Jarl Erik Schmidt (19-apr-2012)


How to connect to exchange via webservice

'List of functions:

Public ReadOnly Property ExService As ExchangeService
            If gExService Is Nothing Then
                gExService = New ExchangeService(ExchangeVersion.Exchange2010_SP1)
                gExService.Timeout = 10000
                gExService.Url = New Uri("https://.../EWS/Exchange.asmx")
                gExService.Credentials = New WebCredentials("", "")
            End If

            Return gExService
        End Get
    End Property

    Public Class InboxItem
        Public Property UniqueID As String
        Public Property ChangeKey As String
        Public Property Subject As String
        Public Property Body As String
        Public Property FromName As String
        Public Property Received As DateTime
        Public Property ReceivedString As String
        Public Property IsRead As Boolean
    End Class

    Public Function GetMessageList(pMaxRecords As Integer, pFolder As String) As List(Of InboxItem)
        Dim vItemsList As New List(Of InboxItem)
        Dim vFolder As WellKnownFolderName
        Dim vMessage As EmailMessage
        Dim vItemIndex As Integer = 0

        Select Case pFolder.ToUpper()
            Case "INBOX"
                vFolder = WellKnownFolderName.Inbox
            Case "SENT ITEMS"
                vFolder = WellKnownFolderName.SentItems
            Case Else
                Throw New Exception("Invalid Folder")
        End Select

        Dim vResults As FindItemsResults(Of Item) = ExService.FindItems(vFolder, New ItemView(pMaxRecords))

        If vResults.Items.Count = 0 Then
            Return vItemsList
        End If

        Dim vPropertySet As New PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, EmailMessageSchema.From, EmailMessageSchema.DateTimeCreated, EmailMessageSchema.IsRead)
        Dim vResponses As ServiceResponseCollection(Of ServiceResponse) = ExService.LoadPropertiesForItems(vResults, vPropertySet)

        For Each vResponse As ServiceResponse In vResponses
            If vResponse.Result = ServiceResult.Success AndAlso TypeOf vResults.Items(vItemIndex) Is EmailMessage Then
                vMessage = DirectCast(vResults.Items(vItemIndex), EmailMessage)

                vItemsList.Add(New InboxItem With {.UniqueID = vMessage.Id.UniqueId,
                                                   .ChangeKey = vMessage.Id.ChangeKey,
                                                   .Subject = vMessage.Subject,
                                                   .FromName = vMessage.From.Name,
                                                   .Received = vMessage.DateTimeCreated,
                                                   .ReceivedString = vMessage.DateTimeCreated.ToShortDateString(),
                                                   .IsRead = vMessage.IsRead})
            End If
            vItemIndex += 1
        Return vItemsList
    End Function

win · Perma link post comment Posted by: Peter Øren (26-mar-2012)


JavaScript Conventions - Article Script

// Now support importing of templates or other scripts like this:
"import /static/template/af.common.templates.someTemplate.js";

// Standard function scope. Not really necessary when debugging.
	var w = scope.window, $ = w.jQuery,
		vAny, vVariables, vYou, vMight, vNeed;

	function anyCommonFunctions(pYouMightNeed) {
		return "somethingUseful";

	$("div.someClass").append(c.runTemplate(af.common.templates.someTemplate, {
		TemplateField: "someValue",
		OtherField: 12345
	}, {
		CustomField: function(pData) {
			return pData.TemplateField + pData.OtherField;

	// Remember to include some comments for non-obvious things


components web · Perma link post comment Posted by: Jan Henrik H. Meling (08-mar-2012)


JavaScript Conventions - Inheritance

(function(scope, undef) {
    "use strict";
	var w = scope.window, af =, c = af.common;

	function MyChildControl() {
        var that = this, priv = {
            myVariable: 54321
	/* The line below will create an instance of the control you want to inherit from,
       and assign it to the prototype property of your constructor. */
	MyChildControl.prototype = new af.controls.MyControl();
	// Remember to only expose what you want exposed
	c.expose("af.controls", MyChildControl);

components web · Perma link post comment Posted by: Jarl Erik Schmidt (08-mar-2012)


JavaScript Conventions - Controls

/* First we create a function scope with two parameters, one is the scope ("this" in this context),
   the other is undefined, which will always be undefined even if someone does window.undefined = true; */
(function (scope, undef) {
    "use strict"; // This will enable ES5 strict-mode for browsers that support this

	/* Then we have this one line which should contain any needed references to other libraries
       and any shared variables that should be shared between instances of your control.
       af.common contains common functions used everywhere in web4, and should always be present */
    var w = scope.window, d = w.document, af =, c = af.common, shared = { instanceCount: 0 };
	// is using jQuery, you should add   $ = scope.jQuery,   as a variable above

    /* We capitalize first letter for constructors and use camelCasing for the rest
       If your constructor takes options, they should always be object literals:
       { myOption: "hello", important: true } */
	/* By including a comment using the format shown below, documentation can be automatically generated for your control */
    function MyControl(pOptions) {
         * A short description of your control, for use in documentation
         * or just so others know when looking at your code.
         * @param {object} pOptions An object literal containing options for your control
         * @return {MyControl} Returns an instance of MyControl when called using the new operator
         * @constructor

        /* "that" refers to the instance of this constructor, and is used for exposing or accessing public
           properties or functions. "priv" is an object literal containing any local variables. */
        var that = this, priv = {
			options: new c.Options({ // instantiate the common Options class
				defaults: {
					myOption: "hey",
					otherOption: 2
				required: ["important"], /* this will make your constructor throw an exception if the
                                           option called "important" is not passed to pOptions */
				// deepMerge: ["data"], // If you need to merge in depth
				// mergeDepth: 2, // you can use these two options
				passed: pOptions // this sends in the passed options to the Options class for checking
			eventHandler: new c.EventHandler(that, { // Include this if you need events for your control
                onSomething: { abortable: false } /* Setting abortable to true will allow an event to
                                                    stop execution of subsequent events by returning false. */
			element: null, /* If you are making a visual control, it is good to have a private variable
                              to keep a reference to the generated root element of your control. */
			someOtherVariable: 12345

		/* The three functions below are shortcut functions, and should be included and used when using events */
        function fireEvent(pEvent, pArgs, pModifiableArgs) { return, pArgs, pModifiableArgs); }
        function attachEvent(pEvent, pFunc) { return priv.eventHandler.attach(pEvent, pFunc); }
        function detachEvent(pEvent, pFunc) { return priv.eventHandler.detach(pEvent, pFunc); }

		/* All functions that are not constructors should be camelCased.
           Try to keep the size of a function under 40 lines if possible
           by refactoring into smaller functions and reusing code. */
        function someFunctionWeKeepToOurselves() {
			return 123;

		/* By including a comment using the format shown below, documentation can be automatically generated for your control */
		function someFunctionWeWantExposed(pSomeParameter) {
             * A function that returns a fixed string joined with the passed string using a dash.
             * @param {string} pSomeParameter The string you want appended to the fixed string
             * @return {string} A fixed string and the passed string joined with a dash.
			var vSomeVariable = "used only by code in this function";
			return [vSomeVariable, pSomeParameter].join(" - ");

		function initialize() { // Initialization code
			// Use of shared variable inside the instance

			// Use of private variable inside the instnace
			priv.myPublicVariable += 50;

		// Expose the functions you want available on the instance here
		that.someFunctionWeWantExposed = someFunctionWeWantExposed;
		// If you have many functions, use this method instead
		//c.expose(this, [attachEvent, detachEvent, someFunctionWeWantExposed, andSoOn];

		initialize(); // Finally we run the initialization code

	c.expose("af.someNameSpace", MyControl); // Expose you control to a namespace

}(this)); // This will refer to window when using a browser

components web · Perma link post comment Posted by: Jarl Erik Schmidt (08-mar-2012)


How to set the datanavigator to active tab page grid

#Region "Set datanavigator datasource and custom tabspecific whereclause"
    Private Sub cMainTab_SelectedPageChanged(ByVal sender As System.Object, ByVal e As DevExpress.XtraTab.TabPageChangedEventArgs) Handles cMainTab.SelectedPageChanged
        ' Find and select the grid:
        For Each ctrl As Control In Me.cMainTab.SelectedTabPage.Controls
            If TypeOf ctrl Is Appframe3.Win.Controls.afGrid Then
                Dim vWhereclause As String = ""
                DataNavigator.DataSource = CType(ctrl, Appframe3.Win.Controls.afGrid).DataSource
                DataNavigator.cDataNavigator.DataSource = CType(ctrl, Appframe3.Win.Controls.afGrid).DataSource
                Catch ex As Exception
                End Try
            End If
        If cMainTab.SelectedTabPage.Name = cTabStart.Name Then
            DataNavigator.Visible = False
            DataNavigator.Visible = True
        End If
    End Sub
#End Region

win · Perma link post comment Posted by: Werner Waage (21-feb-2012)


How to get afSendMail to connect to multiple databases

Duplicate the <dbconnection> item in MailSettings.xml

			<PIMS_DEV>Server=;Database=PIMS1;User ID=af_mail;Password=Pwd</PIMS_DEV>
			<PIMS_TEST>Server=;Database=PIMS2;User ID=af_mail;Password=Pwd</PIMS_TEST>
			<PIMS_PROD>Server=;Database=PIMS3;User ID=af_mail;Password=Pwd</PIMS_PROD>

win · Perma link post comment Posted by: Nils Arne Ramsvik (02-feb-2012)


How to upload files using javascript (plupload)

var vUploader = new af.controls.Uploader({
    autoUpload: true,
    showUploadButton: false,
    dataSourceId: "dsSomething",
    initialize: true
vUploader.setBindings({ IssueId : dsIssues.currentRow("IssueID") });

vUploader.attachEvent('onUploadComplete', function() {

components web · Perma link post comment Posted by: Peter Øren (18-jan-2012)


How to set sortorder on dataobject

dsKnowledge.setParameter("sortOrder", [{Created:'desc'}]);

components dataobject web · Perma link post comment Posted by: Peter Øren (17-jan-2012)


How to execute a procedure from javascript

// Fire without parameters

// Fire without parameters synchronously

// Fire without parameters with callback
procMyProcedure.execute(function(err, data) {
    if (err === null) {
        // use data
    } else {

// Fire without parameters synchronously with callback
procMyProcedure.execute(function(err, data) {
    if (err === null) {
        // use data
    } else {
}, true);

// Fire and forget
    Param1: "foo",
    param1: 12345

// Fire using callback
    Param1: "foo",
    param1: 12345
}, function(err, data) {
    if (err === null) {
        // use data
    } else {

// Fire synchronously
    Param1: "foo",
    param1: 12345
}, true);

// Fire synchronously with callback
    Param1: "foo",
    param1: 12345
}, function(err, data) {
    if (err === null) {
        // use data
    } else {
}, true);

components web · Perma link post comment Posted by: Peter Øren (16-jan-2012)