{"action":"created","issue":{"url":"https://api.github.com/repos/riot/riot/issues/1915","repository_url":"https://api.github.com/repos/riot/riot","labels_url":"https://api.github.com/repos/riot/riot/issues/1915/labels{/name}","comments_url":"https://api.github.com/repos/riot/riot/issues/1915/comments","events_url":"https://api.github.com/repos/riot/riot/issues/1915/events","html_url":"https://github.com/riot/riot/issues/1915","id":167792773,"number":1915,"title":"each loops rely on object identity to sync dom state (aka key attribute)","user":{"login":"corps","id":593850,"avatar_url":"https://avatars.githubusercontent.com/u/593850?v=3","gravatar_id":"","url":"https://api.github.com/users/corps","html_url":"https://github.com/corps","followers_url":"https://api.github.com/users/corps/followers","following_url":"https://api.github.com/users/corps/following{/other_user}","gists_url":"https://api.github.com/users/corps/gists{/gist_id}","starred_url":"https://api.github.com/users/corps/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/corps/subscriptions","organizations_url":"https://api.github.com/users/corps/orgs","repos_url":"https://api.github.com/users/corps/repos","events_url":"https://api.github.com/users/corps/events{/privacy}","received_events_url":"https://api.github.com/users/corps/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/riot/riot/labels/answered","name":"answered","color":"000000"},{"url":"https://api.github.com/repos/riot/riot/labels/question","name":"question","color":"fbca04"}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2016-07-27T07:52:28Z","updated_at":"2016-07-27T08:38:12Z","closed_at":"2016-07-27T08:32:27Z","body":"## Help us to manage our issues by answering the following:\r\n\r\n1. Describe your issue:\r\n\r\nI have a case where the reference of an object in an each changes, due to some external event (loading ajax), which causes focus to be lost to any input on the inside of that loop. \r\n\r\nThis largely has to do with the fact that riotjs relies on object identity when diffing arrays elements.  That may be fine in many cases, but it really sucks when you can't control object identity (again, like in the case of loading in ajax).  I would also prefer not being required to do deep merge of a json response, since this is costly compared to \"swapping\" the as is object.\r\n\r\nI have a work around that literally creates a container that stablizes object identity for an array using a key function, but this would obviously be better server by actually supporting a (optional) key attribute on the each loop.\r\n\r\nFor reference to anyone else looking for a hack solution:\r\n\r\n```js\r\n// ref-container.js\r\nmodule.exports = function (keyF, subIsArray) {\r\n  var objects = {};\r\n\r\n  return function (array) {\r\n    var result = [];\r\n\r\n    for (var i = 0, len = array.length; i < len; ++i) {\r\n      var next = array[i];\r\n      var key = keyF(next, i);\r\n      var object = objects[key];\r\n      if (object == null) objects[key] = object = (subIsArray ? [] : {});\r\n\r\n      if (subIsArray) {\r\n        object.length = 0;\r\n        Array.prototype.push.apply(object, next);\r\n      } else {\r\n        for (var k in object) delete object[k];\r\n        for (var nk in next) object[nk] = next[nk];\r\n      }\r\n\r\n      result.push(object);\r\n    }\r\n\r\n    return result;\r\n  }\r\n};\r\n```\r\n\r\nWhich is used as so:\r\n\r\n```html\r\n<input type=\"text\" each={container(this.users)}>\r\n<script>\r\n  this.container = require(\"ref-container\")(function(o) { return o.id });\r\n  this.users = [{id: 1, name: \"Bob\"}, {id: 2, name: \"John\"}]; \r\n</script>\r\n```\r\n\r\n2. Can you reproduce the issue?\r\n\r\n[Try editing either text field, 5 seconds later an ajax event is simulated and focus is lost](http://jsfiddle.net/a7pft286/1/)\r\n\r\n3. On which browser/OS does the issue appear?\r\n\r\nAll\r\n\r\n4. Which version of Riot does it affect?\r\n\r\n2.5\r\n\r\n5. How would you tag this issue?\r\n\r\n  - [ ] Question\r\n  - [ ] Bug\r\n  - [ ] Discussion\r\n  - [x] Feature request\r\n  - [ ] Tip\r\n  - [ ] Enhancement\r\n  - [ ] Performance\r\n"},"comment":{"url":"https://api.github.com/repos/riot/riot/issues/comments/235522746","html_url":"https://github.com/riot/riot/issues/1915#issuecomment-235522746","issue_url":"https://api.github.com/repos/riot/riot/issues/1915","id":235522746,"user":{"login":"GianlucaGuarini","id":879612,"avatar_url":"https://avatars.githubusercontent.com/u/879612?v=3","gravatar_id":"","url":"https://api.github.com/users/GianlucaGuarini","html_url":"https://github.com/GianlucaGuarini","followers_url":"https://api.github.com/users/GianlucaGuarini/followers","following_url":"https://api.github.com/users/GianlucaGuarini/following{/other_user}","gists_url":"https://api.github.com/users/GianlucaGuarini/gists{/gist_id}","starred_url":"https://api.github.com/users/GianlucaGuarini/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GianlucaGuarini/subscriptions","organizations_url":"https://api.github.com/users/GianlucaGuarini/orgs","repos_url":"https://api.github.com/users/GianlucaGuarini/repos","events_url":"https://api.github.com/users/GianlucaGuarini/events{/privacy}","received_events_url":"https://api.github.com/users/GianlucaGuarini/received_events","type":"User","site_admin":false},"created_at":"2016-07-27T08:38:11Z","updated_at":"2016-07-27T08:38:11Z","body":"No reorder just update the expressions leaving the dom nodes where they are. Object loops trigger a full list re render because the items are not indexable: with no reorder you just force riot updating only the expressions. You can try also just converting your object into an indexable array"}}
{"actor":{"display_login":"GianlucaGuarini"}}