How do Angular js and Knockout
From Knockout to AngularJS
Table of Contents
2.3. Modular code
- Downloads & Links
In contrast to this is AngularJS. This framework offers a much wider range of functions. There are many functionalities that can be used for a homogeneous SPA architecture. AngularJS is preparing to become "market leader" for SPAs and to maintain this position thanks to the support of Google.
In this session (and with the handout you have here) we will compare Knockout and AngularJS. Based selected focus areas the respective advantages and weaknesses should be worked out and demonstrated with code examples. Johannes Hoppe always sheds light on the question of whether and how a switch from knockout to Angular JS is or would be sensible and feasible.
A SPA architecture is always about bringing as much control flow and rendering logic as possible from the web server to the browser. Ideally, the web server only delivers a single HTML document, which then takes control. In principle, a wide variety of design patterns can be applied to this individual HTML document. In practice, however, it has been shown that the MVC (Model-View-Controller) pattern is the preferred implementation. This design pattern has become the standard on the server. It is not a bad idea to carry over the tried and tested to the browser. Most SPA frameworks also offer an MVVM (Model-View-ViewModel) engine. These two principles complement each other well. Due to their great overlap in terms of content, it makes sense to lump both principles together and stir them vigorously. This is exactly how the makers of AngularJS see it, who pragmatically call their framework a MVW (Model-View-Whatever (works for you)) framework.
On the premise that we are in the context of a WMD Move application, it makes sense to select the following focal points as comparison items:
- Modular code
The following example is based on a simple form that changes the content of a yellow note when the value changes:
In the days before MVVM, simple UI topics were sometimes very complex. The following source code demonstrates how, for example, the sticky note only has to be processed with jQuery.
You can see that the individual HTML elements are cumbersome to access. MVVM offers a clear simplification here.
The main task of an MVVM engine is the View (which in our case is pure HTML) as elegantly as possible with the so-called ViewModel connect to. The ViewModel can be seen as a special controller. On the one hand, it provides data of the business logic or the model and also represents methods for these. The "ViewModel" intermediate layer separates the view and model from one another. It is now irrelevant where and how the actual model exists. The ViewModel "hides it" and creates a standardized view of it. Often it will be the case that the actual model is only really tangible on the server. To do this, the ViewModel then directs all operations via AJAX to the server.
This connection between View and ViewModel is called Binding, it usually goes both ways. If the ViewModel changes, the view is updated. If the value of an interaction element changes (e.g. here an input field), the ViewModel is also changed. This is exactly what happens in the following example, which is implemented with Knockout.js.
With knockout, objects of the type are used for the two-way bindings. These implement (as the name suggests) the observer pattern. Correspondingly, the bindings to HTML elements are specified with the data attribute.
In this example we find the directives which an application automatically provides ("auto-bootstrap"), which executes code (eval) and here, for example, sets a model quick-and-dirty and which the view and the model via two- Way binding connects.
It is noticeable that the model does not have to implement any observables. This is where Angular differs fundamentally from Knockout. Incidentally, the AngularJS documentation does not differentiate between "Model" and "ViewModel". One speaks more of the $ scope that holds references to one or any model. (e.g. $ scope.model) This is consistent, otherwise you would not have WMD but a MVVM Application. But one can also easily argue that the $ scope is clearly a ViewModel in the sense of MVVM.
The above example is a little messy, because we manipulate the $ scope directly in the view (for the sake of brevity). In this case we add a newly created property "model" to the. However, the scope should not be changed in the view, this is the responsibility of the controller. You can find a clean example in the second demo.
In the world of Angular there is no rule about modeling. The model is the "business logic" of the application that is beyond Angular's control. The $ scope is therefore not understood as "the business logic". The scope always only contains references to the model, which can consist of one or more objects:
By using this, we are disrupting the well-known AngularJS recommendation that one point must always be used at one point. (E.g. here So there are no surprises if with primitive types (like the string whose values are copied) the model cannot apparently be changed with two-way bindings (see "Scope inheritance" in Understanding Scopes)
Is it possible to change?
An exchange of the MVVM engines is possible, since AngularJS basically covers the functional scope of Knockout.js and also expands it. Both engines use the DOM as a view, so that not everything has to be rewritten. The directives can help minimize the number of lines of code. There will definitely be stumbling blocks due to the fact that an AngularJS model is not "observable". This principle is called "dirty checking". Behind the scenes, AngularJS puts a so-called list for each binding. (Info on $ watch and $ digest) The watches are used to detect changes. In addition, there are standard functions such as or, which take dirty checking into account. In most of them Changes are recognized correctly in cases, but intensive testing is necessary to be really sure.
In every template language there is an option to avoid repetitive code. In this example, it is advisable to outsource the yellow sticky note - so that it can be used several times.
In Knockout this can be done directly via the binding.
An equivalent functionality can be found in AngularJs with Custom directives to implement. In addition to the directives already mentioned (e.g.), you can specify your own directives with a simple command. There are hardly any limits to the freedom of design, a self-created directive can be applied to a DOM element, DOM attribute, a CSS class name or a comment. The following example uses a DOM element "sticky-note" because the resulting source text is so easy to read.
The directive replaces all elements called "sticky-note" and uses the markup from here. The content of "angular.tmpl.html" corresponds to the code previously used:
Is it possible to change?
The change from Knockout to Angular should be relatively unproblematic with regard to existing co-templates. It is of course imperative to port existing co-bindings here as well. However, the principle of the templates is comparable in both frameworks and, with the corresponding manual effort, can be transferred without any surprises. Compared to the templates from Knockout, Angular directives are much more flexible, but still easy and understandable to use. The good documentation on the topic makes the switch easier.
2.3. Modular code
Knockout does not require the use of modules. The developer is completely free to structure the ViewModel or the initialization code according to his own ideas. (Unfortunately, this leads to a lot of KO code that is not structured at all.) However, if knockout is executed at a time when either the CommonJs or an AMD loader (such as require.js) has been executed, so Knockout presents itself as corresponding module. (KO uses a variation of the UMD (Universal Module Definition) pattern)
The following example shows how a ViewModel specifies Knockout as a dependency. This works without any special adjustments:
Unlike AngularJS, Knockout never takes the lead. It sees itself as one of many modules of an application and leaves it to the developer to design a more or less modular architecture.
AMD is just a little bit of dependency injection
- a) the returned module has properties that are to be used directly (i.e. the module behaves like a singleton),
- b) it should be called as a function or
- c) it is e.g. a constructive function which is to be called with the keyword.
AMD / Require.js can be seen as a puristic service locator. Exchanging dependencies for test purposes is possible (as described here, for example), but a bit cumbersome. Working with AMD can be described as a "Dependency Injection" light. After all, you don't always get instantiated dependencies, you have to instantiate the modules or properties / parts of the module yourself. There are simply no strict specifications in AMD format that would allow the module or parts of the module to be instantiated directly by the module loader.
Modular AngularJS code was already used in the previous examples. AngularJS uses its own module format, in which Angular modules are generated by the command. You have to make sure that two completely different concepts meet here:
AngularJS modules use the various methods of the $ provide-service to configure the $ injector, which can assemble a finished object at runtime. For this purpose, the $ injector can instantiate types, execute methods and also load additional modules. The finished object contains one or more Services. Services are always singletons.
In AMD you get a module. There are no further requirements.
At Angular you get a module that contains several named Services may contain. With these conventions to be adhered to, one can achieve a fully-fledged "Dependency Injecton" - especially in terms of testability. The difference between the various $ provide methods (Service, Factory & Provider) is described in detail in the Developer Guide. In short, the following three providers each create a service that has a HelloWorld method.
If you want to use the functionality of the services, you can accept this service as a function parameter:
Before calling the controller, the $ injector checks the signature of the function ("Reflection" via .toString ()) and then "injected" the desired service. It is therefore very important to pay attention to the exact spelling of the function parameters. AMD does not have a comparable comfortable use.
Is it possible to change?
As has been shown, AMD modules and Angular modules are two concepts that have different priorities. With a few small adjustments, both concepts can be combined. In this way, AMD code can be transferred from the knockout world to the Angular world. This is strongly recommended because it is very impractical or error-prone to combine synchronous and asynchronous code with one another. (You either rely entirely on AMD or not at all!)
However, you can no longer use the directive because it is already evaluated during the browser event in the course of the automatic bootstrapping. At this point in time, the asynchronous modules have not yet been loaded.
Therefore, bootstrapping should only be started when require.js has loaded all modules. The standard module is ideal for this. It is now possible to enclose an Angular module with an AMD module without any problems:
One more principle is still missing, which is essential for a SPA: Client-side routing.
"Routing" means that the application can switch between views and update the browser history in the process. This makes it possible to use the browser's "Back" and "Forward" buttons as usual. The routing should also ensure that you can jump to any view by calling up the corresponding URL in the browser. If the routing is well implemented, it is no longer clear to the user whether it is a "classic" application with several HTML pages or a SPA (although the advantages of single-page, such as fast loading times, should of course be retained) .
Knockout does not offer routing out of the box. It makes sense to either rely on Durandal or to implement the principle yourself with one of the many routing libraries available. Examples include Sammy.js, FinchJS or Director.
How a solid routing with knockout can be implemented is part of the following documentation.
It boils down to developing a module that holds the state (here the "appState.js" file with Sammy.js) and thus encapsulates the routing. This routing file can then instruct another module to load a view and a view model, depending on the route, and to execute them with knockout. That module is simply called "app", you could also call this module "controller". This is what this central routing file looks like in this example:
The biggest problem with the present knockout example is the unnecessarily high complexity and lack of standardization. It would be much more advantageous if the existing MVVM framework already offered all the necessary functionalities. This is exactly what AngularJS offers.
One could argue that Durandal (the best known SPA framework for KO) provides the necessary standardization, but Durandal is no longer being developed in favor of AngularJS!
Angular relies on the $ routeProvider, which monitors the history and, if necessary, loads a template and calls the appropriate controller.The usage is easy to see. You define a directive
configured according to:
and defines a suitable list template (templates / list.html):
It is difficult to come to a conclusion. It is obvious that Knockout alone offers very little functionality. But it is quite possible that you already have an excellent architecture with knockout as an MVVM engine. In this case you should stick with Knockout, because Knockout is constantly being developed and maintained. I would recently advise against an "upgrade" to Durandal, since Durandal and AngularJS are not expected to introduce any new innovations due to the convergence of Durandal.
If you do not have an excellent architecture ("historically grown"), then it makes sense to switch to AngularJS. The makers of AngularJS have already made many architectural decisions for you. Due to the modular architecture and the good testability, the new generation of "bad code" is sufficiently avoided!
4. Downloads & Links
You can find this document at: http://bit.ly/Ko2NgDocs
You can find the presentation here: http://bit.ly/Ko2NgSlides
The full-length examples are available on Github:
(Folder: / Slides / examples /)
© 2014, Johannes Hoppe
- Which country is this coin of 1
- Karaoke is still popular
- What's your rating of ABS CBN
- What is human capital in business
- What are cobalt properties
- President Obama was calm in stressful situations
- Why is Audible so expensive and limited
- Why is CoffeeScript so popular
- What is quantitative study in sociology
- Are kind of bars gluten free
- Which custom ROM has the best features
- What is Herokus' business model
- Where can I find web designers
- Can the gravitational energy be quantized
- We live in a timeless reality
- Are there community guidelines for Quora?
- Why do testosterone levels drop
- Which bank has the highest ATMs
- What is the best cure for distractibility
- Are carrier bags actually environmentally friendly?
- What is parenting
- What is the purpose of standardizing data
- What are great ideas for a honeymoon