Constraints are logical conditions on the data of an app. The simplest, and most important, types of constraints are property constraints and object-level constraints.
Constraints should be defined in the model classes of an MVC app, since they are part of their business semantics.
Constraints should be checked in various places of an MVC app: in the UI/view code, in model classes, and possibly in the database.
Software applications that include CRUD data management need to perform two kinds of bi-directional object-to-string type conversions:
Between the model and the UI: converting model object property values to UI widget values, and, the other way around, converting input widget values to property values. Typically, widgets are form fields that have string values.
Between the model and the datastore: converting model objects to storage data sets (called serialization), and, the other way around, converting storage data sets to model objects (called de-serialization). This involves converting property values to storage data values, and, the other way around, converting storage data values to property values. Typically, datastores are either JavaScript's local storage or IndexedDB, or SQL databases, and objects have to be mapped to some form of table rows. In the case of an SQL database, this is called "Object-Relational Mapping" (ORM).
Do not perform any string-to-property-value conversion in the UI code. Rather, this is the business of the model code.
For being able to observe how an app works, or, if it does not work, where it fails, it is essential to log all critical application events, such as data retrieval, save and delete events, at least in the JavaScript console.
Responsive validation means that the user, while typing, gets immediate validation feedback on each input (keystroke), and when requesting to save the new data.