Skip to content

Commit 714adc7

Browse files
authored
Merge pull request #9709 from exec-astraea/client-api-updates
Client API updates
2 parents 72b51ee + 000194b commit 714adc7

File tree

12 files changed

+197
-199
lines changed

12 files changed

+197
-199
lines changed

content/en/docs/howto/extensibility/best-practices-javascript-actions.md

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -183,18 +183,17 @@ For information on how to use *Big.js*, consult the [big.js API](https://mikemcl
183183
Use the following code to create objects:
184184

185185
```javascript
186-
mx.data.create({
187-
entity: "MyFirstModule.Cat",
188-
callback: function(object) {
189-
console.log("Object created on server");
190-
},
191-
error: function(error) {
192-
console.error("Could not commit object:", error);
193-
}
194-
});
186+
import { create } from "mx-api/data"
187+
188+
try {
189+
const cat = await create({ entity: "MyFirstModule.Cat" })
190+
console.log("Object created on server:", cat);
191+
} catch (err) {
192+
console.error("Could not commit object:", err);
193+
}
195194
```
196195

197-
For more information on creating objects, consult the [Create](https://apidocs.rnd.mendix.com/10/client/mx.data.html#.create) section of the *Mendix Client API*.
196+
For more information on creating objects, consult the [Create](https://apidocs.rnd.mendix.com/11/client-mx-api/module-mx-api_data.html#.create) section of the *Mendix Client API*.
198197

199198
#### Changing Objects
200199

@@ -288,37 +287,7 @@ Use the following code to employ an asynchronous return for when your nanoflow n
288287
}
289288
```
290289

291-
Many APIs and functions are designed in an asynchronous way, and use callback functions or promises. A JavaScript action expects a promise to be returned. The promise should be resolved with the return value as expected in the action.
292-
293-
#### Understanding Promises
294-
295-
A `Promise` object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
296-
297-
Use the following code to wrap a callback API in a promise:
298-
299-
```javascript
300-
function AskConfirmation(question) {
301-
// BEGIN USER CODE
302-
return new Promise(function (resolve) {
303-
mx.ui.confirmation({
304-
content: question,
305-
handler: function() {
306-
resolve(true);
307-
},
308-
onCancel: function() {
309-
resolve(false);
310-
}
311-
});
312-
});
313-
// END USER CODE
314-
}
315-
```
316-
317-
Explaining the callback code:
318-
319-
* Use the standard Mendix Client to show a confirmation dialog box with an **OK** and a **Cancel** button (the execution of the nanoflow halts until the user clicks one of the buttons)
320-
* The resolve will return a Boolean value, which is used as the return value of the action
321-
* In the nanoflow, the return variable can be used for an alternative flow for confirmation and cancel
290+
Many APIs and functions are designed in an asynchronous way, and use callback functions or [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). A JavaScript action expects a promise to be returned. The promise should be resolved with the return value as expected in the action.
322291

323292
#### Understanding Promise API
324293

content/en/docs/howto/extensibility/build-javascript-actions/write-javascript-github.md

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ To create a JavaScript action that can search for users on GitHub, follow the st
9191
const url = "https://api.github.com/search/users?q=" + query;
9292
const response = await fetch(url); // Fetch returns a promise, gets the url and wait for result
9393
const jsonData = await response.json(); // Transform to JSON
94-
logger.debug("count results", jsonData.total_count); // log to the console a successful result
94+
console.log("count results", jsonData.total_count); // log to the console a successful result
9595
return []; // return an empty list for now...
9696
// END USER CODE
9797
}
@@ -104,6 +104,8 @@ To create a JavaScript action that can search for users on GitHub, follow the st
104104
10. Finally, set a `Promise.all` return to wait for all promises to be resolved before the nanoflow can continue:
105105

106106
```javascript
107+
import { create } from "mx-api/data"
108+
107109
export async function SearchGitHubUsers(query) {
108110
// BEGIN USER CODE
109111
if (!query) {
@@ -112,24 +114,19 @@ To create a JavaScript action that can search for users on GitHub, follow the st
112114
const url = "https://api.github.com/search/users?q=" + query;
113115
const response = await fetch(url);
114116
const jsonData = await response.json();
115-
logger.debug("count", jsonData.total_count);
117+
console.log("count", jsonData.total_count);
116118
const gitHubUsers = jsonData.items.map(createGitHubUser);
117119
return Promise.all(gitHubUsers);
118120

119-
function createGitHubUser(user) {
120-
return new Promise(function (resolve, reject) {
121-
mx.data.create({
122-
entity: "HowTo.GitHubUser",
123-
callback: function(mxObject) {
124-
mxObject.set("login", user.login);
125-
mxObject.set("avatar_url", user.avatar_url);
126-
resolve(mxObject);
127-
},
128-
error: function(e) {
129-
reject("Could not create object:" + error.message);
130-
}
131-
});
132-
});
121+
async function createGitHubUser(user) {
122+
try {
123+
const mxObject = await create({ entity: "HowTo.GitHubUser" });
124+
mxObject.set("login", user.login);
125+
mxObject.set("avatar_url", user.avatar_url);
126+
return mxObject;
127+
} catch(err) {
128+
throw new Error("Could not create object:" + err.message)
129+
}
133130
}
134131
// END USER CODE
135132
}
@@ -140,6 +137,8 @@ To create a JavaScript action that can search for users on GitHub, follow the st
140137
11. The function will only set the `login` and `avatar_url` properties. To make it more flexible, you will make the function discover the available attributes and set them. Extend the domain model with more attributes from the API like so:
141138

142139
```javascript
140+
import { create } from "mx-api/data"
141+
143142
export async function SearchGitHubUsers(query) {
144143
// BEGIN USER CODE
145144
if (!query) {
@@ -148,30 +147,25 @@ To create a JavaScript action that can search for users on GitHub, follow the st
148147
const url = "https://api.github.com/search/users?q=" + query;
149148
const response = await fetch(url);
150149
const jsonData = await response.json();
151-
logger.debug("count", jsonData.total_count);
150+
console.log("count", jsonData.total_count);
152151
const gitHubUsers = jsonData.items.map(createGitHubUser);
153152
return Promise.all(gitHubUsers);
154153

155-
function createGitHubUser(user) {
156-
return new Promise(function (resolve, reject) {
157-
mx.data.create({
158-
entity: "HowTo.GitHubUser",
159-
callback: function(mxObject) {
160-
// Dynamically set attributes
161-
mxObject.getAttributes()
162-
.forEach(function(attributeName) {
163-
var attributeValue = user[attributeName];
164-
if (attributeValue) {
165-
mxObject.set(attributeName, attributeValue);
166-
}
167-
});
168-
resolve(mxObject);
169-
},
170-
error: function(error) {
171-
reject("Could not create object:" + error.message);
172-
}
173-
});
174-
});
154+
async function createGitHubUser(user) {
155+
try {
156+
const mxObject = await create({ entity: "HowTo.GitHubUser" });
157+
// Dynamically set attributes
158+
mxObject.getAttributes()
159+
.forEach(attributeName => {
160+
const attributeValue = user[attributeName];
161+
if (attributeValue) {
162+
mxObject.set(attributeName, attributeValue);
163+
}
164+
});
165+
return mxObject;
166+
} catch(err) {
167+
throw new Error("Could not create object:" + err.message)
168+
}
175169
}
176170
// END USER CODE
177171
}
@@ -196,9 +190,11 @@ To create a JavaScript action that can search for users on GitHub, follow the st
196190

197191
{{< figure src="/attachments/howto/extensibility/build-javascript-actions/write-javascript-github/select-user-entity.png" alt="select user entity" class="no-border" >}}
198192

199-
15. Your final step is updating the code. The new `userEntity` parameter has already been added. In the `mx.data.create` function, set `userEntity` as the `entity` to be created. Then, add some documentation for future reference:
193+
15. Your final step is updating the code. The new `userEntity` parameter has already been added. In the `create` function, set `userEntity` as the `entity` to be created. Then, add some documentation for future reference:
200194

201195
```javascript
196+
import { create } from "mx-api/data"
197+
202198
/*
203199
Searching users on GitHub.com, it could find users via various criteria. This action returns up to 100 results.
204200
@param {string} query - The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub.
@@ -225,31 +221,24 @@ To create a JavaScript action that can search for users on GitHub, follow the st
225221
const url = "https://api.github.com/search/users?q=" + query;
226222
const response = await fetch(url);
227223
const jsonData = await response.json();
228-
logger.debug("count", jsonData.total_count);
229224
const gitHubUsers = jsonData.items.map(createGitHubUser);
230225
return Promise.all(gitHubUsers);
231226

232-
function createGitHubUser(user) {
233-
// Wrap the Mendix Client API in a promise
234-
return new Promise(function (resolve, reject) {
235-
mx.data.create({
236-
entity: userEntity,
237-
callback: function(mxObject) {
238-
// Dynamically set attributes
239-
mxObject.getAttributes()
240-
.forEach(function(attributeName) {
241-
const attributeValue = user[attributeName];
242-
if (attributeValue) {
243-
mxObject.set(attributeName, attributeValue);
244-
}
245-
});
246-
resolve(mxObject);
247-
},
248-
error: function(error) {
249-
reject("Could not create object:" + error.message);
250-
}
251-
});
252-
});
227+
async function createGitHubUser(user) {
228+
try {
229+
const mxObject = await create({ entity: userEntity });
230+
// Dynamically set attributes
231+
mxObject.getAttributes()
232+
.forEach(attributeName => {
233+
const attributeValue = user[attributeName];
234+
if (attributeValue) {
235+
mxObject.set(attributeName, attributeValue);
236+
}
237+
});
238+
return mxObject;
239+
} catch(err) {
240+
throw new Error("Could not create object:" + err.message)
241+
}
253242
}
254243
// END USER CODE
255244
}

content/en/docs/howto/security/best-practices-security.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,13 @@ This authentication option is not available for Published Web Services and can o
139139

140140
If you choose this option, the API will expect a "X-Csrf-Token" HTTP request header to be set on each incoming request. This authentication option is particularly interesting for custom JavaScript and widget implementations.
141141

142-
The session token can be acquired by calling `mx.session.getConfig("csrftoken")` in JavaScript. This method call should be used before each API call to prevent cross-site request forgery (CSRF/XSRF).
142+
The session token can be acquired by calling a Mendix Client API method to get the current CSRF token. This method should be called before each API call in your widget or JavaScript action to prevent cross-site request forgery (CSRF/XSRF).
143+
144+
```javascript
145+
import getCSRFToken from "mx-api/session";
146+
147+
const token = getCSRFToken();
148+
```
143149

144150
#### Authentication Option 3, Custom {#custom}
145151

content/en/docs/howto10/extensibility/best-practices-javascript-actions.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -180,21 +180,22 @@ For information on how to use *Big.js*, consult the [big.js API](https://mikemcl
180180

181181
#### Creating Objects
182182

183-
Use the following code to create objects:
183+
Use the following code to create objects in Mendix version 10.23 and above:
184184

185185
```javascript
186-
mx.data.create({
187-
entity: "MyFirstModule.Cat",
188-
callback: function(object) {
189-
console.log("Object created on server");
190-
},
191-
error: function(error) {
192-
console.error("Could not commit object:", error);
193-
}
194-
});
186+
import { create } from "mx-api/data"
187+
188+
try {
189+
const cat = await create({ entity: "MyFirstModule.Cat" })
190+
console.log("Object created on server:", cat);
191+
} catch (err) {
192+
console.error("Could not commit object:", err);
193+
}
195194
```
196195

197-
For more information on creating objects, consult the [Create](https://apidocs.rnd.mendix.com/10/client/mx.data.html#.create) section of the *Mendix Client API*.
196+
For more information on creating objects, consult the [Create](https://apidocs.rnd.mendix.com/10/client-mx-api/module-mx-api_data.html#.create) section of the *Mendix Client API*.
197+
198+
If you are using Mendix version 10.22 or below, you will need to use [`mx.data.create`](https://apidocs.rnd.mendix.com/10/client/mx.data.html#.create).
198199

199200
#### Changing Objects
200201

@@ -290,11 +291,17 @@ Use the following code to employ an asynchronous return for when your nanoflow n
290291

291292
Many APIs and functions are designed in an asynchronous way, and use callback functions or promises. A JavaScript action expects a promise to be returned. The promise should be resolved with the return value as expected in the action.
292293

294+
Explaining the callback code:
295+
296+
* Use the standard Mendix Client to show a confirmation dialog box with an **OK** and a **Cancel** button (the execution of the nanoflow halts until the user clicks one of the buttons)
297+
* The resolve will return a Boolean value, which is used as the return value of the action
298+
* In the nanoflow, the return variable can be used for an alternative flow for confirmation and cancel
299+
293300
#### Understanding Promises
294301

295-
A `Promise` object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
302+
If you are using Mendix version 10.22 or below, you will need to use promises. A `Promise` object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
296303

297-
Use the following code to wrap a callback API in a promise:
304+
Use the following code in Mendix versions 10.23 or below to wrap a callback API in a promise:
298305

299306
```javascript
300307
function AskConfirmation(question) {
@@ -314,12 +321,6 @@ function AskConfirmation(question) {
314321
}
315322
```
316323

317-
Explaining the callback code:
318-
319-
* Use the standard Mendix Client to show a confirmation dialog box with an **OK** and a **Cancel** button (the execution of the nanoflow halts until the user clicks one of the buttons)
320-
* The resolve will return a Boolean value, which is used as the return value of the action
321-
* In the nanoflow, the return variable can be used for an alternative flow for confirmation and cancel
322-
323324
#### Understanding Promise API
324325

325326
This function uses the Fetch API:

0 commit comments

Comments
 (0)