Sencha Ext JS 7.7 is Here – Discover What’s New and Exciting – LEARN MORE

https://staging.sencha.com/blog/deep-dive-into-ext-js-5-data/feed/
Table of Contents Hide
  1. What Are Dynamic UIs?
  2. What Are JS Frameworks’ Fundamentals For Dynamic UIs?
  3. How Do You Build Dynamic UIs with JavaScript Frameworks?
  4. What Are the Best Practices for Performance Optimization?
  5. JS Frameworks: Conclusion
  6. JS Frameworks: FAQs
  7. What’s your reaction?
  8. What Are Dynamic UIs?
  9. What Are JS Frameworks’ Fundamentals For Dynamic UIs?
  10. How Do You Build Dynamic UIs with JavaScript Frameworks?
  11. What Are the Best Practices for Performance Optimization?
  12. JS Frameworks: Conclusion
  13. JS Frameworks: FAQs
  14. What’s your reaction?

Deep Dive Into Ext JS 5 Data

July 8, 2014 1 Views

Introduction

Ext JS 5 DataWith the introduction of Ext JS 5, we have greatly expanded the capabilities of the Sencha Data Package, which was initially released with Ext JS 4 and Sencha Touch 2. The data package is one of the cornerstones of application development: the oft neglected “M” (for Model) in the buzzing world of “MVC” and “MVVM”. These new capabilities can be seen throughout the entire application development process, from declaring your data model, to presenting your data and validating user input, and finally, saving it back to the server.

In this article, we’ll walk through each of these features. Let’s start at the beginning.

To learn more, join us for the upcoming webinar — Deep Dive into Ext JS 5 Data, Thursday, 7/17 at 10:00am PDT

UPDATE July 18, 2014: Thanks to everyone who attended the webinar! The recording is available here.

New Declarative Features

Typical applications have many classes that make up their data model. With Ext JS 5, we reduced the amount of repetitive, boilerplate code needed in these Model classes. Many of these enhancements are covered in What’s New In Ext JS 5 so I won’t repeat too much of that here.

Fields

It may seem contradictory in this context, but in Ext JS 5, you are no longer required to declare a Model’s fields. The advantage here is that data can be more easily extended, so long as it needs no special processing prior to record creation. It's not just easier, meaning you have fewer things that you must declare, but it can be faster as well. This optimization occurs because the data is not processed on a per-field basis, unless needed.

While eliminating field declarations is convenient at times and an easy way to eliminate per-field processing, this is not always possible. For example, the defaultValue and convert configs require processing for the field on which they are declared. When adding validators and references on fields, you can still avoid this processing by using the default field type “auto” (and avoiding the configs just mentioned).

Custom Field Types and Validators

One area where declaring your fields is most advantageous is also perhaps the most repetitive type of code in Models: validation. Prior to Ext JS 5, the declaration of validation logic was uniquely a job for Ext.data.Model-derived classes. As such, these validations were not something other classes dealing with similar fields could reuse. At the same time, these validations were frequently related to the type of content in the field. For example, email addresses, phone numbers, gender, date of birth, etc.

With the introduction of custom field types, you can now reuse this logic across all your models. For example, we can declare a “gender” field type:

20780619896606847acee0b_000000

And then use it in any number of Models:

20780619896606847acee0b_000001

See this fiddle to experiment with the above example. In real-world applications, there are likely to be many opportunities to reuse field types and their validators.

Reference Fields and Associations

Declaring associations is another area in Ext JS 5 where we have reduced boilerplate code requirements. In previous releases, the hasMany, hasOne and belongsTo configs required that you manually maintain symmetric declarations on both “sides” of an association. This is no longer the case. You can declare an association in either of the associated classes (though typically on the “many” side).

For example, you can use hasMany on one Model and the corresponding belongsTo is no longer needed. Consider this set of declarations:

20780619896606847acee0b_000002

The above example takes advantage of two new features in Ext JS 5:

  • Declaration of associations on only one of the associated Models.
  • Automatically generated entityName values (by setting the Schema namespace). This allows you to have friendly names for your Models and their generated getter and setter methods while still following the recommended namespace structure in your application. Schema is also new to Ext JS 5 and has some other useful options worth looking into (such as its proxy config), but because there is typically not much need to directly interact with the schema, we won’t cover it further here.

The above example is, however, overly simplified from the perspective of true applications where these records are often linked to each other by holding id values in certain fields. For example, an OrderItem will often have an orderId field and the Order will likely have a personId field. These are sometimes called “foreign keys” and maintaining the integrity of these fields is critical.

When such fields are present, the new reference config can be used to indicate the type of Model a particular field references. Reworking the above code in this example:

20780619896606847acee0b_000003

Given the new reference configs shown here, the same associations are created as with the hasMany example. More than that, Ext JS 5 will maintain these fields as well. For example, adding an OrderItem to the orderItems association of an Order will automatically set the orderId field.

Many-to-Many Associations

In addition to streamlining associations using reference fields, we also added support in Ext JS 5 for a new type of association: many-to-many. A typical scenario where this comes up is modeling Users and Groups. A user can be a member of multiple groups, and a group can have multiple users. Let’s consider a simple declaration like this:

20780619896606847acee0b_000004

Notice again that only one Model has to declare the association (using the manyToMany config). This creates methods on each class similar to hasMany. In the above case, the User class gets a groups method and Group gets a users method. As with hasMany, these return stores that hold the associated records. Under the covers, however, careful bookkeeping has to take place to maintain this type of association.

When models store keys to each other, maintenance of their relationship is straightforward. In the case of many-to-many associations, however, it is not possible to represent the relationship as fields of either associated record. Further, adding a Group to the groups store for a User must add the User record to that Group’s users store (if it exists).

To see this in action, check out this example. One thing is quite new and different in this example:

20780619896606847acee0b_000005

We’ll see more on this later, but for now it is sufficient to say that the extra maintenance required for many-to-many associations is handled by this session instance. We’ll see later how we can use the session to look at the pending edits for these associations.

Connecting The Pieces

Now that we have our data model declared, we’re ready to see some new ways we can use it in our application. Using data binding in Ext JS 5, we can much more easily get our data presented to the user, but then the fun starts as soon as the user begins editing that data.

Form Validation

With the introduction of ViewModels, Ext JS 5 now has the ability to know the connection between the value of a form field and the underlying data storage. Data binding for form fields goes to the next logical step and also connects the validators from Model fields when you set the new config: modelValidation.

For example:

20780619896606847acee0b_000006

The above form is just a basic data binding form using a Person record in the ViewModel. By adding modelValidation: true, however, the child form fields automatically bind to the validator information for their value bindings. In this case, the gender field of the person record in the ViewModel is invalid and that is reflected by the Gender text field’s error indicator.

Data Sessions

The final piece of the puzzle then is to gather all of this validated data, so it can be saved to the server. In previous versions, this was done manually by tracking relevant records and stores and calling their save and sync methods. When dealing with multiple records and stores, this could become a complex process of bookkeeping, sequencing and callback chaining.

This is where Ext.data.Session can greatly simplify your code. The primary job of a session is to track records (by their type and id), so all related parties can retrieve a reference to the same record object. By tracking all of these records, the session ensures that the contents of associations are coherently updated and maintained as edits occur.

Creating a Session

Sessions are typically created using the session config. The key decision then is where in the view hierarchy to create a session. Creating a session at the top (or “viewport”) level makes sense if the application uses a relatively stable set of records over its lifetime. If this is not the case, a child view such as a modal window or closable tab would make more sense because the session can be destroyed along with the view that owned it.

Any component can retrieve the appropriate session instance by calling the lookupSession method. This method will consider that component’s session config, if specified, or find the session from the nearest ancestor in the view hierarchy that has a session configured. In other words, the “session” is inherited by child components.

Getting Records

Records can be manually fetched from a session by calling getRecord or created in the session by calling createRecord. These methods are seldom called directly when using ViewModels which automate this using the links config. Whether called directly or automated by ViewModels, these methods ensure the coherency of record instances tracked by the session.

When records are loaded by the session, traversing their associations will load associated records into the same session. This gives the session the ability to gather changes for all of these records when it comes time to save back to the server.

It is worth mentioning that all records loaded or created by a session are owned by that session and cannot be shared with another session.

Inspecting a Session

You can request that the session produce the current state of all its records by calling its getChanges or visitData methods. The information returned by these methods can be used for a variety of useful purposes such as:

  • Saving all changes to the server in a single transaction
  • Transfer the state of the client’s records to the server to enable custom Ajax requests
  • General diagnostics

Updating a Session

The opposite of getChanges is update. This method can be used to inject any number of record changes of any type (create, update, drop) using the same format returned by getChanges. Internally this mechanism is used to support child session (discussed below), but it enables other techniques as well:

  • Preload a session with all initially relevant records at page load time. This can eliminate many independent Ajax calls to load records and stores individually.
  • Transfer results of server-side record changes back to the client (perhaps in the response to a custom Ajax request) for subsequent saving (or discarding). That is to say, you can seamlessly transfer the current state of records from the client to a server-side method and merge the resulting record changes back on the client without having to commit those changes on the server at the same time. This can be helpful when building “what-if” user experiences.

Child Sessions

It is fairly common to present a user with some sort of user interface that allows them to make changes and then accept or reject those changes. For example, a typical “OK/Cancel” window. We can isolate such a window’s ViewModel by creating a new “child” session. This child session communicates with its parent session to retrieve record data but does not immediately modify those records. Instead, it creates records of its own to hold on to changes. When the user accepts the changes, we simply call the save method on the child session.

You can see this in action in the Kitchen Sink example.

Saving Sessions

When it finally comes time to save changes back to the server, we have a couple choices. We can use getChanges described above and send the data in a custom Ajax request. Or, we can use the standard proxy defined for each Model.

To use the standard proxy, we call getSaveBatch on the session. This returns an Ext.data.Batch object on which we call start. The individual operations in this batch are ordered in such a way as to ensure that the server is never presented with records that it is unprepared to handle. This ordering is derived from the Model’s reference fields. For example, since an OrderItem has an orderId field, any created Order records must be sent to the server first before OrderItems with that orderId.

If the server is handling id generation, this is also when the client-generated IDs are corrected and the corresponding reference fields on associated records are updated.

Caveats

For all their usefulness, sessions do have limitations. These stem from the fact that, to do its job, a session must retain references to all records attached to it and can only remove them when a record is dropped. If a session is over-used, it will become a large memory consumer. You must take care in choosing where to create sessions and allowing them to be decommissioned by connecting them to components with a finite lifecycle.

Conclusion

We think these improvements all across the data layer will make it easier to develop and maintain your applications, and even provide you with some techniques that were previously impossible. We’d love to hear how you’ve used these new features in your applications, and of course, if you have questions we’d be happy to assist you in the forums.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Table of Contents Hide
  1. What Are Dynamic UIs?
  2. What Are JS Frameworks’ Fundamentals For Dynamic UIs?
  3. How Do You Build Dynamic UIs with JavaScript Frameworks?
  4. What Are the Best Practices for Performance Optimization?
  5. JS Frameworks: Conclusion
  6. JS Frameworks: FAQs
  7. What’s your reaction?
  8. What Are Dynamic UIs?
  9. What Are JS Frameworks’ Fundamentals For Dynamic UIs?
  10. How Do You Build Dynamic UIs with JavaScript Frameworks?
  11. What Are the Best Practices for Performance Optimization?
  12. JS Frameworks: Conclusion
  13. JS Frameworks: FAQs
  14. What’s your reaction?
Ready to get started?

Create an account now!

Latest Content
Highlights of Virtual JS Days 2024

Highlights of Virtual JS Days 2024 From February 20-22, 2024, we held the third Virtual…

From the GM’s Desk 2023: An Exciting Year for Sencha & Ext JS 7.7

We are past the midpoint of 2023 and we are very proud of what we…

Sencha MVP Spotlight: Animap - The Historical Research Tool with Andy Allord

Welcome to our Developer Spotlight Series, where we showcase the remarkable talents and achievements of…

See More

Leave a Reply

Your email address will not be published. Required fields are marked *

*

coming soon

Something Awesome Is

COMING SOON!