CRUD examples
- Last Updated: October 21, 2024
- 13 minute read
- OpenEdge
- Version 12.2
- Documentation
const progress = require("@progress/jsdo-core").progress;
const options = {
catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json",
serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/",
authenticationModel: "anonymous"
};
let session,
jsdo;
// A JSDOSession is how you connect to a service. JSDOs use the connections made by
// JSDOSessions to get data.
progress.data.getSession(options).then((object) => {
// getSession() returns an object that has three properties: jsdosession, result, and info
console.log("The result of getSession() is: " + object.result);
console.log("The JSDOSession is connected to the service at: " + object.jsdosession.serviceURI);
session = object.jsdosession;
// A JSDO is a representation of a table. fill() reads records from the service
jsdo = new progress.data.JSDO({name: "Customer"});
return jsdo.fill();
})
.then((object) => {
let rec;
// fill() returns an object that has three properties: jsdo, success, and request
console.log("The result of fill() is: " + object.success);
console.log("The resulting HTTP status code returned is: " + object.request.xhr.status);
// After a fill(), you can read, modify, and delete records and then send the changes
// back to the service via saveChanges().
// You can iterate through the records via a foreach on the JSDO's temp-table, which
// will return a record object with the appropriate fields in the data property
jsdo.ttCustomer.foreach((customer) => {
if (customer.data.SalesRep === "BBB") {
console.log("The SalesRep BBB handles the customer: " + customer.data.Name);
rec = customer;
}
});
// You can update a record just by modifying any of its fields
rec.data.Balance = rec.data.Balance + 1500;
// You can also use assign() to overwrite a record
jsdo.ttCustomer.foreach((customer) => {
if (customer.data.Name === "All Sports") {
// If you do not specify a value for a field, it will be overwritten to be null
customer.assign({
Name: 'All Sports',
SalesRep: 'R2D2',
Balance: '1337',
State: 'MN'
});
}
});
// add() creates a record
jsdo.ttCustomer.add({
Name: 'Robert Good',
SalesRep: 'NS',
Balance: '1337',
State: 'MA',
});
// remove() deletes a record
jsdo.ttCustomer.foreach((customer) => {
if (customer.data.Name === "Bobby Bad") {
customer.remove();
console.log("This customer was deleted: " + customer.data.Name);
}
});
// All of the changes so far are just local until you send them back to the server
// via a call to saveChanges(). saveChanges() also updates the local records in the jsdo.
return jsdo.saveChanges();
})
.then((object) => {
// saveChanges() returns an object that has three properties: jsdo, success, and request
console.log("The result of saveChanges() is: " + object.success);
// The local records are already updated but you can pass a filter to fill() to only get
// a subset of the records
return jsdo.fill('Balance = 1337');
})
.then((object) => {
jsdo.ttCustomer.foreach((customer) => {
console.log("We edited this customer: " + customer.data.Name);
});
// Always clean up your session afterwards!
return session.invalidate();
})
.then((object) => {
// invalidate() returns an object that has three properties: jsdo, result, and request
console.log("The result of invalidate() is: " + object.result);
});
Event example
// This is a sample of how to use event handlers.
const progress = require("@progress/jsdo-core").progress;
const options = {
catalogURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/static/CustomerService.json",
serviceURI: "https://oemobiledemo.progress.com/OEMobileDemoServices/",
authenticationModel: "anonymous"
};
let session,
jsdo;
// Here is where we define all of our event handlers.
// Please note that the JSDO is passed to every event handler.
function beforeFill(jsdo) {
console.log('In beforeFill()');
console.log('The name of the table of the JSDO is: ' + jsdo.name);
}
function afterFill(jsdo) {
console.log('In afterFill()');
}
function beforeUpdate(jsdo) {
console.log('In beforeUpdate()');
}
function afterUpdate(jsdo) {
console.log('In afterUpdate()');
}
function beforeSaveChanges(jsdo) {
console.log('In beforeSaveChanges()');
}
function afterSaveChanges(jsdo) {
console.log('In afterSaveChanges()');
}
progress.data.getSession(options).then((object) => {
session = object.jsdosession;
jsdo = new progress.data.JSDO({name: "Customer"});
// Here is where we subscribe all of our event handlers
jsdo.subscribe('beforeFill', beforeFill);
jsdo.subscribe('afterFill', afterFill);
jsdo.subscribe('beforeUpdate', beforeUpdate);
jsdo.subscribe('afterUpdate', afterUpdate);
jsdo.subscribe('beforeSaveChanges', beforeSaveChanges);
jsdo.subscribe('afterSaveChanges', afterSaveChanges);
console.log("Initial call to fill()");
return jsdo.fill();
})
.then((object) => {
let rec;
console.log('In the success handler of fill()');
console.log("Initial update of a record")
jsdo.ttCustomer.foreach((customer) => {
if (customer.data.Name === "All Sports") {
customer.assign({
Name: 'All Sports',
SalesRep: 'R2D2',
Balance: '1337',
State: 'MN'
});
}
});
console.log("Initial call to saveChanges()");
return jsdo.saveChanges();
})
.then((object) => {
console.log('In the success handler of saveChanges()');
// Always clean up your session afterwards!
return session.invalidate();
});
// This is the output of this program when run:
// Initial call to fill()
// In beforeFill()
// The name of the table of the JSDO is: Customer
// In afterFill()
// In the success handler of fill()
// Initial update of a record
// Initial call to saveChanges()
// In beforeSaveChanges()
// In beforeUpdate()
// In afterUpdate()
// In afterSaveChanges()
// In the success handler of saveChanges()Create operation
Call the add() method on a JSDO
table reference to create a new record in JSDO memory. The fields of the new record
contain the values specified and passed to the method. For any fields whose values
you do not provide, the method provides default values taken from the Data Object
schema in the Data Service Catalog.
When each invocation of the add()
method completes, the new record becomes the working record for the associated table
and the JSDO marks this record as a new record for pending creation on the server.
(Note that if the table has child tables, a working record is not set for these
child tables.)
To synchronize the server database with new records you have created
in JSDO memory without using a Submit operation, you call saveChanges() by passing either an empty parameter list to the method
or a single parameter value of false. This
executes the OpenEdge ABL server routine that implements the Data Object Create
operation once for each newly created record in JSDO memory. In addition, for any
other changed records in JSDO memory, this call also executes the server routine
that implements the associated Delete or Update operation once for each associated
record change.
When you call the saveChanges()
method, if jQuery Promises are supported in your environment, it returns a Promise
object on which you can register callbacks to handle completion of all record-change
operations that it has invoked. Otherwise, you can subscribe event callbacks to
handle the results of these operations.
Operation results are returned as follows:
- For each Create operation that completes, the JSDO fires an
afterCreateevent to execute any callbacks you have subscribed to handle that event. The JSDO also fires anyafterDeleteandafterUpdateevents to execute any callbacks you have subscribed to handle these events. - After all record-change operations complete, the JSDO fires an
afterSaveChangesevent to execute any callbacks you have subscribed to handle that event. In addition, any returned Promise object executes the Promise callbacks that you have registered, depending on the combined operation results. (Note that the signatures of all Promise callbacks are identical to the signature of theafterSaveChangesevent callback.)
After the saveChanges() method and
all resource operations that it has invoked successfully complete, no working
records are set for the tables in the JSDO.
autoApplyChanges
property has the default value of true, any newly
created record is automatically deleted from JSDO memory on the client.Read operation
To load data into JSDO memory on the client, you call the fill() method on the JSDO, passing an optional
parameter to specify selection criteria as either an object or a string. This
executes the ABL server routine that implements the Data Object Read operation. Each
time fill() is called, all records currently in
JSDO memory are cleared and replaced by the records returned by the method.
When you access a Progress Data Service from the Telerik Platform and the
JSDO dialect of the Kendo UI DataSource calls fill() on its JSDO, the DataSource passes an object parameter to the
method. This object contains properties specified according to DataSource
requirements to select, order, and organize the return of the records from the
server. The Data Object resource on the server then receives the DataSource
selection criteria specified by this object in the form of a Progress-defined JSON
Filter Pattern (JFP). Note that the resource Read operation must be programmed to
handle this JFP according to the requirements of the specific Progress Data Object
Service. For more information, see the description of the fill( ) method.
If you are calling this method yourself, you can use a string to specify the
selection criteria, again, according to the requirements of the Data Object resource
whose data you are reading. If you do not pass a parameter to fill(), the records returned to the client depend
entirely on the implementation of the resource Read operation. For more information,
see the description of the fill( ) method.
When you call the fill() method, if
jQuery Promises are supported in your environment, it returns a Promise object on
which you can register callbacks to handle completion of the Read operation that it
executes. Otherwise, you can subscribe event callbacks to handle the results of the
Read operation:
Operation results are returned as follows:
- The JSDO fires an
afterFillevent for any callbacks you have subscribed to handle the event. - Any returned Promise object executes the Promise callbacks that you have registered, depending on the operation results.
Note that before any callbacks execute, if the Read operation completes successfully, the working record for each JSDO table reference is set to its first record returned, depending on any active parent-child relationships. Thus for each child table reference, the first record is determined by its relationship to the related working record in its parent.
Update operation
To modify an existing record in JSDO memory on the client, you can
call the assign() method to assign values to one
or more fields of either a working record or a specific record in JSDO memory, or
you can assign a value directly to the field of a working record. Using the assign() method, you set the values of fields to be
updated in an object that you pass as a parameter to the method.
You can call the assign() method
on:
- A table reference on the JSDO that has a working record, as in the example below
- A specific
progress.data.JSRecordobject reference
When the assign() method
completes, any working record settings that existed prior to calling the method
remain unchanged.
You can also assign a value directly to a single field of a JSDO working record as follows:
Syntax
|
Where:
- jsdo-ref
- The reference to a JSDO, and if the JSDO contains only a single table, an implied reference to any working record that is set for that table.
- table-ref
- A table reference with the name of a table in jsdo-ref memory that has a working record.
- field-ref
- A field reference on a table-ref with the name and value of a field in the working record of the referenced table.
- value
- The value to set the field referenced by field-ref.
After either a successful call to the assign() method or a successful assignment to a field-ref of a working record, the JSDO marks the
affected record for pending update on the server.
data property of a table-ref; use field-ref on the
data property only to read the referenced
field value. Writing field values using the data
property does not mark the record for pending update on the server, nor does it
initiate a re-sort the record in JSDO memory according to any order you have
established using the autoSort property. For more
information, see the description of the data property. To mark a record for
pending update and automatically re-sort the record according to the autoSort property, you must assign a record field
value using one of the mechanisms described above.To synchronize the server database with existing records you have
updated in JSDO memory without using a Submit operation, you call saveChanges() by passing either an empty parameter
list to the method or a single parameter value of false. This executes the OpenEdge ABL server routine that implements
the Data Object Update operation once for each updated record in JSDO memory. In
addition, for any other changed records in JSDO memory, this call also executes the
server routine that implements the associated Create or Delete operation once for
each associated record change.
saveChanges() method invoked without Submit groups invocation of the
associated resource operations in the order of 1) all Delete operations, 2) all
Create operations, and 3) all Update operations, and invokes each such operation one
record at a time over the network.When you call the saveChanges()
method, if jQuery Promises are supported in your environment, it returns a Promise
object on which you can register callbacks to handle completion of all record-change
operations that it has invoked. Otherwise, you can subscribe event callbacks to
handle the results of these operations.
Operation results are returned as follows:
- For each Update operation that completes, the JSDO fires an
afterUpdateevent to execute any callbacks you have subscribed to handle that event. The JSDO also fires anyafterCreateandafterDeleteevents to execute any callbacks you have subscribed to handle these events. - After all record-change operations complete, the JSDO fires an
afterSaveChangesevent to execute any callbacks you have subscribed to handle that event. In addition, any returned Promise object executes the Promise callbacks that you have registered, depending on the combined operation results. (Note that the signatures of all Promise callbacks are identical to the signature of theafterSaveChangesevent callback.)
After the saveChanges() method and
all resource operations that it has invoked successfully complete, no working
records are set for the tables in the JSDO.
autoApplyChanges
property has the default value of true, any
updated record has its changes automatically backed out from JSDO memory on the
client.Delete operation
To delete an existing record from JSDO memory on the client, you
call the remove() method on a JSDO table
reference.
You can call the remove() method
on:
- A table reference on the JSDO that has a working record
- A specific
progress.data.JSRecordobject reference, as in the example below
When the remove() method
completes, no working record is set for the associated table or any of its child
tables.
After either a successful call to the remove() method, the JSDO marks the affected record for pending
deletion on the server.
To synchronize the server database with existing records you have
deleted in JSDO memory without using a Submit operation, you call saveChanges() by passing either an empty parameter
list to the method or a single parameter value of false. This executes the OpenEdge ABL server routine that implements
the Data Object Update operation once for each deleted record in JSDO memory. In
addition, for any other changed records in JSDO memory, this call also executes the
server routine that implements the associated Create or Update operation once for
each associated record change.
saveChanges() method invoked without Submit groups invocation of the
associated resource operations in the order of 1) all Delete operations, 2) all
Create operations, and 3) all Update operations, and invokes each such operation one
record at a time over the network.When you call the saveChanges()
method, if jQuery Promises are supported in your environment, it returns a Promise
object on which you can register callbacks to handle completion of all record-change
operations that it has invoked. Otherwise, you can subscribe event callbacks to
handle the results of these operations.
Operation results are thus returned as follows:
- For each Delete operation that completes, the JSDO fires an
afterDeleteevent to execute any callbacks you have subscribed to handle that event. The JSDO also fires anyafterCreateandafterUpdateevents to execute callbacks you have subscribed to handle these events. - After all record-change operations complete, the JSDO fires an
afterSaveChangesevent to execute any callbacks you have subscribed to handle that event. In addition, any returned Promise object executes the Promise callbacks that you have registered, depending on the combined operation results. (Note that the signatures of all Promise callbacks are identical to the signature of theafterSaveChangesevent callback.)
After the saveChanges() method and
all resource operations that it has invoked successfully complete, no working
records are set for the tables in the JSDO.
autoApplyChanges
property has the default value of true, any
deleted record is restored to JSDO memory on the client.Submit operation
To send multiple record changes over the network in a single request, you:
- Use the same mechanisms to create, update, and delete records in JSDO memory as described in this topic for the Create, Update, and Delete operations.
- Call the
saveChanges()method using the Submit operation by passing it a parameter value oftrue.
When you call saveChanges(true) to
synchronize pending changes with the server database, this executes the OpenEdge ABL
server routine that implements the Data Object Submit operation. This operation
processes all pending record changes sent from the client in a single network
request and returns the results of all these changes from the server in a single
network response.
Note that this Submit operation is supported only for OpenEdge Data
Object Services, where the Data Object is implemented for a ProDataSet resource with
one or more temp-tables that supports before-imaging. This method call relies on
client before-image data to identify all pending record changes for the network
request since the last invocation of the fill() or
saveChanges() method on the JSDO. The server
then relies on the before-image data to identify and process each record change
according to its type. If a ProDataSet resource and the JSDO that accesses it are
not defined to support before-image data, making this call to saveChanges() raises an exception.
When you call the saveChanges()
method to invoke a Submit operation on a supported resource, if jQuery Promises are
supported in your environment, it returns a Promise object on which you can register
callbacks to handle the results for all record changes in the request. Otherwise,
you can subscribe event callbacks to handle the results of the request.
Operation results are thus returned as follows:
- For each record change that the Submit operation completed, the
JSDO fires an
afterDelete,afterCreate, andafterUpdateevent for each record change of the corresponding type in order to execute any callbacks you have subscribed to handle these events. - The JSDO fires an
afterSaveChangesevent to execute any callbacks you have subscribed to handle that event. In addition, any returned Promise object executes the Promise callbacks that you have registered, depending on the overall Submit operation results. (Note that the signatures of all Promise callbacks are identical to the signature of theafterSaveChangesevent callback.)
After the saveChanges() method
completes a Submit operation successfully, no working records are set for the tables
in the JSDO.
autoApplyChanges property has the default value of true, each record change is automatically accepted or
rejected in JSDO memory based on the presence of an error string that can be
returned by calling the JSDO getErrorString()
method on the record. If you want to accept and reject record changes to synchronize
with any server transaction that handles for the Submit operation, you must set
autoApplyChanges to false and call the appropriate accept*Changes() or reject*Changes()
method to handle the results.