Client template 1

Article-8_Small

disclaimer: the article represents a survey on the transformation of JSON data into html on the client part (browser) and reveals the operation details of template в Incoding Framework (search, formation, local storage and plugging in one’s own engine). Examples from the article are available at GitHub

Why is the server one not good ?

Before answering this question, one should study what asp.net mvc can offer.  Razor  - is a server template, which is by default a feature of asp.net mvc, it has a huge functionality and can perform C# code declared within the cshtml  file framework, therefore it does not cause problems, so, what is the matter? When the fed back result for Action  is built up by forming ( View or PartialView )  html  on the server one will get a ready-made content, rather than “pure” data, which may cause the following problems:

  • One may not use Action  when developing a mobile application or a third-party client (API )
  • The traffic used for data transmission grows due to the bulky html content compared to the compact JSON  data.
  • The forming takes up the server resources, which can be avoided by delegating them to the client. (they are more numerous, so we don’t mind).

Note: as far as the client is concerned, it is of course a joke, that we don’t mind, the actual performance will be dealt with later on in this article.

We may say that content formation on server side has much more opportunities, but possesses a set of problems which can’t be solved without turning to client part..

There is a solution

КThough  Razor is good, modern applications require the data to be fed back as JSON or xml, therefore server-based html construction does not fit every scenario. On using client pure template engine. A list of requirement was dressed up, that can be implemented in our “wrapper”.

    • Typing
    • IML Integration
    • Thin template
    • Replacement for the “hot” one
    • Something of your own

 

Typing

Magic string

Razor’s advantage is that there is intellisense support and instrument for refactor ( Rename, Delete ). Comparing it to the client’s one, let us consider an example in order to see the difference.

 Note: Server implementation allow to receive a model scheme and subsequently use the known in advance rather than dynamic types. 

 Note: an example of  template for handlerbars, where ordinary strings are used and Visual Studio can’t calculate in advance the areas included.

FirstName being renamed for Name via special instruments for refactor, such as  R#,  will affect View, but this is not supported by handlerbars since there is no link between the code and template.
To solve this task a builder  has been made up for snap-to for the selected engine ( handlebars,mustaches etc. ) .

 

ScriptTemplate vs Template


Incoding Framework has two ways of creating  template

  • ScriptTemplate -  the resulting markup is placed in script  tag with a preset Id

 note: any type should be indicated as type except for javascript, in order for the browser not to perform the embedded code

  • Template -  “pure” resulting mark-up.

Note: this ways is useful when template  feeds back as a result from  Action ( a detailed review will be represented in the  integration with IML  block)

Syntax

The ITemplateSyntax includes methods used for building up  template, in order to register it an inscription should be added to IoC ( Bootstarpper.cs )

Note: Handlebars ( default by nuget  ) and  Mustaches  implementations are currently set, but individual TemplateSyntax may b written basing on their example. . 

  • ForEach  – is a cycle on collection ( razor –based counterpart of @foreach(var item in Model) {} )
    • On major (data received in response )

    • On embedded

  • NotEach -displays the content if there is no data ( razor-based counterpart of  @if(Model.Count == 0) { } )

Note: can be used together with ForEach

  • For  – displays the content of the indicated field (razor-based counterpart of   Model.Title )

  •  ForRaw – displays the content of the indicated field without coding  HTML ( razor-based analogue of Html.Raw(Model.Title) )

  • Is – means to display, if the field is  True or  NOT NULL ( razor-based counterpart of @if(Is != null || Is){} )

  • Not – means to display, if the field is   False or NULL (razor-based counterpart of  @if(Is == null || !Is) {} )

  • Inline - depending on the field value displays the true content ( True or NOT NULL ) or false content ( False or NULL ) ( razor –based counterpart of @(Is ? “true-class” : “false-class”) )

Note:  Is and Not are used to build big blocks, while  Inline draws back the content at once.
Note: Inline has counterpart IsInline, NotInLine, that only show one part of the condition.

Sample

    • Set class as red if true

    •   Hide element if true or show overwise

    •  Display title if true

 

  • Up -  to go up the hierarchy

Note: the method is necessary when it is necessary to get the value (condition) of the field, but within the domestic ForEach

  • Summary

 note: downloading the example is available on  GitHub

 

integration with IML

IML has methods (AjaxGet, Submit, AjaxPost), to get the data, which can further be inserted via the Insert. The data can be html content or json objects. In order to insert json objects template is used, the path to which is specified by Selector.

NOTE: Starting with version 1.2, methods or WithTemplateById WithTemplateByUrl are preferable to use.

  • WithTemplateById -to find a dom element on Id, which contains  template

NB: to build template ScriptTemplate(tmplId)should be used in this case.

 

sample



  • WithTemplateByUrl – Download layout on ajax

Sample

Controller

View Template

 N.B.: when building up template for ajax Template rather than ScriptTemplate method should be used. 

View IML

Does each template has its own Action ?

There are two solutions that allow not to duplicate the code in action:

  • Shared action

Note: extensions for Url can be built, in order to add the path check via ReSharper annotation 

 Note: MVD was initially positioned as a universal template loader

Id vs Url

Initially, we used a dom element (script) as storage template layout, but gradually switched to boot with ajax, which has the following advantages:

  • Re-use template on different View

Note: for Id it was realized bringing out template into Layout (another master page)

  • Layout is factored out of View

Note: for Id it was realized through partial view

  • Lazy load (template is loaded on demand)

Note: especially true when using tabs

thin template

We chose engine, which support logic less template, such as Mustaches, Handlerbars, because this approach allows to simplify View, moving complex logic on the server, where it is easier “to deal with the complexity.”

For clarity, a task that will be solved in the “normal” way and using logic less

  • Ordinary

  • Logic Less

In the first case, we calculate the value in View, but in logic less we calculate the expression beforehand on the server that has the following advantages:

  • Re-use in other scenarios
  • Unit Test can be covered
  • Less code into View layout

ПAdvantages of logic less manifest when increasing complexity of the tasks, because to expand and maintain the conditions easier on the server side than in View

Replacement for the “hot”"

Task appeared, after problems had been discovered with mustaches, which slowed down in ie 8 and below, and also had problems with inserting large amounts of data (more than 30 entries). Since the implementation of mustaches used in a number of projects, the choice of engine should be simple, so that any could be used.

Note: the code, described below, is available at GitHub

JavaScript Code

  Note: Since not all engine support pre compile, tmpl can be returned unchanged

Layout Code

 Note: The code is in layout, because it must be before the first call Insert.WithTemplate

Template Code

 note: template is built on a “pure” jquery tmpl, without using ITemplateSyntax , but the implementation can be written and registered in IoC

IMl Code

  Note: from IML, nothing has changed, so template engine can be easily replaced without significant alterations 

 

Something of one’s own

Faster, much faster !!

For the first versions of framework, we stored template in dom elements (script), but this method did not allow to build lazy load, so then we switched to ajax loading, which had other problems:

  • If many elements are loaded immediately on one home page that the pool of browser requests is filled up

note: this is partly solved by using cache, but the request will still be, though the status is 304

  • Absence of pre-compile for engine

Note: especially true when there is a large number of inserted data (more than 30 objects)

Once and forever

The solution was found in Local Storage, which allows to save template in browser and then to use it all the time. Will there always be one template? – To answer this question, let’s look at the code (pseudocode) of this mechanism operation.

  • Line 1 – check availability template in local storage

Note: selector and version are keys (details about version below)

  • Line 2 –  return  template from local storage
  • Line 4 – obtain selector value
  • Line 5 – add template to local storage

Note: before adding pre compile should be done

  • Line 6 -return   template from local storage

And if I change the layout template, but the key will remain the same? – In order to solve this problem, we have added versioning globally. To specify the current version of all template field TemplateFactory.Version must be set using JavaScript

Note: the code should be carried out before calling Insert.WithTemplate, so it is best to be placed in Layout
On the example I set Guid, which guarantees the new version after the full (F5) page reloading, but this behavior is relevant only for the development process, and when the code will be laid out in production, it is necessary to fix the version.

Our policy versioning

  • Debug    - while  developping the mark up activity rate  in the template is high, so the version is updated as often as possible (we use Guid, to maintain its uniqueness)
  • Release -  after the project has been uploaded on the server, a fixed version must be installed
Layout

Current Version

 note: TeamCity build.number used as a fixed version. Our approach to the continuous integration ( TeamCity, rake ) will be thoroughly considered in the subsequent papers.    

 

One for all and all for one

When building template, it is necessary to specify only the model type, but it is not considered if it is a collection or a single object. Some template engine require to specify what it will be – a collection or a single object (for example handlebars {{# with data}} or {{# each autors}}), so we decided to remove this condition and not to take into account the amount of items when template constructing. Owing to this feature we did not need to add method With (which not all engine support).

пример

Коллекция объектов

 Один объект

Общий template

 

Client is not a server or Our hook (Repeated mistakes)

During training employees to use client template, I compiled a list of the most frequent mistakes that because they write code, as well as for the server template

GUID -in view it is used to specify a unique name for the element within the pages, but in the case of the client template it has pitfalls.

Condition: each tag li must have a unique Id

Code contains an error, because the variable uniqueId will be calculated once on the server, bypass of the collection will take place on client. To test this, we must see the resulting layout.

For the code to work correctly, the logic of guid calculation has to be transfered to Model

 Conclusion

We constantly develop each Incoding Framework component, contributing new features to it with every version and “polish” the old ones and certainly template is not an exception, to make sure one can see our BugTracker. All I have described in the article are proven by personal experience constructions and practices that allow to develop cross-platform applications initially, but not to reconstruct the architecture when it costs a lot.

Vlad Kopachinsky

I am a Senior developer at Incoding Software in Russian Federation. I created the Incoding Framework for rapid development

More Posts - Website - Twitter - Facebook - LinkedIn

One comment on “Client template

  1. Pingback: Derrick

Leave a Reply