Sample List of Products for an Order We've created a sample HTML5 document that can be opened within Mobile CRM application. It is a list of products associated with an order. Order DetailsForm now contains one more tab of type IDocumentView. OrderDetails.htm file is then displayed on the IFrame of DocumentView. When the document is opened, it loads a list of all products using Resco JavaScriptBridge and fetch.execute() method. Products are presented to user through our custom JavaScript control, AdvancedList. User can click on a product listed in the AdvancedList and modify the amount of products associated with an Order by clicking/taping the Add or Remove buttons. For purpose of this sample, we decided to use JQueryMobile to simplify the process of designing the page. Let’s take a look at the structure of html document and a few lines of JavaScript code, providing the whole functionality of the page. First, we include references to JavaScript libraries to the head section of the html document: <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" /> <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script> <script src="advancedList.js"></script> <script src="JSBridge.js"></script> Then the html document alone. It is really simple. As we are using JQueryMobile, the most of the work is done by the JQueryMobile library itself. The largest part of the html structure is definition of two templates that we will use for AdvancedList control. One template is for selected item of the list, the second is the general template for all the other items listed. <div id="mainPage" data-role="page"> <div class="content" /> <!-- template for AdvancedList --> <div id="person-unselected" data-list-template="person-template"> <table> <tr> <td style="width: 50px; text-align: center"> <span id="quantity" data-source-member="3"></span> </td> <td width="*" style="vertical-align: top; padding-left: 20px"> <span data-source-member="0"></span><br /> <br /> <p style="font-size: 14px"> Price: <span data-source-member="1" style="font-weight: bold"></span> $ <br /> </p> </td> </tr> </table> </div><!-- /template --> <!-- selected template for AdvancedList --> <div id="person-selected" data-list-template="person-template"> <table> <tr> <td style="width: 50px; text-align: center"> <span id="quantity" data-source-member="3"></span> </td> <td width="*" style="vertical-align: top; padding-left: 20px"> <span data-source-member="0"></span><br /> <br /> <p style="font-size: 14px"> Price: <span data-source-member="1" style="font-weight: bold"></span> $ <br /> </p> </td> </tr> <tr> <td></td> <td style="padding-left: 15px"> <div data-role="controlgroup" data-type="horizontal" data-mini="true" style="padding-top: 15px"> <a data-role="button" data-icon="plus" data-listbutton="true" data-buttonname="add">Add</a> <a data-role="button" data-icon="minus" data-listbutton="true" databuttonname="remove">Remove</a> </div> </td> </tr> </table> </div><!-- /selected template --> </div><!-- /page --> Last but not least, there are 3 methods written in JavaScript: - LoadDataSource method loads the data from CRM and sets it as a datasouce for JavaScript AdvancedList control. - ProductBtnClicked method handles the clicks on Add/Remove buttons, so the number of products for order is immediately reflected in the order entity - Initialize method Initialize method: 1. get the templates from html DOM using JQuery var template = $("#person-unselected"); var selectedTemplate = $("#person-selected"); 2. Instantiate and initialize the list control. Add templates to the list, set the index of the selected template and initialize a filter productList = new advancedList("list-people", false); productList.addTemplate(template); productList.addTemplate(selectedTemplate); productList.selectedTemplateIndex = 1; productList.useFilter = true; productList.filterPlaceholder = "Type product name to filter products..."; 3. Assign event handlers. One for button clicks and one for row validating. Row validating event is fired each time the data are bound to the item. You can modify the value that is finally presented to the user. In this case, when the quantity property of product entity is zero, no digit is shown. productList.listButtonClicked = productBtnClicked; productList.rowDataValidating = function(data, dataSourceMember){ if (dataSourceMember == 3 && data == 0){ return ""; } } 4. Add the list control to the DOM and hide the template definitions productList.appendTo($(".content")); // hide templates defined in html template.hide(); selectedTemplate.hide(); 5. If ownerID is in correct format, call loadDataSource method in #mainPage init event. Also handle the size of the list there. var ownerId = location.search; if (ownerId != null && ownerId.length > 32) { $('#mainPage').live('pageinit', function(event){ ownerId = ownerId.replace('?', '') loadDataSource(ownerId); $("#mainPage").width($(window).width() - 40); }); } $(window).resize(function() { $("#mainPage").width($(window).width() - 40); }); LoadDataSource method: As mentioned in the 'Implementing the CRM Fetch request from Javascript' section (refer to the MobileCRM documentation), we call bridge methods to get the data. For more info refer to that section. In this case we are interested in product entities, we want attributes 'name', 'price', 'productId' and from linkedentity salesorderdetails we need quantity attribute. In Callback of fetch.execute() method, we simply set the data obtained ,as a datasource of our list. function loadDataSource(orderId) { // fetch the data var fetch = new MobileCRM.FetchXml.Fetch(); var entity = new MobileCRM.FetchXml.Entity("product"); fetch.entity = entity; entity.attributes = [new MobileCRM.FetchXml.Attribute('name'), new MobileCRM.FetchXml.Attribute('price'), new MobileCRM.FetchXml.Attribute('productid')]; entity.order = [new MobileCRM.FetchXml.Order('name')]; if (orderId != null && orderId.length > 32) { var linkentity = new MobileCRM.FetchXml.LinkEntity("salesorderdetail"); linkentity.attributes = [new MobileCRM.FetchXml.Attribute('quantity')]; linkentity.from = "productid"; linkentity.to = "productid"; linkentity.linktype = "outer"; linkentity.filter = { conditions: [{ attribute: "salesorderid", operator: "eq", value: orderId}] }; entity.linkentity = [linkentity]; } fetch.execute(function (res) { window.productList.setDataSource(res); }, function (err) { alert(err); }, null); } ProductBtnClicked method: When a user selects an item from the list, they can click on the add or remove buttons to set the amount of products for an order. This is handled in productBtnClicked callback. When the amount changes, we simply change the label showing the number of products selected and using Mobile CRM bridge we notify the Mobile CRM that the amount of products has changed. function productBtnClicked(data, senderName, template) { var qnty = data[3] === undefined ? 0 : data[3]; if (senderName === "add") { qnty++; } else if (qnty > 0) { qnty--; } data[3] = qnty; var txtQnty = qnty == 0 ? "" : qnty; $("#quantity", template).text(txtQnty); MobileCRM.bridge.command("setProductQuantity", data[2] + ":" + qnty); } That’s it. As you can see, the implementation of this html form for picking products was easy using Resco Mobile CRM Bridge. Go, try it by yourself—with HTML5 and JavaScript, you can greatly improve the visual appearance of the Mobile CRM application.
© Copyright 2024