This chapter will guide you through the process of implementing basic functionality using the Genie JavaScript SDK. You will implement a login page, show an application menu driven by the process map in the server application, and hook up a data entry form to an activity and its associated fields and methods.
To configure some of the functionality of the SDK, you're target project will need to define a config object in JavaScript, which we’ll detail here:
window.genie = window.genie || {}; genie.config = { appendColonToLabels: false, appSite: 'MySite', authenticationMode: 'Alternate', backButton: false, formmappingFormat: '[p]', homePage: 'Home', implementationId: '', keepActivitiesOpenForSession: true, loginPage: 'Login', maintenancePage: 'Maintenance', messageBundlePath: 'assets/', onMaintenance: false, showAllMessages: false, timeFormat: 12, urlBlobs: 'http://xxx.com/downloads/blobs/', urlPrefix: 'https://localhost/GenieService/GenieService.svc/restishssl/', urlProxy: '/ESAProxy.ashx', useBundle: true, xmlNamespace: 'http://www.saasplications.com/GenieService' }; |
<script type="text/javascript" src="~/Scripts/config.js"></script> |
Form mapping files are used to map activities on the server to pages on the client. Therefore, if the server issues an activity request, the Genie JavaScript SDK will know which page to navigate to in response. Let’s create a form mapping file now:
<activities> <activity form="Home" default="true"/> <activity form="DataEntry" name="[activityname]" style="[activitystyle]" /> <activity form="SummaryList" name="[activityname]" style="[activitystyle]" /> </activities> |
As you add new pages to your application, you will need to ensure that you add a corresponding activity element for it in this file.
Note: Adding a default="true" attribute to an activity element will result in that activity automatically being navigated to after a successful login.
Now we can finally start building out application. Let’s implement a simple login page, which will contain User Name and Password fields (with corresponding labels obtained from the server), a Log In button, and a message control.
<div bind="login"> <div id="username"> <label>User Name:</label> <input /> </div> <div id="password"> <label>Password:</label> <input type="password" /> </div> <div> <button type='submit'>Log In</button> </div> <div bind="messages"></div> </div> |
The way that this works is that the SDK looks for elements in the page with the bind="login" attribute. If it finds one, then it will look for the username, password, and submit elements, and handle them accordingly. You’ll note this bind attribute pops up regularly (it also appeared in this example for the message control). This is how the SDK knows what elements it should watch and interact with.
Note: After the user has logged in and is using the application, if the user’s session is lost (cleaned up, etc), then a pop up window will appear (invoked by the SDK) asking them to log in again.
Let’s display a menu at the top of the page, based upon the contents of the process map sent by the server, and the form mapping file.
<div id='menuMainContainer'> <ul id='menuContainer' bind='menu'></ul> </div> |
Note: You’ll find that the process map now renders on the login screen. To prevent this behaviour, usually your login page will use a different master layout to that of all other pages, which doesn’t include this control.
Let’s implement a view that displays a list of items. Once we have that, we’ll customise it to allow you to drill down upon an item in the list.
<div bind="activity" activityname="[activityname]" activitystyle=" [activitystyle] "> </div> |
<div bind="activity" activityname="[activityname]" activitystyle="[activitystyle]">
<table id="mySummaryList" bind="data" populatemethod="[methodname]"></table>
</div>
The SDK will see this, call the method on the activity specified by the populatemethod attribute, and populate the table with data retrieved from the server.
You can customise the rendering of the list using underscore templates. Detailing the use of underscore templates is beyond the scope of this document, but some good sources of information include:
Using this templating approach, you can completely change how the list is rendered. This may include customising what columns are displayed in a table, or completely restructuring how the data is laid out. Let’s implement a template now.
<table id="mySummaryList" populatemethod="listMyCookingClasses" bind="data"></table>
<script type="text/template" id="mySummaryListHeaderTemplate">
<thead>
<tr>
<th>Title</th>
<th>Date</th>
<th>Venue</th>
<th>Avail.</th>
<th>Status</th>
</tr>
</thead>
</script>
<script type="text/template" id="mySummaryListItemTemplate">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</script>
<script type="text/template" id="mySummaryListItemTemplate">
<tr>
<td><%=data.Name%></td>
<td><%=data.EventDate%></td>
<td><%=data.Venue_Address%></td>
<td><%=data.AvailableSpaces%></td>
<td><%=data.Status%></td>
</tr>
</script>
You can access data deeper than just the top level, but you will need to use underscores in place of dot notation. Note how data.Venue_Address returns the value of the Address field on the Venue object.
You can turn on the ability to drill down on an item in a data control by setting the candrilldown attribute to true on the data control element. The first cell of each row will be turned into a hyperlink, which the user can click on to drill down on that row.
<table id="mySummaryList" populatemethod="listMyCookingClasses" bind="data" candrilldown="true"></table>
Note: The hyperlink will only be created for data controls that are rendered as a table, with no item templating applied. However, any anchor tags defined in item templates will be treated as drill down links automatically. You simply need to set the url of the anchor tag to be of the format pagename#id=x.
Setting the candrilldown attribute to true will create the hyperlink, but by default the drill down will remain on the same page. If, for example, you want the user to be able to drill down on an item to view more details about that item in a different page, you can set the drilldownpage attribute on the data control element to point to the page to be navigated to.
<table id="mySummaryList" populatemethod="listMyCookingClasses" bind="data" candrilldown="true" drilldownpage="details.html"></table>
A row action typically appears as a button or a hyperlink on each row of the data publication, which performs an action on that row. For example row actions may be things such as Edit, Delete, Add to Cart, and so on. These actions will map to methods on the server.
<script type="text/template" id="mySummaryListItemTemplate">
<tr>
<td><%=data.Name%></td>
<td><%=data.EventDate%></td>
<td><%=data.Venue_Address%></td>
<td><%=data.AvailableSpaces%></td>
<td><%=data.Status%></td>
<td><button actionid="MyAction">Test Action</button></td>
</tr>
</script>
<activity form="SummaryList" name="[activityname]" style="[activitystyle]">
<gridview id="mySummaryList">
<actions>
</actions>
</gridview>
</activity>
<activity form="SummaryList" name="[activityname]" style="[activitystyle]">
<gridview id="mySummaryList">
<actions>
<action id="MyAction" methodName="TestActionMethod" />
</actions>
</gridview>
</activity>
<activity form="SummaryList" name="[activityname]" style="[activitystyle]">
<gridview id="mySummaryList">
<actions>
<action id="MyAction" methodName="TestActionMethod">
<param name="itemId" value="@contextId" />
<param name="contextObject" value="Item" />
</action>
</actions>
</gridview>
</activity>
These param elements are essentially just key/value pairs. The keys can be any value that the server method expects as its parameters. Note how the value of the itemId parameter is @contextId. This is a special replacement variable. When the method call is made to the server, this value will be replaced with the row ID.
Note: If you want to pass the value of an input element to the method as a parameter, you can use the @userInput special replacement variable as the value of a parameter. When the action is invoked, the SDK will look for an input in the item/row whose name is of the format <rowid>_userinput_<paramname>.
Rather than invoking a method on the server when a button is clicked (as per actions), you may wish to get and display a context menu instead. To do so, follow the same method outlined in the section titled Adding Support for Row Actions, but instead of specifying a methodName attribute, specify a contextMenu attribute instead. For example:
<activity form="SummaryList" name="[activityname]" style="[activitystyle]">
<gridview id="mySummaryList">
<actions>
<action id="MyAction" contextMenu="xxx.Item">
<param name="itemId" value="@contextId" />
<param name="contextObject" value="Item" />
</action>
</actions>
</gridview>
</activity>
Nothing needs to be done to enable editable data grids. When a data publication is received from the server that is marked as being editable, the default template will automatically insert input boxes in editable cells.
Note: If you are templating the data publication control, it’s essential that your input elements have a data-columnid attribute with the column ID that the input element corresponds to as its value in order for any value changes to be sent back to the server. <- Does not work properly currently. Should be by column name.
Let’s create a data entry form that displays data from the server, allows you to edit it, and saves those changes back to the server.
You learnt how to configure an activity container in the previous section. Do the same again here for the data entry form, mapping it to an activity/style combination in the server application:
<div bind="activity" activityname="[activityname]" activitystyle="[activitystyle]">
</div>
You learnt how to configure message control back when implementing the login view. Do the same again here for the data entry form.
Note: You can put the message control either inside the activity container div, or outside of it. If it’s within the activity container div, then it will only display messages from that activity. When placed outside, it will show messages from all the activities on the page (including popup windows, etc).
<div bind="messages"></div>
You’ll note that the message control renders as an unordered list. You can use CSS styles to render it according to your needs.
There are a number of ways of binding an input field to a field on the server. One way is as follows:
<div bind="activity" activityname="[activityname]" activitystyle="[activitystyle]">
<input bind="field" fieldid="LastName" />
</div>
Note how we’re setting the bind attribute to a value of “field” (so the SDK will know that it’s an element to be mapped to a field on the server), and setting the fieldid attribute to the name of the field to map to. The SDK will display the value of that field in the input box.
Normally, however, you will also have a label associated with the field. The following HTML demonstrates binding both a field plus a label to a field on the server:
<div bind="activity" activityname="[activityname]" activitystyle="[activitystyle]">
<div bind="field" fieldid="FirstName">
<label></label>
<input />
</div>
</div>
As you can see, we’ve bound the parent div to the field on the server, and simply created label and input elements within the div. The SDK will automatically map the label of the field sent from the server to the label element, and map the value of the field to the input element.
It’s a similar story when you have a field that will display a number of values that the user can select from (such as a dropdown list), however you bind it as a datafield (instead of just a field), and you also need to specify the populate method or query:
<div bind="datafield" fieldid="Title" populatemethod="listTitles">
<select></select>
</div>
To finish this data entry form we need a Save button. Add the following HTML to your view:
<button bind="method" method="Save">Save</button>
When you click this button, a message should appear in the message control you configured earlier stating that the save was successful.
In this step, we will explain “How to add new JavaScript SDK component and render it as HTML page?”.
We will be creating new component “Chart of Accounts” and adding it to existing list of menus/components.
For each menu, there is corresponding html page which renders when user click on that menu.
First we have to find where the existing html pages in source code are. You can find in “Views/App” folder. Now, you can copy existing page “CheckList.cshtml” and rename it to “ChartOfAccounts.cshtml” and then add to the project in same hierarchy “Views/App” folder.
To make appropriate changes in html page, you need to login WPF application (http://apps.saasplications.com/wpf/). In “Financials” menu, press “Chart of Accounts” menu. Then in “System” menu, press “Traffic Debug”. You can see both “Request” and “Response” in both text and XML forms.
You need to set “ViewBag.Title” to same menu text as is in WPF application which is “Chart of Accounts”. You can keep “ViewBag.Icon” same as was in “CheckList” but you can change if you want.
In Traffic, you can find Activity name and Style.
Now, you need to bind to that activity in your html page.
For now, your html page (empty) is created. Now you need to add this html page to get it displayed in existing menu list.
You can find that file where existing html pages are added, and that is “FormMapping.xml”. You can add your page at bottom.
You can build and run application. You can see new menu “Chart of Accounts”.
You can see empty “Chart of Accounts” page when you click on new menu.
Here we will explain all menus one by one with examples of "How data is fetched from WPF application to Web Application and saved back to WPF Application from Web application using Genie SDK?".
Vehicle Check is used as safety measure application in which driver has to enter vehicle code/ODO and also check for any issue. If driver see any issue, he must need to report that issue and replace vehicle by finding another vehicle and assigning to himself. Then. he can mark "Vehicle Check Done".
To build Vehicle Check page, we need to see traffic debug and XML request to identify activity name and style.
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.TourRun" data-ex-activitystyle="VehicleCheck"> </div> |
We need to replicate fields in Web application as exist in WPF application after adding static header Vehicle code/rego.
To add static field Rego/License No; use data-ex-bind to "field", and data-ex-fieldid to "Vehicle.RegoLicenceNo".
<div class="input-group" data-ex-bind="field" data-ex-fieldid="Vehicle.RegoLicenceNo"> <label data-ex-attribute="label" class="control-label"></label> <span data-ex-attribute="value" class="form-control-static"></span> </div> |
To add ODO input field; use data-ex-bind to "field" and data-ex-fieldid to "ODO.Start".
<div class="input-group" data-ex-bind="field" data-ex-fieldid="ODO.Start"> <span data-ex-attribute="label" class="input-group-addon">ODO</span> <input data-ex-attribute="value" type="number" class="form-control" min="0"> </div> |
We need to add three tabs Things to Take, Report Issue and Change Driver while making first tab Things to Take as active tab.
<ul id="vehicleCheckTabs" class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"> <a href="#things" id="things-tab" role="tab" data-toggle="tab">Things To Take</a> </li> <li role="presentation"> <a href="#report" role="tab" id="report-tab" data-toggle="tab">Report Isssue</a> </li> <li role="presentation"> <a href="#driverChange" role="tab" id="driverChange-tab" data-toggle="tab">Change Driver</a> </li> </ul> |
Now, we need to add contents/fields to each tab.
<div id="vehicleCheckTabContent" class="tab-content"> </div> |
We need to display special instructions (if exist) in Things to Take tab. To bind with Special Instructions field; use data-ex-bind to"field" and data-ex-fieldid to "SpecialInstructions".
<div id="vehicleCheckTabContent" class="tab-content"> <div role="tabpanel" class="tab-pane active in" id="things" data-ex-bind="field" data-ex-fieldid="SpecialInstructions"> <p style="padding-top: 10px; padding-bottom: 10px" class="col-xs-12" data-ex-attribute="value" data-ex-renderashtml="true"></p> </div> </div> |
In Report Issue tab, user can report any issue and can replace vehicle as well.
<div id="vehicleCheckTabContent" class="tab-content"> <div role="tabpanel" class="tab-pane in" id="report"> </div> </div> |
To report issue we need to create text field to enter issue and then button to report/save issue. To bind field data, use data-ex-fieldid to "Vehicle.Issues.Issue". To bind button to Save method, use type="submit", data-ex-contextobject='Vehicle.Issues', data-ex-bind="method", data-ex-method="Save".
<div class="input-group" data-ex-bind="field" data-ex-fieldid="Vehicle.Issues.Issue"> <input id="issueToReport" x-webkit-speech type="text" class="form-control" placeholder="Enter Issue..." data-ex-attribute="value"> <span class="input-group-btn"> <button id="reportIssue" class="btn btn-default" type="submit" data-ex-contextobject='Vehicle.Issues' data-ex-bind="method" data-ex-method="Save">Report</button> </span> </div> |
Now, we need to list down all vehicles registration number, and show them in drop-down list once user press Get Vehicles button.
To fetch data from service, use data-ex-bind="method" data-ex-method="listReplacementVehicles".
<button class="pull-right btn btn-primary btn-lg" style="margin: 0 5px;" data-ex-bind="method" data-ex-method="listReplacementVehicles"> Get Vehicles </button> |
To select specific Vehicle number, and bind selected field, use data-ex-bind="datafield" data-ex-fieldid="UDefInt" so that selected vehicle is passed to service using field "UDefInt".
<div class="input-group"> <span class="input-group-addon">Select Replacement Vehicle</span> <select class="form-control" data-ex-bind="datafield" data-ex-fieldid="UDefInt" data-ex-populatemethod="listReplacementVehicles" data-ex-autopopulate="0"> </select> </div> |
To apply vehicle change, user need to press Apply Vehicle Change. To apply this we need to bind method to "applyVehicleChange".
<button class="pull-right btn btn-primary btn-lg" data-ex-bind="method" data-ex-method="applyVehicleChange"> Apply Vehicle Change </button> |
Now if you build and run, you can see Vehicle check page.
In last tab, Change Driver, user can assign vehicle using button Assign Me as Replacement with binding to method "assignMeAsReplacementDriver".
<div id="vehicleCheckTabContent" class="tab-content"> <div role="tabpanel" class="tab-pane in" id="driverChange"> <button class="pull-right btn btn-primary btn-lg" data-ex-bind="method" data-ex-method="assignMeAsReplacementDriver"> Assign Me as Replacement </button> </div> </div> |
Now, user can mark both fields Supporting Items Onboard and Vehicle Check Done.
<div class="input-group" data-ex-bind="field" data-ex-fieldid="SupportingItemsOnboard"> <input id="SupportingItemsOnboard" type="checkbox" data-ex-attribute="value" /> <label for="SupportingItemsOnboard" class="form-control" data-ex-attribute="label">Supporting Items Onboard</label> </div> <div class="input-group" data-ex-bind="field" data-ex-fieldid="VehicleCheckDone"> <input id="vehicleCheckComplete" type="checkbox" data-ex-attribute="value" /> <label for="vehicleCheckComplete" class="form-control" data-ex-attribute="label">Vehicle Check Completed</label> </div> |
Manifest application is used to maintain passenger data in which driver on his vehicle pass on to some hotels and is supposed to pick passengers from that hotels. Passenger personal information is also maintained who take ride.
To build Manifest page, we need to see traffic debug and XML request to identify activity name and style.
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.TourRun" data-ex-activitystyle="Manifest"> </div> |
Please note that Manifest app is still in-progress. But still we will explain the fields that are displayed in Manifest app. We will explain how these data fields are bound.
To add Destination field to Manifest app, use data-ex-bind="field" data-ex-fieldid="DestinationId".
<div class="day-info" data-ex-bind="field" data-ex-fieldid="DestinationId"> Destination: <span data-ex-attribute="text"></span> </div> |
To add Vehicle field to Manifest app, use data-ex-bind="field" data-ex- fieldid="Vehicle.RegoLicenceNo".
<div class="day-info" data-ex-bind="field" data-ex- fieldid="Vehicle.RegoLicenceNo"> Vehicle: <span data-ex-attribute="value"></span> </div> |
To add Total Pax field to Manifest app, use data-ex-bind="field" data-ex-fieldid="Pax".
<div class="day-info" data-ex-bind="field" data-ex-fieldid="Pax"> Total Pax: <span data-ex-attribute="value"></span> </div> |
Now we need to add checkbox input field of label Hide Pixed up Pax , and bind field id to "HideCompletedChildren".
<div class="input-group" data-ex-bind="field" data-ex-fieldid="HideCompletedChildren"> <input id="vehicleCheckComplete" type="checkbox" data-ex-attribute="value" /> <label for="vehicleCheckComplete" class="form-control" data-ex-attribute="label">Hide Pixed up Pax</label> </div> |
To get list of hotels, we need to fetch data using data-ex-bind="data" data-ex-populatemethod="listHotelPickups" data-ex-autopopulate="1", and display data in table.
<div class="table-responsive"> <table class="table" id="hotelPickupList" data-ex-bind="data" data-ex-populatemethod="listHotelPickups" data-ex-autopopulate="1"></table> </div> |
Now we driver can press Leave City button once pickup is complete.
<button id="leavingCity" type="button" data-ex-bind="method" data-ex-method="pickupsComplete" class="btn btn-lg btn-primary"> Leaving City </button> |
Then notes can be added using Notes field with binding to "DriverNotes".
<div data-ex-bind="field" data-ex-fieldid="DriverNotes"> <h3>Notes</h3> <textarea data-ex-attribute="value" style="width: 100%; height: 50px; resize: none;"></textarea> <button class="btn btn-primary">Save</button> </div> |
Return Manifest application is opposite to Manifest application. In Manifest, passengers were picked up from hotels but in Return Manifest passengers are dropped off back to their places.
To build Return Manifest page, we need to see traffic debug and XML request to identify activity name and style.
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.TourRun" data-ex-activitystyle="ReturnManifest"> </div> |
Please note that Return Manifest app is still in-progress. But still we will explain the fields that are displayed in Return Manifest app. We will explain how these data fields are bound.
To get list of drop-off locations, we need to fetch data using bindings as follows and display data in table.
<div class="table-responsive"> <table class="table" id="finalDropoffList" data-ex-bind="data" data-ex-populatemethod="listFinalDropoffs"></table> </div> |
To hide drop-off location, we can add checkbox Hide Dropped Off so user can hide or show drop-off location.
<div data-ex-bind="field" data-ex-fieldid="HideCompletedChildren"> <input id="vehicleCheckComplete" type="checkbox" data-ex-attribute="value" /> <label for="vehicleCheckComplete" class="form-control" data-ex-attribute="label">Hide Dropped Off</label> </div> |
Then driver can finish day by pressing button Finished for day and entering ODO meter reading.
<div data-ex-bind="field" data-ex-fieldid="HideCompletedChildren"> <input id="vehicleCheckComplete" type="checkbox" data-ex-attribute="value" /> <label for="vehicleCheckComplete" class="form-control" data-ex-attribute="label">Hide Dropped Off</label> </div> <div data-ex-bind="field" data-ex-fieldid="ODO.Finish"> <span data-ex-attribute="label" class="input-group-addon"></span> <input data-ex-attribute="value" type="number" class="form-control" min="0"> </div> |
As Manifest application is used to maintain passenger data in which driver on his vehicle pass on to some hotels and is supposed to pick passengers from that hotels. Passenger personal information is also maintained who take ride. In Return Manifest passengers are dropped off back to their places.
Confirm Manifest is just used to confirm once correct information is made, otherwise Manifest will be rejected. All other fields are same.
<div> <a href="#" id="confirmManifest" data-ex-bind="method" data-ex-method="confirmManifestAndAvailability"> Confirm Manifest </a> <a href="#" data-ex-bind="method" data-ex-method="rejectManifestAndAvailability"> Reject Manifest </a> </div> |
Menu app is used for Meal selections. Who would be supplier? How many guests are there? What are the selections of menu items? What is the estimated time of arrival?
To build Menu page, we need to see traffic debug and XML request to identify activity name and style.
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.TourRun" data-ex-activitystyle="MealMenu"> </div> |
Please note that Menu app is still in-progress. But still we will explain the fields that are displayed in Menu app. We will explain how these data fields are bound.
To fetch data for all menu items, we need to build request and bind fields and display data in table as follows:
<div> <table class="table" id="mealMenuSelections" data-ex-bind="data" data-ex-populatemethod="listMenuSelections"></table> </div> |
To fetch data for only work meal menu items, we need to build request and bind fields and display data in table as follows:
<div> <table class="table mealMenuSelectionSummary" id="mealMenuSelectionSummary" data-ex-contextobject="WorkMealMenu" data-ex-bind="data" data-ex-populatemethod="publishSelectionsSummary"> </table> </div> |
To add Notes field to Menu app, use data-ex-bind="field" data-ex-fieldid="WorkMealMenu.Notes".
<di data-ex-bind="field" data-ex-fieldid="WorkMealMenu.Notes"> <h3>Notes</h3> <textarea style="width: 100%; height: 50px;" data-ex-attribute="value"></textarea> </di> |
To add ETA field to Menu app, use data-ex-bind="field" data-ex-fieldid="WorkMealMenu.ETA".
<div data-ex-bind="field" data-ex-fieldid="WorkMealMenu.ETA"> <span>ETA</span> <input id="mealMenuEta" tabindex="1" data-ex-attribute="value" type="number" class="form-control" /> </div> |
To add Send Email button to Menu app, specify type="button" data-ex-bind="method" data-ex-method="sendSelectionsEmail".
<button id="passengerNoShowButton" type="button" data-ex-bind="method" data-ex-method="sendSelectionsEmail" class="btn btn-lg btn-primary"> Send Email </button> |
Roster application shows a list of drivers in order they have to perform duties for specific date range.
To build Roster page, we need to see traffic debug and XML request to identify activity name and style.
<ESA> <CreateActivity name="ERP.Person" style="PortalRoster" suppressFields="1"> <Field id="CurrentBranchId" masked="0" /> <Field id="QueryDateRange.From" masked="0" /> <Field id="QueryDateRange.To" masked="0" /> <DataPublication autoPopulate="0" id="driverroster" populateMethod="listDriverRoster" /> <DataPublication autoPopulate="once" id="CurrentBranchComboBox" populateMethod="listBranches" queryMode="single" /> </CreateActivity> </ESA> |
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.TourRun" data-ex-activitystyle="PortalRoster"> </div> |
In Roster app, we simply need two fields; From Date and To Date to enter From and End date respectively. We also need to have List Roster button so when user press it, all drivers will be listed for specified date range.
To pass From and To date to service, we need to bind these fields.
From date is bound to field "QueryDateRange.From" while To date is bound to "QueryDateRange.To". And "datepicker" adapter is used to show calendar to select date.
<div data-ex-bind="field" data-ex-fieldid="QueryDateRange.From"> <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i> From</span> <input type="text" data-ex-attribute="value" data-ex-adapter="datepicker" class="form-control"> </div> <div data-ex-bind="field" data-ex-fieldid="QueryDateRange.To"> <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i> To</span> <input type="text" data-ex-attribute="value" data-ex-adapter="datepicker" class="form-control"> </div> |
To get data from service we added button List Roster when pressed request is made to service so we would have all drivers available.
<button id="listDriverRoster" type="button" data-ex-bind="method" data-ex-method="listDriverRoster"> List Roster </button> |
To display data returned from service, we need to display in table.
<table id="portalRoster" data-ex-bind="data" data-ex-populatemethod="listDriverRoster"></table> |
Cash Count application is used to collect and count cash for Journal batches, find the discrepancy if exist, and reconcile cash based on cash collected and spent.
To build Cash Count page, we need to see traffic debug and XML request to identify activity name and style.
<ESA> <CreateActivity name="ERP.JournalBatch" style="Driver" suppressFields="1"> <Field id="CreatorId" masked="0" /> <Field id="JournalFilter" masked="0" /> <Field id="CurrentBranchId" masked="0" /> <Field id="Status" masked="0" /> </CreateActivity> </ESA> |
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.JournalBatch" data-ex-activitystyle="Driver"> </div> |
Now, we need to get list of journal batches, so user can select any batch and reconcile. We can get data using method "listMyBatchesToReconcile" using data field "PersistentId".
When list of batches are available, then user can select any batch using drop-down list that can be added as follows:
<div data-ex-bind="datafield" data-ex-fieldid="PersistentId" data-ex-populatemethod="listMyBatchesToReconcile"> <label for="PersistentIdField">Run:</label> <select id="PersistentIdField" class="form-control"></select> </div> |
Once you select batch from Journal batches list then can see its status. If Journal batches have different Statuses. A cash batch may be counted for example.
We can display status fields and batch status as follows:
<div id="statusField" data-ex-bind="field" data-fieldid="Status"> <label data-ex-attribute="label"></label> <p data-ex-attribute="text"></p> </div> |
We can also see cash discrepancy using data-fieldid="CashDiscrepancy".
<div id="cashDiscrepancyField" data-ex-bind="field" data-fieldid="CashDiscrepancy"> <label data-ex-attribute="label"></label> <p data-ex-attribute="value" class="form-control-static pull-right"></p> </div> |
Now, we need to get count of each bill of $100, $50, $20, $10, $5, $1.
<div data-ex-bind="field" data-fieldid="BillCount100.Plan"> <label for="count100Field">$100</label> <input id="count100Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> <div data-ex-bind="field" data-fieldid="BillCount50.Plan"> <label for="count50Field">$50</label> <input id="count50Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> <div data-ex-bind="field" data-fieldid="BillCount20.Plan"> <label for="count20Field">$20</label> <input id="count20Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> <div data-ex-bind="field" data-fieldid="BillCount10.Plan"> <label for="count10Field">$10</label> <input id="count10Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> <div data-ex-bind="field" data-fieldid="BillCount5.Plan"> <label for="count5Field">$5</label> <input id="count5Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> <div data-ex-bind="field" data-fieldid="CoinCount200.Plan"> <label for="count2Field">$2</label> <input id="count2Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> <div data-ex-bind="field" data-fieldid="CoinCount100.Plan"> <label for="count1Field">$1</label> <input id="count1Field" tabindex="4" data-ex-attribute="value" type="number" class="form-control" /> </div> |
Here is the Total field which is calculated automatically based on number count of $100, $50, $20, $10, $5, $1.
<div data-ex-bind="field" data-fieldid="TotalBillsAndCoins.Plan"> <label for="totalBillsAndCoinsField">Total:</label> <input id="totalBillsAndCoinsField" data-ex-attribute="value" type="text"/> </div> |
Now we need to reconcile batches based on cash collected and spent.
<div data-ex-bind="field" data-fieldid="TotalCash"> <label for="totalCashField">Cash Collected:</label> <input id="totalCashField" data-ex-attribute="value" type="text"/> </div> <div data-ex-bind="field" data-fieldid="TotalSpent"> <label for="totalSpentField">Cash Spent:</label> <input id="totalSpentField" data-ex-attribute="value" type="text" /> </div> |
Once reconciliation is done, user can mark it by pressing Save button.
<button id="saveButton" tabindex="8" data-ex-bind="method" data-ex-method="MarkCounted"> Save </button> |
When user clicks new menu “Chart of Accounts”, program must display similar structure as displayed below containing tree-view and respective fields. For this project, only “Name” field was required to be displayed. So when user double clicks any leaf-node, program must raise a request to get data of that node from service, and then name of the clicked node must be displayed in “Name” field, then user can make any change to the field, and then changes must be saved so user can view that changes in WPF application.
To build Chart of Accounts page, we need to see the response in traffic debug how tree-view data is returned from service. You will see tree-view data is organized as follows:
<div class="row" data-ex-bind="activity" data-ex-activityname="ERP.GLAccount"> </div> |
You can easily see which data variable “lvChartOfAccounts” you need to bind in your html page to get this all data. So, now you need to make request as follows:
You can debug in browser to see data returned from server when you click on “Chart of Accounts” menu.
Now, you have to build tree-view in JS once data is returned from service. For that, I have added “TreeViewAdapter.js” and referenced in html page as follows:
As we requested data from service using data-ex-bind="data", with back-end view as “DataPublicationView” and model as “DataPublication”, so we have to find which event triggers when data is returned. So I have found that event triggered when data published is “onDataPublished”.
For that event, I have written event handler. And I also found which variable of “DataPublication” model will return all data and that is “$rawXml”.
As you can see from response that all data is encapsulated in Rows tag, so first we need to find “Rows” tag.
Now, we need to loop on Rows children to parse each row and differentiate parent and child items and organize in such a form that each node can have “Attributes” and “Items”. Attributes can have “id”, “value” etc. Items can have further nodes consisting of Attributes and Items. I have also included “ItemsLength” which tells items count. In case of leaf node, “itemsLength” would be zero.
Rows can be parsed as follows:
Further children rows can be parsed using following recursive function.
Once data is formed in tree structure, then we need to display data using html template. For that I have defined two templates: one for parent item and other for child item/leaf node consisting of “li” items with action and label.
To render data, “renderParentItems” function is called on data.
In renderParentItems function, we loop on items and see if itemsLength is greater than zero then use parent template, and also called renderChildItems; otherwise use child template to render node.
Now, if you build and run application, you can see treeview.
Now, the challenge is if you need to find selected item, and get id and type of selected item so that request can be made to genie service to get data for specific node.
For that I have written following code which unselect already selected item, and select current clicked item.
Then I have written click event which triggered when leaf node is selected, then you can get id and type of selected item to pass model function and get data of selected node.
Now, we need to add “Name” field in html page so we can see data returned from service. Also we need to add “Save” button so that changes can be saved using “Save” method.
You can see data changed in Name field was saved and can be viewed in WPF application.