Issuing Requests
A dataModel
is a representation of your model from the server. Footwork dataModels have features and capabilities aimed at the management of a record of your data on some sort of remote resource.
Request Types¶
Example DataModel Configured For Requests:¶
function Person (personData) { var self = fw.dataModel.boot(this, { url: '/person', idAttribute: 'id' }); // note the self.id observable is mapped to the idAttribute self.id = fw.observable(personData.id).map('id', self); self.name = fw.observable(personData.name).map('name', self); }
Requests return promises
The following sections outline how to use the API to issue requests related to the dataModel
you are working with. Footwork utilizes ES6's fetch
for AJAX internally. If you need to make a generic AJAX request you will want to use fetch
, for more info on using fetch
see ES6 Fetch.
It is also important to note that all of the methods used below return an ES6 Promise and so you can hook into them using standard methods such as .then()
. For more information see: ES6 Promise.
Create A New Record¶
To create a record using a dataModel
:
- It must have a falsey value resolved for its mapped
idAttribute
(the falsey value tells Footwork thedataModel
needs to be created, not updated). - It must have a valid
url
configured to create the record on (see: url configuration). - The data you want saved needs to be mapped (see mapping request data).
Using the example dataModel we instantiate a new instance and provide it a value for the id
, which if you remember is mapped to the idAttribute
. This value will be used to construct the url
when we update the record on the server. We also provide a value for the name
which is what we want saved:
var person = new Person({ id: 1, name: 'Bruce Wayne' });
Since the id
observable is mapped to the idAttribute
of our dataModel
it will be used when we issue the request. Footwork follows a typical REST endpoint schema by appending the id
of a model to the URL when update a record. So in this case the final request will be to POST /person/1
.
To create the dataModel
on the endpoint we call save
on the instance:
var promise = person.save();
When save
is called:
- The
url
is resolved - The mapped
idAttribute
is resolved (and since it is falsey, a create request is generated) - All of the mapped observable data is resolved and collected together in the structure the mappings define.
- A
POST
request is issued in the form ofurl/idAttribute
and passed the data (this can be customized with an explicit url object configuration).
Request Options
-
If you need to pass options to the underlying ES6 fetch call you can do so by passing them into the
dataModel.save
call:person.save({ method: 'POST' });
-
By default when the request is returned its data is applied to your
dataModel
, you can disable this by passingwriteResponse: false
as an option:person.save({ writeResponse: false });
Read A Record¶
To read (or fetch) a record using a dataModel
:
- It must have a non-falsey value resolved for its mapped
idAttribute
(the non-falsey value tells Footwork where the record is located at and is used in url generation). - It must have a valid
url
configured to read the record from (see: url configuration). - The data you want fetched needs to be mapped (so Footwork knows where to write it after retrieving the request data, see mapping request data).
Using the example dataModel we instantiate a new instance and provide it a value for the id
, which if you remember is mapped to the idAttribute
. This value will be used to construct the url
when we fetch the data from the server:
var person = new Person({ id: 1 });
Since the id
observable is mapped to the idAttribute
of our dataModel
and we have a simple string configured for the url
, it will be used when we dispatch the fetch request (see url configuration). Footwork follows a typical REST endpoint schema by appending the id
of a model to the URL when fetching its data. So in this case the final request will be to GET /person/1
.
To issue the request we call fetch
on the dataModel
instance:
var promise = person.fetch();
When fetch
is called:
- The
url
is resolved - The
idAttribute
is resolved - A
GET
request is issued in the form ofurl/idAttribute
(this can be customized with an explicit url object configuration).
In the above example this would generate a request to GET /person/1
.
At this point Footwork waits for the request to finish. Your endpoint should return an object literal representing the data you want to be written to your dataModel
. For example, given our person
instance and the GET /person/1
request, our endpoint should return something like:
{ id: 1, name: 'Bruce Wayne' }
Once the request returns a response, Footwork then takes the mappings defined and uses that to translate and write the response object back to the person
instance.
// ...after the request finishes: person.name() === 'Bruce Wayne'
Now that the request has finished and the data has been written back to the mapped observables:
- Any UI bound to the
dataModel
would then update automatically. - Any subscriptions or computed observables based on the mapped observables would also receive updates.
Request Options
If you need to pass options to the underlying fetch call you can do so by passing them into the dataModel.fetch
call:
person.fetch({ method: 'POST' });
Update A Record¶
To update a record using a dataModel
:
- It must have a non-falsey value resolved for its mapped
idAttribute
(the non-falsey value tells Footwork thedataModel
needs to be updated, not created). - It must have a valid
url
configured to update the record on (see: url configuration). - The data you want saved needs to be mapped (see mapping request data).
Using the example dataModel we instantiate a new instance and provide it a value for the id
, which if you remember is mapped to the idAttribute
. This value will be used to construct the url
when we update the record on the server. We also provide a value for the name
which is what we want saved:
var person = new Person({ id: 1, name: 'Bruce Wayne' });
Since the id
observable is mapped to the idAttribute
of our dataModel
it will be used when we issue the request. Footwork follows a typical REST endpoint schema by appending the id
of a model to the URL when update a record. So in this case the final request will be to PUT /person/1
.
To update the dataModel
on the endpoint we call save
on the instance:
var promise = person.save();
When save
is called:
- The
url
is resolved - The mapped
idAttribute
is resolved (and since it is non-falsey, an update request is generated) - All of the mapped observable data is resolved and collected together in the structure the mappings define.
- A
PUT
request is issued in the form ofurl/idAttribute
and passed the data (this can be customized with an explicit url object configuration).
Request Options
-
If you need to pass options to the underlying fetch call you can do so by passing them into the
dataModel.save
call:person.save({ method: 'POST' });
-
By default when the request is returned its data is applied to your
dataModel
, you can disable this by passingwriteResponse: false
as an option:person.save({ writeResponse: false });
Delete A Record¶
To delete (or destroy) a record using a dataModel
:
- It must have a non-falsey value resolved for its mapped
idAttribute
(the non-falsey value tells Footwork where the record is located at and is used in url generation). - It must have a valid
url
configured to delete the record at (see: url configuration).
Using the example dataModel we instantiate a new instance and provide it a value for the id
, which if you remember is mapped to the idAttribute
. This value will be used to construct the url
when we delete the record on the server:
var person = new Person({ id: 1 });
Since the id
observable is mapped to the idAttribute
of our dataModel
it will be used when we issue the request. Footwork follows a typical REST endpoint schema by appending the id
of a model to the URL when update a record. So in this case the final request will be to DELETE /person/1
.
To delete the dataModel
on the endpoint we call destroy
on the instance:
var promise = person.destroy();
When destroy
is called:
- The
url
is resolved - The mapped
idAttribute
is resolved (and since it is non-falsey, an update request is generated) - A
DELETE
request is issued in the form ofurl/idAttribute
(this can be customized with an explicit url object configuration).
Request Options
If you need to pass options to the underlying fetch call you can do so by passing them into the dataModel.destroy
call:
person.destroy({ method: 'POST' });
Handling Errors¶
For all requests made, the ES6 Promise created will be passed back to the caller. You can use that to handle any errors that might occur:
var promise = myDataModel.fetch(); // example request promise.then(function (response) { if (!response.ok) { console.log('Something went wrong with the request:', response.statusText); } }).catch(function (error) { console.log('Something else went wrong:', error); });
Overriding Request Options¶
A dataModel
has 3 ways in which you can alter the options passed into the underlying fetch call when a request is made:
-
Individually with each request as shown in the above CRUD sections
-
As a configuration option
-
On a global
fw.options.fetchOptions
configurationYou can supply the same fetch options object configuration or callback on
fw.options.fetchOptions
just as you would on a configuration option:fw.options.fetchOptions = fetchOptions: { credentials: 'same-origin' };
By supplying your options here they will be used on all requests issued.
Override Priority
You can supply fetch options in 3 different ways, they are applied to your requests by mixing them together when the request is generated. This is done by extending one onto the other such that the options you supply are used in the following priority (higher ones override lower ones):
- Individual request options (shown for each CRUD action above)
- dataModel configuration options
- Global
fw.options.fetchOptions
(shown here in this section)
Altering the Storage Method¶
By default the storage engine utilizes a RESTful endpoint. All requests are dispatched through fw.dataModel.sync
which is then proxied through fw.sync
. You can override the default behavior by providing your own method at either of these two locations.
-
action
The request action (create/read/update/delete).
-
dataModel
Your
dataModel
instance -
options
Any passed in options