No Results
Search Tips:
- Please consider misspellings
- Try different search keywords
リモートオブジェクトと jQuery Mobile の併用例
Visualforce リモートオブジェクトは、JavaScript フレームワークとうまく「融合」できるように設計されています。次の例は、拡張されていますが単純であり、リモートオブジェクトと jQuery Mobile を使用して取引先責任者のリストを表示し、取引先責任者の追加、編集、および削除を行います。
次の例は Salesforce モバイルパックの jQuery Mobile を使用し、jQuery 用モバイルパックに含まれているサンプルコードに基づいています。リモートオブジェクトと jQuery Mobile により、携帯端末向けの単純な取引先責任者管理ページを簡単に作成できます。
リモートオブジェクトと jQuery Mobile を使用した単純な取引先責任者エディタ
1<apex:page docType="html-5.0" showHeader="false" sidebar="false">
2
3 <!-- Include jQuery and jQuery Mobile from the Mobile Pack -->
4 <apex:stylesheet value="{!URLFOR($Resource.MobilePack_jQuery,
5 'jquery.mobile-1.3.0.min.css')}"/>
6 <apex:includeScript value="{!URLFOR($Resource.MobilePack_jQuery,
7 'jquery-1.9.1.min.js')}"/>
8 <apex:includeScript value="{!URLFOR($Resource.MobilePack_jQuery,
9 'jquery.mobile-1.3.0.min.js')}"/>
10
11 <!-- Remote Objects declaration -->
12 <apex:remoteObjects jsNamespace="RemoteObjectModel">
13 <apex:remoteObjectModel name="Contact" fields="Id,FirstName,LastName,Phone">
14 <!-- Notes is a custom field added to the Contact object -->
15 <apex:remoteObjectField name="Notes__c" jsShorthand="Notes"/>
16 </apex:remoteObjectModel>
17 </apex:remoteObjects>
18
19 <head>
20 <title>Contacts</title>
21 <meta name="viewport"
22 content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
23
24 <script type="text/javascript">
25 var $j = jQuery.noConflict();
26
27 // Config object with commonly used data
28 // This keeps some hard-coded HTML IDs out of the code
29 var Config = {
30 Selectors: {
31 list: '#cList',
32 detailFields: "#fName #lName #phone #notes #error #contactId".split(" ")
33 },
34 Data: {
35 contact: 'contact'
36 }
37 };
38
39 // Get all contacts, and display them in a list
40 function getAllContacts() {
41 $j.mobile.showPageLoadingMsg();
42
43 var c = new RemoteObjectModel.Contact();
44 // Use the 'limit' operator to increase the default limit of 20
45 c.retrieve({ limit: 100 }, function (err, records) {
46 // Handle any errors
47 if (err) {
48 displayError(err);
49 } else {
50 // Empty the current list
51 var list = $j(Config.Selectors.list).empty();
52 // Now add results records to list
53 $j.each(records, function() {
54 var newLink = $j('<a>'+ this.get('FirstName')+ ' ' +
55 this.get('LastName')+ '</a>');
56 newLink.data(Config.Data.contact, this.get('Id'));
57 newLink.appendTo(list).wrap('<li></li>');
58 });
59
60 $j.mobile.hidePageLoadingMsg();
61 list.listview('refresh');
62 }
63 });
64 }
65
66 // Handle the Save button that appears on both
67 // the Edit Contact and New Contact pages
68 function addUpdateContact(e){
69 e.preventDefault();
70
71 var record = new RemoteObjectModel.Contact({
72 FirstName: $j('#fName').val(),
73 LastName: $j('#lName').val(),
74 Phone: $j('#phone').val(),
75 Notes: $j('#notes').val()
76 // Note use of shortcut 'Notes' in place of Notes__c
77 });
78
79 var cId = $j('#contactId').val();
80 if( !cId ) { // new record
81 record.create(updateCallback);
82 } else { // update existing
83 record.set('Id', cId);
84 record.update(updateCallback);
85 }
86 }
87
88 // Handle the delete button
89 function deleteContact(e){
90 e.preventDefault();
91 var ct = new RemoteObjectModel.Contact();
92 ct.del($j('#contactId').val(), updateCallback);
93 }
94
95 // Callback to handle DML Remote Objects calls
96 function updateCallback(err, ids){
97 if (err) {
98 displayError(err);
99 } else {
100 // Reload the contacts with current list
101 getAllContacts();
102 $j.mobile.changePage('#listpage', {changeHash: true});
103 }
104 }
105
106 // Utility function to log and display any errors
107 function displayError(e){
108 console && console.log(e);
109 $j('#error').html(e.message);
110 }
111
112 // Attach functions to the buttons that trigger them
113 function regBtnClickHandlers() {
114 $j('#add').click(function(e) {
115 e.preventDefault();
116 $j.mobile.showPageLoadingMsg();
117
118 // empty all the clic handlers
119 $j.each(Config.Selectors.detailFields, function(i, field) {
120 $j(field).val('');
121 });
122
123 $j.mobile.changePage('#detailpage', {changeHash: true});
124 $j.mobile.hidePageLoadingMsg();
125 });
126
127 $j('#save').click(function(e) {
128 addUpdateContact(e);
129 });
130
131 $j('#delete').click(function(e) {
132 deleteContact(e);
133 });
134 }
135
136 // Shows the contact detail view,
137 // including filling in form fields with current data
138 function showDetailView(contact) {
139 $j('#contactId').val(contact.get('Id'));
140 $j('#fName').val(contact.get('FirstName'));
141 $j('#lName').val(contact.get('LastName'));
142 $j('#phone').val(contact.get('Phone'));
143 $j('#notes').val(contact.get('Notes'));
144 $j('#error').html('');
145 $j.mobile.changePage('#detailpage', {changeHash: true});
146 }
147
148 // Register click handler for list view clicks
149 // Note: One click handler handles the whole list
150 function regListViewClickHandler() {
151 $j(Config.Selectors.list).on('click', 'li', function(e) {
152
153 // show loading message
154 $j.mobile.showPageLoadingMsg();
155
156 // get the contact data for item clicked
157 var id = $j(e.target).data(Config.Data.contact);
158
159 // retrieve latest details for this contact
160 var c = new RemoteObjectModel.Contact();
161 c.retrieve({
162 where: { Id: { eq: id } }
163 }, function(err, records) {
164 if(err) {
165 displayError(err);
166 } else {
167 showDetailView(records[0]);
168 }
169
170 // hide the loading message in either case
171 $j.mobile.hidePageLoadingMsg();
172 });
173 });
174 }
175
176 // And, finally, run the page
177 $j(document).ready(function() {
178 regBtnClickHandlers();
179 regListViewClickHandler();
180 getAllContacts();
181 });
182
183 </script>
184 </head>
185
186 <!-- HTML and jQuery Mobile markup for the list and detail screens -->
187 <body>
188
189 <!-- This div is the list "page" -->
190 <div data-role="page" data-theme="b" id="listpage">
191 <div data-role="header" data-position="fixed">
192 <h2>Contacts</h2>
193 <a href='#' id="add" class='ui-btn-right' data-icon='add'
194 data-theme="b">Add</a>
195 </div>
196 <div data-role="content" id="contactList">
197 <ul id="cList" data-filter="true" data-inset="true"
198 data-role="listview" data-theme="c" data-dividertheme="b">
199 </ul>
200 </div>
201 </div>
202
203 <!-- This div is the detail "page" -->
204 <div data-role="page" data-theme="b" id="detailpage">
205 <div data-role="header" data-position="fixed">
206 <a href='#listpage' id="back2ContactList" class='ui-btn-left'
207 data-icon='arrow-l' data-direction="reverse"
208 data-transition="flip">Back</a>
209 <h1>Contact Details</h1>
210 </div>
211 <div data-role="content">
212 <div data-role="fieldcontain">
213 <label for="fName">First Name:</label>
214 <input name="fName" id="fName" />
215 </div>
216 <div data-role="fieldcontain">
217 <label for="lName">Last Name:</label>
218 <input name="lName" id="lName" />
219 </div>
220 <div data-role="fieldcontain">
221 <label for="phone">Phone:</label>
222 <input name="phone" id="phone"/>
223 </div>
224 <div data-role="fieldcontain">
225 <label for="notes">Notes:</label>
226 <textarea name="notes" id="notes"/>
227 </div>
228
229 <h2 style="color:red" id="error"></h2>
230
231 <input type="hidden" id="contactId" />
232 <button id="save" data-role="button" data-icon="check"
233 data-inline="true" data-theme="b" class="save">Save</button>
234 <button id="delete" data-role="button" data-icon="delete"
235 data-inline="true" class="destroy">Delete</button>
236 </div>
237 </div>
238 </body>
239</apex:page>4 つのリモートオブジェクト操作すべてが使用されていますが、コールバックハンドラは 3 つしかありません。
- getAllContacts() は retrieve() をコールして取引先責任者のリストを読み込み、コールバック用の匿名関数を提供します。コールバックは、エラーがないかチェックし、結果を反復処理してページに追加します。
- 同様に、showDetailView() は retrieve() をコールして詳細ページ用に 1 件の取引先責任者を読み込み、結果は再び匿名関数によって処理されます。
- addUpdateContact() と deleteContact() は、取引先責任者の追加、更新、および削除を処理します。どちらのメソッドも updateCallback() をコールバック関数として渡します。updateCallback() はリモートオブジェクト操作の結果を使用しません。エラーのチェックを行い、エラーをコンソールにログ出力し、getAllContacts() をコールしてページを更新するのみです。