Appframe Knowledge Base


50 hits
9

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
aviw_Testing_Async.refreshDataSourceAsync()


'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")
     vProc.Parameters.Add("Test","Test")
     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
     vRec.SelectColumns.Add("Test")
     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
CR3.AddStatus(CR3.TaskType.Data,vTask)

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



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

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

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)

3

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="current-item"
	data-item-template="current-item-edit"
	data-item-template="new-item-edit"
	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-attr="src:/file/db/Persons/dsPersons/<%=PrimKey%>/<%=ImageCRC%>" 
	data-attr="href:/persons?<%=ID%>"
	
   	data-action="save" (used in button elements: click button will save record to database)
   	data-action="cancel" 
   	data-action="delete" 
   	data-action="edit" 
   	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-action="next" 
	data-action="previous" 

   	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)
	
	functions:
	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>
	<br>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>
  </div>
</div>

<!-- 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>
	<br>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>
  </div>
  <div data-item-template="current-item" class="active">
    <h4 data-field="Name"></h4>
	<span data-field="Address"></span>
	<br>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>
  </div>
</div>

<!-- 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>
	<br>
	<span data-field="ZipCode"></span>
	<span data-field="City"></span>
  </div>
  <div data-item-template="current-item" class="active">
    <h4 data-field="Name"></h4>
	<input type="text" data-field="Address"></input>
	<br>
	<input type="text" data-field="ZipCode"></input>
	<input type="text" data-field="City"></input>
  </div>
</div>

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 :
(23-feb-2015)
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)
3

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" 
		class="form-control" 
		data-field="PostCode" 
		data-lookup-id="lookupPostCode"
		data-lookup-bindings="Postcode=Postcode, Location=Location">
		
<!--  To define a lookup add attributes as shown below. -->
<div id="lookupPostCode"
		data-templating="lookup"
		data-object-id="dsPostCodes"  
	 	data-lookup-width="400"
		data-display-fields="Postcode, Location">  <!-- creates lookup markup automatically -->
</div>
<!-- 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"
		id="lookupPostCode"
	 	class="list-group"
		data-object-id="dsPostCodes" 
	 	data-lookup-width="400"
		data-disable-instant
		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>
		</div>
	</div>
</div>

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

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

D. Young Hoang :
I am going through the Certification Program using Appframe.Core v4.30.0.19024 and data-lookup-bindings is no longer working. After looking into the js source code, looks like it has been updated to data-value-bindings. I used data-value-bindings and it worked. In addition to that the JS console will throw a warning message if the data type of the first field/column from the lookup's data object does not match with the input data type. To fix that, I need to set the data-display to the selected field. i.e.: <input data-field="CustomerID" type="number" class="form-control" id="Orders_CustomerID" data-lookup="dsCustomers" data-display="ContactID" data-value-bindings="CustomerID=ContactID"> (05-okt-2017)
3

Using Rest API to return result a API resource

Example of how to retrieve documents in Pims Document Control function getDocuments(){ jQuery.ajax({ url: "https://api.pimsdevhosting.com/dcs/documents/?take=100", 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)

D. Young Hoang :
for sorting results, add parm ?order=["Title","OtherField"] or ?order=[{"desc":"Title"},{"asc","OtherField"}] This is important for paging since skip 0 or no skip does not implement row_number() causing the final results to skew... issue https://www.pims.no/issues/issue?43709 (03-jul-2018)
3

How to get access information about current user

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

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

3

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>
</div>

<!-- 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" 
	 data-attr="src:/file/db/info/dsKommentarer/Bilde/<%=PrimKey%>/<%=Bilde%>?height=35" 
	 data-null-image="/static/graphics/camera-icon.svg">

<!-- 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-crop="Bilde" 
		data-ratio="1" 
		data-attr="src:/file/db/brukerinfo/dsPerson/Bilde/<%=PrimKey%>/<%=Bilde%>" 
		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 -->
</div>

<!--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)

3

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: "https://api.pimsdevhosting.com/procedure/dcsCreateNewDocumentID/call", 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)

3

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)

2

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 Francis Becker (29-apr-2013)

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

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
''' http://msdn.microsoft.com/en-us/library/ms229002.aspx
''' </remarks>
Public Class ManagePeople

    Private gEditor As CustomEditorControl

    Public Sub New()

        InitializeComponent()

        ' 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()
        Controls.Add(gEditor)

    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
        atbv_FancyCRMApp_People.RefreshDataSource()

        ' 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!
        atbv_FancyCRMApp_Messages_Unread.RefreshDataSource()
        atbv_FancyCRMApp_Messages_All.RefreshDataSource()

    End Sub

End Class

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

2

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 http://msdn.microsoft.com/en-us/library/ms229002.aspx
''' </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()
        Try
            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
        Next
		
		' 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)

2

How to execute a stored procedure

Try
	Dim myProc As New afProcedureCall("astp_CRM_SearchForCandidates")
	myProc.Parameters.Add("SearchCategory", Me.cSearchCategory.EditValue)
	myProc.Parameters.Add("SearchText", Me.cSearchText.EditValue)
	Dim vDataSet as DataSet = afAccessLayer.ExecProcedure(myProc)
Catch ex As Exception
	CR3.HandleException(ex)
End Try

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

2

How to use the appframe confirm dialog

af.controls.confirm({
                title: "title",
                message: "message",
                buttons: ["Yes", "No"],
				escape: 1,
                callback: function(index) {
                    if (index === 0) {
						//your code
                    }
                }
            });

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

2

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)
Try
    Await t
Finally
    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 Narožnij :
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)
1

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()
vColumnsToRetreive.Add("Primkey")
vColumnsToRetreive.Add("RiskID")
 
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)

1

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
objColumnsToRetreive.Add("Primkey")
 
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)

1

Export report to PDF and save to filestore

Dim vReport As New AppFrame3.Reporting.afReport(vReportID, vFilter)
vReport.LoadLayoutAndData()

Dim vMemoryStream As System.IO.MemoryStream = New System.IO.MemoryStream()
vReport.ExportToPdf(vMemoryStream)

vMemoryStream.Seek(0, System.IO.SeekOrigin.Begin)
Dim vFileStoreLayer As New AppFrame3.Common.Data.afFileStoreLayer
vFileStoreLayer.InsertFile(vMemoryStream, vFileName, vViewName, vPrimKey)

vMemoryStream.Close()

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

Kevin Francis Becker :
I needed to prepare a new row in the filestore table as per Trong's post https://www.pims.no/teamdoc?8088/151517/post-811237 (17-okt-2017)
Kevin Francis Becker :
Dim vTable As DataTable = CType(pFilestoreTableView.DataSource, DataTable) Dim vNewRow As DataRow = vTable.NewRow() vTable.Rows.Add(vNewRow) Dim vPrimKey = vNewRow("PrimKey").ToString() Dim vViewName = pFilestoreTableView.DataSource.ToString() (17-okt-2017)
1

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: "http://www.omega.no/",
    destroyOnClose: true // will dispose of the dialog after it closes

});

vDialog.show();

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

1

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

WITH CTE
AS
(SELECT *,
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')

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

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

1

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)

1

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.

http://stackoverflow.com/questions/155246/how-do-you-truncate-all-tables-in-a-database-using-tsql#156813
*/

/*
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 ? NOCHECK CONSTRAINT ALL'  
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 *
    FROM SYS.IDENTITY_COLUMNS
    JOIN SYS.TABLES ON SYS.IDENTITY_COLUMNS.Object_ID = SYS.TABLES.Object_ID
    WHERE SYS.TABLES.Object_ID = OBJECT_ID(''?'') AND SYS.IDENTITY_COLUMNS.Last_Value IS NULL)
    AND OBJECTPROPERTY(OBJECT_ID(''?''), ''TableHasIdentity'') = 1
    DBCC CHECKIDENT (''?'', RESEED, 0) WITH NO_INFOMSGS'

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

1

Change file in a filetable with web4


HTML:
<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>
            <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. -->
            </div>    
        </div>    
	</div>
</div>	    


JS:


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

$('.fileChange').click(function() {
    ChangeFile($(this).data('inputfileid'));
});

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

1

Multiple recipients in sstp_Mail_MessageSendImmediateSmtp

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

DECLARE @ToRecipientsXML NVARCHAR(MAX)

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

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

1

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: -->

<p><%=MyFieldName%></p>

<!-- 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)

1

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>
		</span>
	</div>

<!--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>
            </label>
        </div>
		<div data-item-template="edit"></div>
    </div>


<!--Example of [data-filter-type="single"] and static list-->
	<h4>Filters</h4>
	<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>
	</div>


<!--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>
            </label>
        </div>
		<div data-item-template="edit"></div>

    </div>


<!--Example of [data-filter-type="multiple"] and dynamically rendered list -->
	<h4>Area</h4>
    <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>)
            </label>
        </div>
		<div data-item-template="edit"></div>
    </div>


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



<!--Example of [data-filter-type="multiple"] and dynamically rendered list-->
	<h4>Severity</h4>
    <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>)
            </label>
        </div>
		<div data-item-template="edit"></div>
    </div>

</div>

<script>
      $(function(){
                 new af.url.DataFilter();
       });
</script>

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

1

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)

1

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()
    InitializeComponent();
    gDataObj = New afDataObject();
	components.Add(gDataObj);
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
        gDataObj.Dispose()
    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)

1

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:
ALTER DATABASE <DATABASE> SET NEW_BROKER WITH ROLLBACK IMMEDIATE

--Enable Service Broker (run separately to ensure db is in single user mode)
ALTER DATABASE <DATABASE> SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE <DATABASE> SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE
ALTER DATABASE <DATABASE> SET MULTI_USER WITH ROLLBACK IMMEDIATE

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

1

How to set background color on cell in afGrid

gridMyGrid.attachEvent("onFormatCellValue", function(pCell) {
	pCell.css.backgroundColor = "#f00";
});

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

1

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

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

<ul>
@foreach (var vRow in vDataSet[0])
{
	<li>@HtmlEncode(vRow["Column1"])</li>
}
</ul>

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)
1

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)

1

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))
            Next
            If vTotal > 0 Then
                e.CustomValue = vExternal / vTotal
            Else
                e.CustomValue = Nothing
            End If
        End If

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

1

Date date-picker web-templating

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

<input type="text" 
		data-field="StartDato"
		data-datepicker="date/datetime"  
		data-startmode="years/months/dates" 
		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)

1

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" 
	data-field="Categories"
	data-options="dsCategories"
	data-option-text="Category">

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

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

0

ListHeader and ListFooter

<!-- ListHeader: Will give a searchbox that search in searchcolumn, sorting, 
				filtering, paging and export to xls (evertyhing based on dataobject config) -->
@Render("ListHeader", ID:"ArkivHeader", DataObject:"dsArkiv")

<!-- ListFooter: Paging support -->
@Render("ListFooter", ID:"ArkivFooter", DataObject:"dsArkiv")

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

0

Build MSI packages for you Pims client

You can now build installer packages for your Pims Client via Login builder project.

  • Open Login builder project ("Appframe->Login Builder").
  • Configure your project or create new one.
  • In toolbar navigate and press "Build->Installer package..."
  • Supply comments for your build and press "Build".

Worth Noting:

  • You should open login builder where you usually build your "ClickOnce". Recommendation is to build it from our terminal servers.
  • Installer package underlying technology (windows installer) uses strict version number policy, only 3 part version numbering is actually used and there is limit for each version number [major].[minor].[build] to [0..255].[0..255].[0..65535].
  • You do not have to care about [build] version part. It will be incremented with every build of installer package.
  • Any number can reside in last part of version number (last number is sometimes called [revision] or [private]).

Installer Login Win · Perma link post comment Posted by: Tomas Dambrauskas (24-sep-2014)

Luke Simcock :
Thanks for this. I couldn't get it to work until i made the first box in the ‘Last Version’ a 0. For my clients I have been using 4.30.1.0 to start my versioning and it seems to be working fine. (15-jan-2015)
0

Using af.common.runTemplate - Generating html with data using a template

/* Calling af.common.runTemplate passing a template and an object containing the data you want
   in your template and/or an object of custom handlers that should be run when the templates
   is replacing the field having that name. Values in the data object get escaped, while the
   return values of any custom handlers do not. Custom handlers are used instead of data if present. */

var vTemplate, vResult, vData = { ID: "TheDivId", Text: "A test text string" };
vTemplate = '<span id="<%=ID%>"><%=Text%> - <a href="<%=Link%>">Click me</a></span>';

vResult = af.common.runTemplate(vTemplate, vData, {
    Link: function(data) {
		// Note: passing data from database into a javascript link like this
		// could result in XSS security holes if not escaped. Be careful!
		return "javascript:alert('" + data.Text + "');";
    }
});

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

0

How to extend a JavaScript object

/* Calling af.common.extend will take the first object, and merge any subsequent objects into the first one,
   overwriting any previous values having the same key. The function returns the modified first parameter. */

var vMyObject = { myItem: true, secondItem: 1 };

af.common.extend(vMyObject, { secondItem: 2, newItem: "Hi" });

// vMyObject is now: { myItem: true, secondItem: 2, newItem: "Hi" }

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

0

Declarative data binding of fields and buttons

<!-- You can declaratively bind fields and buttons by adding a some data-attributes -->
<!-- To bind fields you specify a data-object-id attribute and a data-field attribute -->
<!-- Declarative field binding supports the following element types -->

<!-- Uneditable text (the form-control-static is for when used in a bootstrap3 form) -->
<p class="form-control-static" data-object-id="dsSomething" data-field="SomeField"></p>

<!-- Editable elements -->
<input type="text" data-object-id="dsSomething" data-field="SomeField">
<textarea data-object-id="dsSomething" data-field="SomeField"></textarea>
<select data-object-id="dsSomething" data-field="SomeField">
	<option>Foo</option>
    <option>Bar</option>
</select>


<!-- To bind buttons you specify a data-object-id attribute and a data-action attribute -->
<!-- The currently supported actions are: new, save, cancel, delete, previous and next -->
<!-- You can use input type="button" element, but it is recommended to use button elements -->
<!-- (The btn class is to get bootstrap3 style on the buttons. For appframe style use afButton) -->
<button class="btn" data-object-id="dsSomething" data-action="new">New</button>
<button class="btn" data-object-id="dsSomething" data-action="save">Save</button>
<button class="btn" data-object-id="dsSomething" data-action="cancel">Cancel</button>
<button class="btn" data-object-id="dsSomething" data-action="delete">Delete</button>
<button class="btn" data-object-id="dsSomething" data-action="previous">Previous</button>
<button class="btn" data-object-id="dsSomething" data-action="next">Next</button>

web web-templating · Perma link post comment Posted by: Jan Henrik H. Meling (06-feb-2014)

0

Binding ComboBox in a form to show items from a custom data object

// For how to define an array data object, see: http://kb.omega.no/kb/1240

// For this to work properly, the field must be defined without LookupID and ListBoxID
// in the form panel designer in the app designer.

// Get a reference to the field
var vMyField = formMain.getFields("IssueType");

// Define the ComboBox instance and pass in the data object
vMyField.comboBox = new af.controls.ComboBox({
    input: vMyField.getInput(),
    limitToList: true,
    dropdown: af.controls.DropdownList,
    dataObject: vDataObject,
    displayMember: "Type",
    valueMember: "Type",
    clearable: false
});

// Push the selected value into the form's data object, or call the form's callback
vMyField.comboBox.attachEvent("onValueChanged", function (pValue) {
    if (vMyField.validDataObjectField) {
        vDO.currentRow(vMyField.data.FieldName, pValue);
    } else if (typeof vMyField.callback === "function") {
        vMyField.callback();
    }
});

// Makes the ComboBox not broken
$(vMyField.getInput()).attr("type", "afComboBox");

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

0

How to get and use data from a data source in Razor

// case sensitive stuff!

@{ var data = GetRows("dsMyDatasource", "MyField = 'Something'"); }

@data.Count <!-- Returns the number of rows contained in 'data' -->
@data.Sum("FieldName") <!-- Return the sum of all the values in the specified column -->
@data.Min("FieldName") <!-- Return the smallest of all the values in the specified column -->
@data.Max("FieldName") <!-- Return the largest of all the values in the specified column -->
@data.Average("FieldName") <!-- Return the average of all the values in the specified column -->

@foreach(dynamic row in table){
    <!-- The dynamic keyword makes it possible to access fields on the row 
         without using square brackets ( ["FieldName"] ) -->

    <!-- Return the typed value of a field -->
    @row["FieldName"] 
    @row.FieldName
    
    <!-- Write the value of a field using the default format or using a specified format string -->
    @row.Write("FieldName")
    @row.Write("FieldName", "dd-MMM-yyyy")
}

<!-- Group the data by one or more fields by using .GroupBy(ParamArray pFieldName() As String) -->
@foreach(dynamic group in table.GroupBy("FieldA", "FieldB")){
    <!-- The dynamic keyword makes it possible to access the values of the grouped fields
        without using square brackets ( ["FieldName"] ) -->
 
     <!-- Return the typed value of one of the grouped fields -->
    @group["FieldA"] 
    @group.FieldB
    
    @foreach(dynamic row in group) {
        <!-- Lets you do the same as you normally do with rows -->
    }
    
    @group.Count <!-- eturns the number of rows in the group -->
    @group.Sum("FieldName") <!-- Return the sum of all the values in the specified column -->
    @group.Min("FieldName") <!-- Return the smallest of all the values in the specified column -->
    @group.Max("FieldName") <!-- Return the largest of all the values in the specified column -->
    @group.Average("FieldName") <!-- Return the average of all the values in the specified column -->
    
    <!-- Further group the data by another field by using .GroupBy(ParamArray pFieldName() As String) -->
    @foreach(dynamic subGroup in group.GroupBy("FieldC")){
        <!-- subGroup is used in the exact same manner as group -->
    }
}

razor web · Perma link post comment Posted by: Sigmund Lunde (11-nov-2013)

0

How to manipulate form fields

// Get and set the caption of a field
var vOldCaption = formMain.getFields("FieldName").caption();
formMain.getFields("FieldName").caption("New caption");

// Get and set the disabled state of a field
formMain.getFields("FieldName").disabled();
formMain.getFields("FieldName").disabled(true || false);

// Get and set the visible state of a field
formMain.getFields("FieldName").display();
formMain.getFields("FieldName").display(true || false);

// Hide and show a field
formMain.getFields("FieldName").hide();
formMain.getFields("FieldName").show();

// Get and set the value of a field
formMain.getFields("FieldName").value();
formMain.getFields("FieldName").value("New value");

// Get a reference to the af.controls.ComboBox instance of a field
var vComboBox = formMain.getFields("SomeComboBoxField").comboBox;

// Get references to the different html-elements of a field
// Normally you should not have to do things directly on the html element
// but it you really have to, this is the way to do it
var vFieldElement = formMain.getFields("FieldName").getElement();
var vLabelElement = formMain.getFields("FieldName").getLabel();
var vInputElement = formMain.getFields("FieldName").getInput();

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

0

How to set caption of field in form

formSomething.getFields("FieldName").caption("Your new caption");

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

0

How to define a filter object in JavaScript

// For the filter to be compatible with the filter builder it must be 
// an or-group containing and-groups containing filter expressions.
// If you do not need to support opening the defined filter in the filter builder,
// you can use any structure and it will work when applied to a data object.

var vFilterObject = {
    type: "group",
    mode: "and" || "or",
    items: [
        { /* Groups can be nested in groups to get all possible "and/or" combinations */
            type: "group",
            mode: "and" || "or",
            items: [/* and so on */]
        },
        { /* Expressions having one of these operators must have a single value and its corresponding valueType */
            type: "expression",
            column: "MyColumnName",
            operator:   "equals"
                    ||  "notequals"
                    ||  "greaterthan"
                    ||  "greaterthanorequal"
                    ||  "lessthan"
                    ||  "lessthanorequal"
                    ||  "beginswith"
                    ||  "notbeginswith"
                    ||  "endswith"
                    ||  "notendswith"
                    ||  "contains"
                    ||  "notcontains"
                    ||  "like"
                    ||  "notlike"
                    ||  "dateequals"
                    ||  "timeequals"
                    ||  "timebefore"
                    ||  "timeafter",
            value: "Some value" || 12345 || new Date(),
            valueType: "string" || "number" || "datetime" || "uniqueidentifier"
        },
        { /* Expressions having one of these operators must have value = null and valueType = "null" */
            type: "expression",
            column: "MyColumnName",
            operator:   "isnull"
                    ||  "isnotnull"
                    ||  "istrue"
                    ||  "isfalse"
                    ||  "isblank"
                    ||  "isnotblank",
            value: null,
            valueType: "null"
        },
        { /* Expressions having one of these operators must have an array of two values of a common valueType */
            type: "expression",
            column: "MyColumnName",
            operator:   "between"
                    ||  "notbetween"
                    ||  "timebetween"
                    ||  "timenotbetween",
            value: [
                "a" || 1 || new Date(Date.now() - 1000*60*60*24),
                "z" || 1000 || new Date()
            ],
            valueType: "string" || "number" || "datetime" || "uniqueidentifier"
        },
        { /* Expressions having one of these operators can have one of more values in an array of a common valueType */
            type: "expression",
            column: "MyColumnName",
            operator:   "inlist"
                    ||  "notinlist",
            value: [
                "a" || 1 || new Date(Date.now() - 1000*60*60*24*1),
                "b" || 2 || new Date(Date.now() - 1000*60*60*24*2),
                "c" || 3 || new Date(Date.now() - 1000*60*60*24*3),
                "d" || 4 || new Date(Date.now() - 1000*60*60*24*4),
                "e" || 5 || new Date(Date.now() - 1000*60*60*24*5),
            ],
            valueType: "string" || "number" || "datetime" || "uniqueidentifier"
        }
    ]
};

// NOTE: All the pipes ( | ), are just there to indicate your possibilities,
// and should not actually be present in your filters
        
// If you want to validate the filter, turn it into SQL client-side, or apply it on an array, you can use the af.Filter class
var vFilterInstance = new af.Filter(vFilterObject);

vFilterInstance.toSQL(); // returns the filter as an SQL

var vArrayOfRows = [{ MyColumnName: "Some value" }];
vFilterInstance.filter(vArrayOfRows); // would filter the array using the defined filter

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

0

Checking for multiple things in QueryString in one go

@QueryString.ContainsAll("x", "y", "z")
<!-- Returns whether or not all of the specified query parameters are supplied -->

@QueryString.ContainsIntegers("x", "y", "z")
<!-- Returns whether or not all of the specified query parameters are integers -->

@QueryString.ContainsDecimals("x", "y", "z")
<!-- Returns whether or not all of the specified query parameters are decimals -->

@QueryString.ContainsAlphanumerics("x", "y", "z")
<!-- Returns whether or not all of the specified query parameters are alphanumeric -->

@QueryString.ContainsLists("x", "y", "z")
<!-- Returns whether or not all of the specified query parameters are lists -->

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

0

How to update and save current data object row in JavaScript

// First update the values you want to save
dsSomething.currentRow("SomeField", "NewValue");
dsSomething.currentRow("OtherField", "OtherValue");

// The use one of the following depending on the situation
dsSomething.endEdit(); // Fire and forget
dsSomething.endEdit(function() { /* do something after */ }); // Asynchronously
dsSomething.endEdit(function() { /* do something after */ }, true); // Synchronously

components dataobject web · Perma link post comment Posted by: Torbjørn Mevik (15-jul-2013)

D. Young Hoang :
dsSomething.endEdit(function(eErr, eData) { if (eErr === null) { alert('Successfully saved.'); } else { alert('Something went wrong. Please try again(' + eErr + ')'); } }, true); (06-jul-2018)
0

How to get data using afAccessLayer and afRecordSource

Import Appframe3.Common.Data							


'Table to retrieve data from
Dim vRs As New afRecordSource("atbv_LessonsLearned_LessonCategory")		

'Columns of interest
vRs.SelectColumns.AddRange(New String() {"Category", "Lesson"})	

'Where-clause
vRs.Whereclause="Lesson like '%learned%'"			

'Result is returned as datatable
Dim vLessonCategories as DataTable = afAccessLayer.GetData(rs)			

win · Perma link post comment Posted by: Torbjørn Mevik (08-jul-2013)

Karl Stroud :
Pretty sure it's "Imports Appframe3.Common.Data" with an (s). (05-jun-2017)
Andrew Wooding :
This would be a lot easier to find if mentioned the word "filter". Hopefully my comment here will make it easier for the next person. (25-jun-2019)
0

How to remove toolbar buttons

myToolbar.removeButton("ButtonName");

components web · Perma link post comment Posted by: Øystein Kaldestad (12-apr-2013)

0

How to add new buttons to the toolbar

// Settings ActionID,ButtonStyle,Caption,HasSeparator,Icon,ParentID,Tooltip,Type
myToolbar.addButton({ActionID:'NewButton',Type:'Button',Tooltip:'New button!',Caption:'New Button'});

components web · Perma link post comment Posted by: Øystein Kaldestad (12-apr-2013)