もうひとこと: コードについて
Apex クラスは、Visualforce ページのコントローラで、メソッドの @RemoteAction アノテーションを使用します。このアノテーションを使用すると、Visualforce ページは JavaScript 対応の方法でロジックをラップします。これは、Visualforce Remoting と呼ばれます。
Visualforce Remoting を使用すると、Apex と JavaScript 間を迅速かつ緊密に統合できます。この通信モデルは、従来の Visualforce/Apex MVC パラダイムの同期モデルと異なり、非同期で動作します。そのため、パラメータをコントローラに渡したら、DOM 操作を実行して、モバイルテンプレートやフレームワークを使用してページを作成する前に、レスポンスハンドラ関数から結果を取得し、追加のクライアント側ロジックを記述できます。
Visualforce Remoting は、Salesforce オブジェクトへのサーバ側の直接アクセスを簡素化し、迅速なプラットフォーム開発のための Apex ツール (SOQL や Apex メソッドなど) を使用できるため、Salesforce プラットフォームでのモバイル開発者に最適です。また、ビューステートを処理する必要がないため、ページのパフォーマンスが向上します。
Apex クラス QuickOrderController
このクラスは Visualforce Remoting を使用します。また、このクラスには、倉庫を検索して注文および品目を作成するために Visualforce ページによってコールされるロジックが含まれています。
1global class QuickOrderController{
2 public static List<Merchandise__c> merchandise;
3 public static Line_Item__c quickOrder;
4
5
6 public QuickOrderController(ApexPages.
7 StandardController controller){
8 }
9
10 @RemoteAction
11 global static List<Merchandise__c> findWarehouses(String accId,
12 String merchName, String warehouseDist){
13 merchandise = new List<Merchandise__c>();
14 String queryString = '';
15 String queryName = '%' + merchName + '%';
16
17 Account acc = [Select Location__Longitude__s,
18 Location__Latitude__s, Name, Id
19 from Account where Id =: accId];
20
21 //Finds warehouses nearby if you have location
22 //specified on the Account
23 if(acc.Location__Latitude__s != null &&
24 acc.Location__Longitude__s != null){
25 queryString = 'SELECT Id, (SELECT Id, Name, Quantity__c,
26 Warehouse__r.Name, Warehouse__r.Id,
27 Warehouse__r.Street_Address__c,
28 Warehouse__r.City__c '+
29 'FROM Merchandise__r WHERE Name
30 like :queryName) '
31 +'FROM Warehouse__c WHERE '
32 +'DISTANCE(Location__c, GEOLOCATION('
33 +acc.Location__Latitude__s+','
34 +acc.Location__Longitude__s+'), \'mi\')';
35 if(warehouseDist != null){
36 queryString += ' <'+ warehouseDist;
37 }
38
39 }
40 //If no location defined on the Account, this will run
41 //query against the merchandise name only
42 else {
43 queryString = 'SELECT Id, Name,
44 Location__Longitude__s,
45 Location__Latitude__s, '
46 +'(SELECT Id, Name, Warehouse__r.Name,
47 Quantity__c
48 FROM Merchandise__r WHERE Name
49 like :queryName) '
50 +'FROM Warehouse__c limit 25';
51
52 }
53
54 //This creates a list of merchandise
55 //to display in the search results
56 Warehouse__c[] warehouses = Database.Query(queryString);
57 for(Warehouse__c warehouse : warehouses){
58 Merchandise__c[] merch =
59 warehouse.getSObjects('Merchandise__r');
60 if (merch != null) {
61 for (Merchandise__c m : merch){
62 merchandise.add(m);
63 }
64 }
65 }
66 return merchandise;
67
68 }
69
70 //This remote action creates the invoice for the quick order
71 @RemoteAction
72 global static Line_Item__c createQuickOrder(
73 String accId, String merchandiseId){
74 Invoice__c newInvoice = new Invoice__c();
75 newInvoice.Account__c = accId;
76 insert newInvoice;
77
78 quickOrder = new Line_Item__c();
79 Merchandise__c m = [Select Id, Name from Merchandise__c
80 where Id=: merchandiseId limit 1];
81 quickOrder.Merchandise__c = m.Id;
82 quickOrder.Invoice__c = newInvoice.Id;
83
84 return quickOrder;
85 }
86
87 //This remote action creates the line item related to the
88 //invoice for the quick order
89 @RemoteAction
90 global static Boolean insertQuickOrder(String o, String q){
91 try {
92 Integer quantity = integer.valueof(q);
93
94 Line_Item__c order = new Line_Item__c();
95 /* The order variable being passed in as a param is being
96 passed in the form of a JSON object. You need to use
97 the JSON deserialize method in Apex to convert it
98 into a SObject */
99 order = (Line_Item__c)JSON.deserialize(
100 o, Line_Item__c.class);
101
102 order.Quantity__c = quantity;
103 insert order;
104
105 //Need to requery for the name for the post to chatter
106 //since it wasn't explicitly specified
107 Line_Item__c li = [Select Name, Merchandise__r.Name, Id,
108 Quantity__c, Invoice__c from Line_Item__c
109 where Id =: order.Id];
110
111 FeedItem post = new FeedItem();
112 post.ParentId = aId;
113 post.Body = UserInfo.getName() + ' just created a quick order';
114 post.type = 'LinkPost';
115 post.LinkUrl = '/' + li.Invoice__c;
116 post.Title = li.Merchandise__r.Name + ': ' + li.quantity__c;
117 insert post;
118 } catch(System.Exception ex) {
119 system.debug(ex.getMessage());
120 }
121 return true;
122 }
123
124 //This remote action handles deleting the invoice if
125 //the user doesn't want to insert the line item
126 @RemoteAction
127 global static Boolean goBack(String invoiceId){
128 // Delete created invoice and return to original
129 //search screen
130 Invoice__c cancelledInvoice = [select Id from Invoice__c
131 where Id=: invoiceId];
132 delete cancelledInvoice;
133
134 return true;
135 }
136
137}1FeedItem post = new FeedItem();
2 post.ParentId = aId;
3 post.Body = UserInfo.getName() + ' just created a quick order';
4 post.type = 'LinkPost';
5 post.LinkUrl = '/' + li.Invoice__c;
6 post.Title = li.Merchandise__r.Name + ': ' + li.quantity__c;
7 insert post;Visualforce ページ QuickOrderPage
このページは、ユーザ入力を使用してコントローラをコールし、商品および倉庫情報をユーザに表示します。ユーザが注文を作成する場合、このページはコントローラをコールし、カスタマー取引先に関連付けられている注文を作成して品目を追加します。また、コードはページの最初で Salesforce モバイル設計テンプレートを使用して、ページのスタイル設定も行います。
1<apex:page standardController="Account"
2 extensions="QuickOrderController" docType="html-5.0"
3 standardStylesheets="false" showheader="false" sidebar="false">
4
5 <!--Include stylesheets for the mobile look and feel -->
6 <apex:stylesheet value="{!URLFOR(
7 $Resource.Mobile_Design_Templates,
8 'Mobile-Design-Templates-master/
9 common/css/app.min.css')}"/>
10 <apex:includeScript value="{!URLFOR(
11 $Resource.Mobile_Design_Templates,
12 'Mobile-Design-Templates-master/common/js/
13 jQuery2.0.2.min.js')}"/>
14 <apex:includeScript value="{!URLFOR(
15 $Resource.Mobile_Design_Templates,
16 'Mobile-Design-Templates-master/common/js/
17 jquery.touchwipe.min.js')}"/>
18 <apex:includeScript value="{!URLFOR(
19 $Resource.Mobile_Design_Templates,
20 'Mobile-Design-Templates-master/common/
21 js/main.min.js')}"/>
22
23 <style>
24 /* Default S1 color styles */
25 .list-view-header, .data-capture-buttons a {
26 background: -webkit-linear-gradient(
27 #2a93d5,#107abb);
28 background: linear-gradient(#2a93d5,#107abb);
29 box-shadow: 0 1px 3px rgba(0,0,0,.2),
30 inset 0 1px 0 rgba(255,255,255,.21);
31 color: white;
32 font-weight: bold;
33 }
34
35 #resultPage, #searchPage {
36 padding-bottom: 50px;
37 }
38 </style>また、QuickOrderPage は、Canvas SDK をコールし、パブリッシャーの [登録] ボタンを有効に��て、パブリッシャーウィンドウを閉じます。
1<!-- This needs to be included so the publisher can be used
2 to submit the action -->
3<script type='text/javascript' src='/canvas/sdk/js/publisher.js'></script>1//This method will activate the publish button
2//so the form can be submitted
3Sfdc.canvas.publisher.publish({
4 name: "publisher.setValidForSubmit",
5 payload:"true"});1<script type='text/javascript'>
2 Sfdc.canvas.publisher.subscribe({name: "publisher.post",
3 onData:function(e) {
4 //This subscribe fires when the user hits
5 //Submit in the publisher
6 insertQuickOrder();
7 }});
8</script>1// Success - close the publisher and refresh the feed
2Sfdc.canvas.publisher.publish({name: "publisher.close",
3 payload:{ refresh:"true"}});