jRIApp is another HTML5 framework created for developing Web applications, which in their functionality are not much inferior to desktop applications.
The main difference from already existing angularJS or emberJS frameworks is the presence of a data service integrated with the framework, as well as the use of MVVM design architecture instead of the most common MVC framework in this type of framework.
In general, it can be described as HTML5 Framework implementing data binding, infrastructure for declarative attachment of logic to HTML elements, data classes (DbContext, DbSet) and data server services implemented.
The client part of the framework is written in javascript (
currently in development typescript version ), and the server part in C #.
')
This framework is published on
GitHub under the MIT license. It includes a demo application written using ASP.NET MVC4 and contains documentation on its use.
The style of applications created using jRIApp is very similar to creating applications using Microsoft Silverlight with a WCF RIA service. Data binding has a similar syntax - unidirectional, bidirectional, can use a data converter. Actions (action) can be tied through commands (command) to custom elements such as buttons or hyperlinks.
For example, this is how a page switch is created in a demo application:
<div style="margin-top:40px;text-align:left; border:none;width:100%;height:15%"> <div style="float:left;" data-bind="{this.dataSource,to=dbSet,source=VM.productVM}" data-view="name=pager,options={sliderSize:20,hideOnSinglePage=false}"> </div> <div style="float:left; padding-left:10px;padding-top:10px;"> <span>Total:</span> <span data-bind="{this.value,to=totalCount,source=VM.productVM.dbSet}"></span>, <span>Selected:</span> <span data-bind="{this.value,to=selectedCount,source=VM.productVM}"></span> </div> <button style="float:right;" data-bind="{this.command,to=addNewCommand,mode=OneWay,source=VM.productVM}"> + New Product </button> </div>
Templates also have a similar type of creation - they exclude the use of a script similar to foreach cycles, which repeat the output of chunks of markup in the resulting HTML document. This functionality in templates is beautifully replaced by the fact that each DOM element to the properties of which is bound to data is actually wrapped when creating a binding with a view of an element (element view), which essentially can bind any logic to an HTML element. Thus, jQuery plugin binds logic to the HTML element, but the framework does so in a declarative style.
An example of a small template:
<div id="stackPanelItemTemplate" data-role="template" class="stackPanelItem" > <fieldset> <legend><span data-bind="{this.value,to=radioValue}"></span></legend> Time: <span data-bind="{this.value,to=time,converter=dateTimeConverter,converterParam='HH:mm:ss'}"></span> </fieldset> </div>
In addition, there are ready-made user elements integrated with components for working with data, such as DataGrid, DataForm, StackPanel, ComboBox, etc. Data validation takes place both on the client and on the server and uses metadata set on the server side.
In addition, I would like to include in this topic some basics to get started with the Framework.
The base class of the framework:
Why is he so remarkable?
First, it carries observer functions, i.e. You can attach events to which subscribers want to receive notifications. It also carries the basic function of destroying an object in order to free its resources (
mainly links to other objects and events ), and it can also notify other objects of its destruction using an event, and it can also notify subscribers of errors that occurred in this object (
as a rule, clients only subscribe to the error event of the Global and Application objects ).
Another important function inherent in this class is that it has a method,
extend , which allows you to inherit functionality in derived classes.
An example of creating a new object class:
var NewObject = RIAPP.BaseObject.extend( {
Further, the class of the object can be obtained from other modules.
var Instance = app.getType('custom.NewObject').create('radioValue1');
Since all classes of objects are created inside modules, classes of objects can also be exported from them as is done in the classical definition of modules, i.e. inside each module, the
this variable refers to the module itself and any properties can be attached to it.
For example, in one of the modules, newObjMod, we export the class:
var thisModule = this; thisModule.NewObject = NewObject;
and in another we import:
var NewObject = app.modules.newObjMod.NewObject;
Having studied the basis of the definition of classes in the Framework, you can proceed to the definition of data binding, i.e. to the object,
Binding .
Data binding:
In principle, an object, Binding, can be created in code, but more conveniently, this is the declarative definition of data binding, which is mainly used in applications (
in the documentation there is an example of creating a binding in code ).
An example of binding data to an HTML element,
select :
<select size="1" style="width:220px" data-bind="{this.dataSource,to=mailDocsVM.dbSet,mode=OneWay,source=VM.sendListVM} {this.selectedValue,to=selectedDocID,mode=TwoWay,source=VM.sendListVM} {this.toolTip,to=currentItem.DESCRIPTION,mode=OneWay,source=VM.sendListVM.mailDocsVM}" data-view="options:{valuePath=MailDocID,textPath=NAME}">
The attribute, data-bind defines data binding expressions. Each expression wraps itself in curly braces and defines the path to the property of the receiver and the path to the property of the data source. For the expression, you can set the mode -
mode , i.e. in which direction the data is moved: OneTime (once from the source to the receiver), OneWay (from the source to the receiver), and TwoWay (in both directions). Mode, OneWay - is the default mode and can be omitted. In addition to the paths to the properties and the binding mode, you can also specify the
source . This binding property is not necessary, because if you do not specify it, the path for the source property will be calculated from the data context. If you specify it, the entire path is calculated from the Application instance. As a rule, custom view models are attached to the VM property (
this is the namespace attached to the Application object ). Therefore,
source = VM.sendListVM , stands for [Application Object] .VM.sendListVM.
An example of initializing (creating) custom view model:
If we did not specify the
source , in the binding expression, then the path property for the source would be determined from where the expression is specified. If, simply, on the HTML page, then the entire path is also calculated from the Application object.
However, if an expression is used inside a
Data Template or a Data Form, the source (
if not explicitly specified in the expression ) is determined from the data context of the template or form (
data context ).
Also, data binding can have a data converter and a parameter for the converter, which helps to change data when passing from the source to the receiver and back. For example, it is convenient for formatting numbers and dates.
Binding life cycle:
When creating Single Page Applications it is required that prolonged use of the application does not lead to a memory leak.
Therefore, the Framework has a system for creating objects, which provides cleaning of memory from unnecessary objects (
ie, deleting references to unused objects is carried out ).
The root of life (
that is, the root object storing references ) is an instance of a Global object, a
singleton instance of which is created automatically when jriapp.js is loaded. This object stores links to Application objects created by the user on the HTML page (
as a rule, also one instance, but you can create several if you create them in Web Parts ). The Application object in turn stores references to the objects it created, and so on.
When an object is destroyed (by
calling its destroy method ), references to it are deleted. He is responsible for this, the object that created it.
The framework is based on data bindings, and element views are element views (a
wrapper with logic attached to a DOM element, similar to the jQuery plugin ). They are created and deleted in large quantities during the application life cycle.
When creating binding objects, the Framework first determines whether the HTML DOM element has an associated element type. For example, in the Framework there is a module that defines the element view classes embedded in the Framework for DOM elements (
users can add custom element views in their modules ). Some of them are associated with an element by the element tag name. For example, for the main types of input elements there are corresponding types of element view. However, some element views are registered by their own name (
i.e., not associated with certain tags ). For example, TabsElView, registered under the name tabs, and BusyElView under the name busy_indicator. In practice, this means that in order to select (
change ) which type of element view will create a binding, you can use the data-view attribute.
In the following example, we indicated that we want the binding to create an element view registered as expander.
<span data-bind="{this.command,to=expanderCommand,mode=OneWay,source=VM.headerVM}" data-view="name=expander"></span>
Also, for element view, you may need to pass options to create it (
element view will get them in its constructor ).
<input type="text" data-bind="{this.value,to=testProperty,mode=TwoWay,source=VM.testObject1}" data-view="options:{updateOnKeyUp=true}" />
Modular structure:
The framework has a hierarchy of modules.
The Global object has the top module structure. In one of its modules, the Application class is defined.
The Application object, in turn, also has its own modules (
most of the framework modules ).
When creating an instance of an application (
Application ), it initializes its modules, which in turn are divided into key (
which are defined in the framework ) and user-
defined (
user-defined ).
Custom modules provide an extension of the Framework's capabilities, as well as serve to create definitions of the View Model classes in them, which in the user applications, MVVM, provide data sources for bindings (
DataBindings ).
Results:
I think this is only a small part of everything that is in the framework for creating applications. The documentation for it now has 80 pages and it is not possible to describe all its features in the short introductory topic. For a more detailed acquaintance with him you will need to write a few such small topics covering each individual part of the use of the framework. But first of all I propose to watch the project on GitHub and watch the video of the demo application on youtube.
Also, please note that the Framework was created by me to translate applications working in SilverLight, and that these were applications for working with data. Therefore, the design of the demo application is simple, it shows mainly how to work with data. However, if you want a good design, then this Framework does not limit anything in terms of the use of styles and design. The design will depend only on the designer.