On our latest project written in Angular, a co-worker of mine was faced with a problem which caught my attention. I decided to dive a bit deeper into it, as well as researching the reasons behind this behaviour and possible solutions.
On a certain part of the application the user was presented with data on a table. The table was constructed by utilizing an ng-repeat, which iterated over a list of elements consisting of a somewhat complicated nested structure. I don’t want to go deeper behind this choice, but to put it in a few words; It was simply not worth it to transform the data, specially since it was already neatly packaged and fed to us by our ORM, in this case Sequelize.
Problems arose when the user wanted to clone a row in this table. My first though was to simply encode and decode this row into Json back and forth, to later slice it into the array. This did however not work; ng-repeat did not like this newly cloned row. The error message told me the repeater couldn’t handle duplicated elements in the array, this was a major clue.
Some research showed me that in order for the ng-repeat to handle identical elements, Angular adds some key-value pairs of its own, preceded by two dollar signs. The problem was due to the fact that Json.stringify didn’t take this Angular-specific values into consideration, happily cloning these as well thus creating completely identical elements.
The solution lay within Angular itself. By utilizing angular.toJson and angular.fromJson this problem was easily avoided. Taking a look behind the hood reveals the magic, angular.toJson strips off any Angular specific values. Once the newly created element was sliced into the array it automagically received a new set of fresh $$-led values which ng-repeat happily accepted.
Some last words
For more complicated use cases consider Angulars method for deep cloning.