Use case: I have an object, where I want to control the sort/display order.
Using the code below, I can accomplish this with:
<div each="{ ckey,crow inkey [recordkeys,records] }">
</div>
{ "a":{"foo":"bar", "bar":"foo"},
"b":{"foo":1, "bar":2}
}
<div each="{ ckey,crow in records }">
</div>
But with a well-defined sort order instead; determined by the order in recordkeys. The current each={ ... in ... }
statement basically has an implementation-defined sort order which cannot be influenced deterministically.
commit 12d0441da420700cd56237cff6cca4512c52b8bf
Author: Stephen R. van den Berg <[email protected]>
Date: Mon Aug 29 15:57:42 2016 +0200
Support inkey keyword for each and sorted keylists.
diff --git a/lib/browser/tag/each.js b/lib/browser/tag/each.js
index d5394ad..2fd3ad6 100644
--- a/lib/browser/tag/each.js
+++ b/lib/browser/tag/each.js
@@ -31,8 +31,9 @@ import {
* @returns { Object } - new object containing the values of the original item
*
* The variables 'key' and 'val' are arbitrary.
- * They depend on the collection type looped (Array, Object)
+ * They depend on the collection type looped (Array, Object, [Array, Object])
* and on the expression used on the each tag
+ * The [Array, Object] variant is valid when the member inkey is true.
*
*/
export function mkitem(expr, key, val, base) {
@@ -119,15 +120,21 @@ export default function _each(dom, parent, expr) {
expr.update = function updateEach() {
// get the new items collection
var items = tmpl(expr.val, parent),
+ keys,
// create a fragment to hold the new DOM nodes to inject in the parent tag
frag = document.createDocumentFragment()
root = ref.parentNode
+ if (expr.inkey) {
+ keys = items[0]
+ items = items[1]
+ }
+
// object loop. any changes cause full redraw
if (!isArray(items)) {
hasKeys = items || false
items = hasKeys ?
- Object.keys(items).map(function (key) {
+ (keys || Object.keys(items)).map(function (key) {
return mkitem(expr, key, items[key])
}) : []
}
@@ -144,7 +151,8 @@ export default function _each(dom, parent, expr) {
// reorder only if the items are objects
var
- _mustReorder = mustReorder && typeof item == T_OBJECT && !hasKeys,
+ _mustReorder = mustReorder && typeof item == T_OBJECT &&
+ (!hasKeys || expr.inkey),
oldPos = oldItems.indexOf(item),
pos = ~oldPos && _mustReorder ? oldPos : i,
// does a tag exist in this position?
commit 6a6ae43b68f72c262c4ed242b009357e4452aed6
Author: Stephen R. van den Berg <[email protected]>
Date: Mon Aug 29 03:18:38 2016 +0200
Support inkey keyword for each and sorted keylists.
diff --git a/src/brackets.js b/src/brackets.js
index 45842a8..9c0460d 100644
--- a/src/brackets.js
+++ b/src/brackets.js
@@ -118,7 +118,7 @@ var brackets = (function (UNDEF) {
/\\({)|{/g, // $_RIX_OPEN
RegExp('\\\\(})|([[({])|(})|' + S_QBLOCKS, REGLOB), // $_RIX_CLOSE
DEFAULT, // $_RIX_PAIR
- /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/, // $_RIX_LOOP
+ /^\s*{\^?\s*([$\w]+)(?:\s*,\s*([$\w]+))?\s+in(key)?\s+(\S.*)\s*}/, // $_RIX_LOOP
/(^|[^\\]){=[\S\s]*?}/ // $_RIX_RAW
]
It's essentially the same as:
But with a well-defined sort order instead; determined by the order in recordkeys.
@@ -319,7 +319,8 @@ var brackets = (function (UNDEF) {
var m = expr.match(_cache[$_RIX_LOOP])
return m
- ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
+ ? { key: m[1], pos: m[2], val: _cache[0] + m[4].trim() + _cache[1],
+ inkey: m[3] === 'key' }
: { val: expr.trim() }
}