Using the EntityService from JavaScript
How to access items in JavaScript via the EntityService API.
The EntityService
is a standalone XHR (XMLHttpRequest) library for creating, fetching, saving, and deleting Sitecore entities. The library is /sitecore/shell/client/Services/Assets/lib/entityservice.js
.
This topic describes:
The EntityService has many utilities and helpers that assist in the data transaction between the front end and back end. For example:
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.createEntity.should.be.a.type( "function" ); peopleService.fetchEntity.should.be.a.type( "function" ); peopleService.fetchEntities.should.be.a.type( "function" ); peopleService.loadMetadata.should.be.a.type( "function" );
The structure of an entity object is based on metadata (a schema). The EntityService
requests this metadata only once from the server, using the OPTIONS request.
This example shows how you instantiate the EntityService and create an entity:
An
EntityService
is instantiated.When the
EntityService
is asked to execute any server related request (createEntity, fetchEntity, and so on), the supplied URL is accessed with anOPTIONS
request. All subsequent requests are queued until the server responds with a valid metadata object.After the metadata object is returned, it is attached to the context
EntityService
and all entities can be validated and sanitized based on this metadata.The following code examples are based on this metadata:
var metadata = { "entity": { "key": "ItemID", "properties": [ { "key": "id", "datatype": "number" }, { "key": "ItemID", "datatype": "guid" }, { "key": "isActive", "datatype": "boolean" }, { "key": "balance", "datatype": "string" }, { "key": "picture", "datatype": "string" }, { "key": "age", "datatype": "number" }, { "key": "name", "datatype": "string" }, { "key": "gender", "datatype": "string" }, { "key": "company", "datatype": "string" }, { "key": "email", "datatype": "email" }, { "key": "phone", "datatype": "string" }, { "key": "address", "datatype": "string" }, { "key": "about", "datatype": "string" }, { "key": "registered", "datatype": "date" }, { "key": "latitude", "datatype": "number" }, { "key": "longitude", "datatype": "number" }, { "key": "subscribed", "datatype": "string" }, { "key": "children", "datatype": [ { "properties": [ { "key": "name", "datatype": "string" } ] } ] }, { "key": "tags", "datatype": [ "string" ] } ] } };
Entity represents an Entity client side
Constructor
EntityService.Entity ( sanitizedData, entityServiceSchema, options )
Parameters
sanitizedData: object. An object that meets has been validated by the schema
entityServiceSchema: object. The entity schema
options: object. The entity options
Returns
Entity: an entity
You create an entity by passing an object, setting the path in the Sitecore content tree where you want the item to be created, and calling the execute
method:
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); var aNewGuy = { name: "David", isActive: "true", gender: "male" }; peopleService.createEntity( aNewGuy ).then( function ( david ) { david.should.be.an.instanceOf( EntityService.Entity )}; david.isNew.should.be.false; david.ItemID.should.not.be.empty; david.name.should.eql( "David" ); david.isActive.should.eql( true ); david.gender.should.eql( "male" ); /** * ... and because not all of the key/values for this `Entity` were given based on the * `peopleService` end point metadata, they will still be added to the `Entity`. Their default * values are also based on the metadata. */ david.should.have.a.property( "id", null ); david.should.have.a.property( "balance", null ); david.should.have.a.property( "picture", null ); david.should.have.a.property( "age", null ); david.should.have.a.property( "company", null ); david.should.have.a.property( "email", null ); david.should.have.a.property( "phone", null ); david.should.have.a.property( "address", null ); david.should.have.a.property( "about", null ); david.should.have.a.property( "registered" ); david.should.have.a.property( "latitude", null ); david.should.have.a.property( "longitude", null ); david.should.have.a.property( "subscribed", null ); david.should.have.a.property( "children", null ); david.should.have.a.property( "tags", null ); done(); } ).fail( done );
You create a dirty entity without a call to the server by not giving an object to the createEntity
method. All dirty entities are considered new. You can check this with the isNew
property.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.createEntity().then( function ( david ) { david.isNew.should.be.true; done(); } ).fail( done );
You fetch a single entity with the fetchEntity
method, giving the entity id/guid. fetchEntity returns a query so you need to call execute.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "951c3e2e-02e8-4bbc-bbc8-e69ada95e670" ).execute().then( function ( cooley ) { cooley.name.should.eql( "Queen Cooley" ); done(); } ).fail( done );
You fetch all entities based on the given URL with the fetchEntities
method.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntities().execute().then( function ( people ) { people.should.be.an.Array.with.a.lengthOf( 3 ); people[ 0 ].should.be.an.instanceOf( EntityService.Entity ); people[ 1 ].should.be.an.instanceOf( EntityService.Entity ); people[ 2 ].should.be.an.instanceOf( EntityService.Entity ); people[ 0 ].isValid().should.be.ok; people[ 1 ].isValid().should.be.ok; /* * The data of people[ 2 ] has been intentionally made invalid */ people[ 2 ].isValid().should.not.be.ok; done(); } ).fail( done );
You must fetch or create an entity before you can save it.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "951c3e2e-02e8-4bbc-bbc8-e69ada95e670" ).execute().then( function ( cooley ) { cooley.should.be.an.instanceOf( EntityService.Entity ); cooley.name = "Mrs Queen Cooley"; cooley.save().then( function ( savedCooley ) { savedCooley.name.should.eql( "Mrs Queen Cooley" ); done(); } ).fail( done ); } ).fail( done ); Each time you save an Entity, it will trigger a ‘save’ event that you can listen for: ( entity.on(’save’, callback) ).
You must fetch or create an entity before you can destroy it.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "951c3e2e-02e8-4bbc-bbc8-e69ada95e670" ).execute().then( function ( cooley ) { cooley.should.be.an.instanceOf( EntityService.Entity ); cooley.destroy().then( function () { done(); } ).fail( done ); } ).fail( done );
A dirty entity is an entity you create in browser memory without saving it. This is useful, for example, if you are waiting for user input.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.createEntity().then( function ( aNewDirtyEntity ) { /* At this point `aNewDirtyEntity` has not been saved */ aNewDirtyEntity.should.be.an.instanceOf( EntityService.Entity ); aNewDirtyEntity.name = "Queen"; /* After modifying the dirty item, now we save it */ aNewDirtyEntity.save().then( function () { done(); } ).fail( done ); } );
Checking if an entity is dirty
You check if an entity has not been saved (it is “dirty”) with the isNew property:
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.createEntity().then( function ( guy ) { guy.isNew.should.be.true; done(); } ).fail( done ); When the origin of an Entityis is the server, isNew is always false. var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.createEntity( { name: "guy" } ).then( function ( guy ) { /* * `guy` is technically from the server because we are creating a new `Entity` by giving an * object to the `createEntity` method. */ guy.isNew.should.be.false; done(); } ).fail( done );
There are situations where you need to retrieve the data stored in an entity as raw JSON without any of the additional methods and properties. The following method is used internally to retrieve the data that is sent to the server:
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "951c3e2e-02e8-4bbc-bbc8-e69ada95e670" ).execute().then( function ( queen ) { var queenAsJson = queen.json(); queen.should.be.an.instanceOf( EntityService.Entity ); queenAsJson.should.be.an.instanceOf( Object ); queenAsJson.should.not.be.an.instanceOf( EntityService.Entity ); done(); } ).fail( done );
You can extend an entity with tracking to add additional functionality, for example:
Automatically save when a property changes.
Call hasChanged() to see if the entity has changed.
Call revertChanges() to revert property values.
Add tracking to your entity with the trackable option:
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "d4119c4f-31e9-4fd0-9fc4-6af1d6e36c8e" ).option( "trackable", true ).execute().then( function ( melton ) { melton.option( "trackable" ).should.be.true; done(); } ).fail( done );
When you turn trackable on, changes are automatically saved. You can listen to the save event using emitter on
or once
.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "d4119c4f-31e9-4fd0-9fc4-6af1d6e36c8e" ).option( "trackable", true ).execute().then( function ( melton ) { /* Listening to the `save` event `once`. You can also use `on` here to continuously listen to the `save` event. */ melton.once( "save", function ( error ) { done(); } ); melton.name = "Melton the Magnificent"; } ).fail( done );
When you turn trackable on, Sitecore adds the hasChanged method so you can check if an entity has changed:
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "d4119c4f-31e9-4fd0-9fc4-6af1d6e36c8e" ).option( "trackable", true ).execute().then( function ( melton ) { melton.hasChanged().should.be.false; melton.name = "Melton the Magnificent"; melton.hasChanged().should.be.true; done(); } ).fail( done );
The hasChanged
method does not return true
if a value changes between null, undefined, and '' the empty string).
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "d4119c4f-31e9-4fd0-9fc4-6af1d6e36c8e" ).option( "trackable", true ).execute().then( function ( melton ) { melton.hasChanged().should.be.false; melton.subscribed = ""; melton.hasChanged().should.be.false; melton.subscribed = null; melton.hasChanged().should.be.false; melton.subscribed = undefined; melton.hasChanged().should.be.false; done(); } ).fail( done );
When you turn trackable on, Sitecore adds the revertChanges
method, so you can revert changes.
var peopleService = new EntityService( { url: "/sitecore/api/ssc/people" } ); peopleService.fetchEntity( "d4119c4f-31e9-4fd0-9fc4-6af1d6e36c8e" ).option( "trackable", true ).execute().then( function ( melton ) { melton.name.should.eql( "Banks Melton" ); melton.name = "Melton the Magnificent"; melton.name.should.eql( "Melton the Magnificent" ); melton.hasChanged().should.be.true; melton.revertChanges(); melton.hasChanged().should.be.false; melton.name.should.eql( "Banks Melton" ); done(); } ).fail( done );