-
Notifications
You must be signed in to change notification settings - Fork 27.5k
ngRepeat does not support free-style code #5537
Comments
I, too, have noticed certain multiline expressions do not work (while others do), and ngRepeat was one of those "does not work" ones. I always assumed it was for performance issues, or some other wise purpose. But if it's not... then certainly multiline ngRepeat would be great for readability as it can (with reasonable frequency) be a pretty long one. |
This has been fixed in #5000. |
That fix in #5000 looks just as bad as the one before the fix. It fixes only one use case, others may have different style for some reason, for example what if I want to start with a newline? |
The regexp merged in #5000, var match = expression.match(/^\s*(.+)\s+in\s+([\r\n\s\S]*?)\s*(\s+track\s+by\s+(.+)\s*)?$/) will match:
Optionally followed by:
So, this regexp is kind of crazy... some parts of it don't seem to make any rational sense. but I'm not seeing how the "extraneous spaces" example would fail with it. |
Anyways, I think I see what you're saying, the Unfortunately, making this match greedy sort of breaks the trackByExp portion. Since we don't have positive lookbehind in JS, one thing we could do is split this into multiple matches: match = expression.match(/^\s*(.+)\s+in\s+(.+)$/);
lhs = match[1];
rhs = match[2];
match = rhs.match(/\s+track\s+by\+(.+)$/);
if (match) {
rhs = rhs.substr(0, rhs.length - match[0].length);
trackByExp = match[1];
} This way you can have a greedy and correct match for the rhs expression... The issue with this is that it could potentially hurt performance, and we don't want that. But it should be an easy patch to write if you care to write it, and perhaps we could consider if it's worth merging. edit > /^\s*([\s\S]+?)\s+in\s+([\s\S]+)$/m.exec('item de\nferp\nin\nitems \nok\ntrack by f')
[ 'item de\nferp\nin\nitems \nok\ntrack by f',
'item de\nferp',
'items \nok\ntrack by f',
index: 0,
input: 'item de\nferp\nin\nitems \nok\ntrack by f' ] |
@caitp, first of all, sorry for the confusion. I mixed up DOTALL and MULTILINE modes and semantics of I took a closer look at ECMA-262 and found out that JavaScript does not support DOTALL mode: To support line wrapping at any possible position (re your edit in last comment): Based on the above I think all dots should be replaced by Extraneous space elaboration (re "but I'm not seeing how the "extraneous spaces" example would fail with it.)": I was referencing /^\s*(.+)\s+in\s+([\r\n\s\S]*?)\s*(\s+track\s+by\s+(.+)\s*)?$/.exec("item in items")
["item in items", "item ", "items", undefined, undefined] Note the extra space in the first capturing group. Since Resolution: I'll try to craft a PR for the regex below to allow anything possible and have only one regex (the test provided here contains random newlines and shows how flexible it could be given $parser could handle it): /^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/
.exec('item \t\n \t in \n \t\n\n deep .\nitems \t\t\n | filter:\n\n{\n\t prop:\n\n "track by $index"\n\n}\n\n | orderBy:"name" \n\n track \t\n by \n\n\t $index \t\n ') Curiosity: Do you happen to know why /^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/.exec("item in ") matches and puts a |
I think @TWiStErRob summed it up pretty well 👍 |
http://plnkr.co/edit/Z6sILlb9hU9OLSA553VZ?p=preview here's a quick demo with the current implementation --- it will fail if the lhs expression has trailing whitespace before a newline (for example), or if there are two spaces before So it's a bit finicky, but maybe it's not such a problem as people typically don't use weird styles. I'm not sure. |
Hi all, Thanks! |
I think @TWiStErRob is working on it. |
…ssion With this change it's possible to split the ng-repeat expression into multiple lines at any point in the expression where white-space is expected. Closes angular#5537 Closes angular#5598
…ssion With this change it's possible to split the ng-repeat expression into multiple lines at any point in the expression where white-space is expected. Closes angular#5537 Closes angular#5598
The following uses of ng-repeat result in some kind of error, however they should be valid if parsed by
$parser
:Extraneous spaces
note: two spaces after
item
.Multiline code
The regular expression at
ngRepeatDirective
'slink
is too restrictive.To fix the first problem don't be greedy when matching the variable name (
\1
:(.+)
VS(.+?)
[probably\4
should be non-greedy too, though I could not come it with anything to break it]:/^\s*(.+?)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/
To fix the second problem, use "dot matches newline"/"multiline mode", i.e.
/regex/m
:/^\s*(.+?)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/m
I was trying to trick angular.js to ignore them in different ways, for example declarding
ng-repeat
as non-CDATA
in DTD to make it drop the whitespaces, but it didn't work. See XHTML 1.1 @ 4.7 and XHTML @ 3.3.3: everything undeclared is CDATA, hence no normalization.The text was updated successfully, but these errors were encountered: