Backbone.js Collections ↔ JSON:API Server: Custom Sync Strategy
0 reputation · 08 Dec 2021, 03:57 UTC
0 reputation · 08 Dec 2021, 03:57 UTC
Integrate a Backbone.js collection with a JSON:API‑compliant backend by customizing the sync and parse methods, so that fetched resources populate models with proper attributes and relationships.
Backbone 1.3.5 does not understand the data envelope or relationships objects that JSON:API returns. Overriding sync to inject authentication headers can interfere with the library’s optimistic update logic, while a collection‑level parse may hide errors that occur on individual models. Additionally, event signatures differ between 1.3.5 and 1.4.0, which could affect view re‑rendering after a sync event.
data and relationships into Backbone models while preserving nested relationships?sync adapter add auth headers without breaking optimistic UI behavior?parse at the collection level mask per‑model parse errors, and how can those be surfaced?34775 reputation · 08 Dec 2021, 11:26 UTC
sync method for outgoing data and the parse method for incoming de-serialization.parse method. JSON:API returns resources within a data envelope and separates related entities into relationships and included keys. You must manually map these to a format Backbone models can consume.
response.data array to create primary models.response.included array to populate a cache of related models by ID to avoid duplication.relationships object to model attributes as IDs or references, depending on your architecture's needs.To add authentication headers without breaking optimistic UI behavior, override the sync method at the Base Model or Collection level. By intercepting the options object before it reaches the server, you can inject headers without interfering with the internal state logic.
MyCollection.sync = function(method, model, options) {
options.headers = options.headers || {};
options.headers['Authorization'] = 'Bearer ' + localStorage.getItem('token');
options.headers['Content-Type'] = 'application/vnd.api+json';
// Wrap data in JSON:API format
const payload = {
data: {
type: this.model,
id: model.id,
attributes: model.toJSON()
}
};
return Backbone.sync.apply(this, method, model, options);
}
Overriding parse at the collection level can mask per-model errors if the logic uses a generic try-catch block. To surface these errors:
parse methods to validate specific attributes.parse aggregate errors or trigger a custom event when validation fails.error event in your views to ensure the UI reflects specific model failures.Note: This strategy assumes Backbone 1.3.5+. If using 1.4.0+, ensure your event listeners account for the updated event signatures where the model is passed as the second argument in collection-related events.
Use comments to ask for clarification. Post a solution as an answer.
5,930 reputation · 08 Dec 2021, 15:37 UTC
While overriding parse handles the primary data envelope, a critical detail often overlooked is the management of included resources and pagination metadata. Since Backbone collections are designed to be simple arrays of models, they cannot natively store the links or meta objects returned by a JSON:API server.
To avoid duplicate model instances when processing the included array, it is recommended to use a centralized model cache or a shared registry. This ensures that if multiple primary resources reference the same related entity, they all point to a single Backbone model instance.
Because parse must return an array for the collection, pagination data is typically lost. A common pattern to resolve this is to attach the metadata directly to the collection instance during the sync process:
// Inside a custom sync override
success: function(response) {
this.pagination = response.links; // Store metadata on the collection
this.parse(response);
}