Skip to main content

Injecting logic into angular.js two-way binding pipeline

Recently I was implementing a small workaround solution for angular.js date input control and discovered useful $parsers/$formatters pipeline of NgModelController (controller of ng-model directive).
In the following example, ngModel is an instance of ng-model directive controller. We get a single instance of it per DOM element.

Many HTML element directives may interact with ngModel, each putting parser handlers to the beginning of parsing pipeline and formatter handlers to the end of formatting pipeline. These pipelines transform values between ngModel.$viewValue (what you see) and ngModel.$modelValue (what you get in your model). Using directive priority setting, one can ensure that $parsers and $formatters are in the correct order.
The problem with the control was that it did not support manual date entry. We were using old version of angular.js, without ng-model-options support, so on every keystroke, this control tried to convert input string value to date object. This obviously failed in the middle of entry and input was being cleared.
So easy workaround in our case was to create new directive with higher priority setting and put a function in the beginning of parsing pipeline. This function would simply transform input value into necessary state for the input control to work correctly.
Obviously, these pipelines are not for workarounds only. They may be very useful, when implementing custom controls and combining them with any 3rd party solutions.

Comments

Popular posts from this blog

Nginx secure link with node.js

Serving static files is a natural task for web servers. They, especially ones, having asynchronous architecture (like Nginx), are very good at such tasks. However, usually there is an additional security logic, which should restrict access to files you've published. IIS, for example, offers deep integration with application layer, which allows custom .NET "middleware" logic injection into the request pipeline. Node.js applications are very often published behind Nginx for various reasons and, with the help of Nginx "Secure Link" module, it's possible to offload static file serving tasks from node.js to Nginx, even if the files are not public. This module uses "shared secret" string (known to Nginx and the application) and expects a hash, based on this secret, to be present in the request to decide whether to proceed or return an error. Secure Link module may work in 2 alternative modes ( http://nginx.org/en/docs/http/ngx_http_secure_link_modul...

Performance of Redis sorted set operations

I was working on a feature recently, which involved several Redis "remove from sorted set" operations. Target production environment sorted sets are expected to be small and most of these calls would be trying to remove items, which do not exist in the sets. Although ZREM operation has documented LON(N) time complexity, ZSCORE has documented constant time complexity. This led me to believe, that Redis might have constant time complecity for ZREM calls when values to be removed do not exist in the set (if ZSCORE "knows" if item is NOT in the set in constant time, ZREM can do the same, right?). Not in this case, apparently. ZSCORE documented constant time complexity is actually misleading (as many cases of asymptotic time complexity documentation for small data sets). Redis stores small sorted sets (up to 128 items by default) as "ziplists", which are essentially linked lists, optimized for memory consumption. Browsing through Redis source code confirms th...

Lost promises

I love Promises . I think they make modern JavaScript possible, especially on the server side. But promises are, you know, promises and some of them are literally lost! I would even say that lost promises are, to a certain degree, the buffer overflow of JavaScript. OK, it's not as widespread and it hasn't cost as many billions of dollars, but it still may be as subtle, as difficult to notice and just as devastating. At least I have encountered this issue a few times and it works like that: In the code above we simply forget to add "return" keyword before call to sideEffect3 function. This is totally OK, except when you rely on the fact that the Promise returned from giveMePromise is resolved after "side effect 3" can be observed. In our case, Promise was given, but it was lost. That sideEffect3  function is trying in vain, because it's work will never be used. I think this is just a danger of asynchronous code and such errors can only be detecte...