Skip to content

Commit 4c5966d

Browse files
fix($compile): ensure that hidden input values are correct after history.back
Due to the nature of some browser's PageCache/BFCache, returning to an Angular app sometimes causes `input[hidden]` elements to retain the last value that was stored before the page was navigated away from previously. This is particularly problematic if the input has an interpolated value. E.g. `<input type="hidden" value="{{ 1 + 2 }}">` since when the browser returns, instead of the original interpolation template, the HTML contains the previous value `<input type="hidden" value="3">`. This commit instructs the browser not to attempt to reinstate the previous value when navigating back in history by setting `autocomplete="off"` on the hidden input element element.
1 parent 1c0aa0c commit 4c5966d

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/ng/compile.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -2054,13 +2054,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
20542054
var nodeType = node.nodeType,
20552055
attrsMap = attrs.$attr,
20562056
match,
2057+
nodeName,
20572058
className;
20582059

20592060
switch (nodeType) {
20602061
case NODE_TYPE_ELEMENT: /* Element */
2062+
2063+
nodeName = nodeName_(node);
2064+
20612065
// use the node name: <directive>
20622066
addDirective(directives,
2063-
directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
2067+
directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective);
20642068

20652069
// iterate over the attributes
20662070
for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
@@ -2102,6 +2106,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
21022106
attrEndName);
21032107
}
21042108

2109+
if (nodeName === 'input' && node.getAttribute('type') === 'hidden') {
2110+
// Hidden input elements can have strange behaviour when navigating back to the page
2111+
// This tells the browser not to try to cache and reinstate previous values
2112+
node.setAttribute('autocomplete', 'off');
2113+
}
2114+
21052115
// use class as directive
21062116
if (!cssClassDirectivesEnabled) break;
21072117
className = node.className;
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html ng-app>
3+
<body>
4+
<form>
5+
<input type="hidden" value="{{value}}" />
6+
<button ng-click="value = '{{ 7 * 6 }}'">Click me</button>
7+
</form>
8+
<script src="angular.js"></script>
9+
</body>
10+
</html>

test/e2e/tests/input-hidden.spec.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
describe('hidden thingy', function() {
4+
it('should pass', function() {
5+
6+
loadFixture('input-hidden');
7+
expect(element(by.css('input')).getAttribute('value')).toEqual('');
8+
9+
element(by.css('button')).click();
10+
expect(element(by.css('input')).getAttribute('value')).toEqual('{{ 7 * 6 }}');
11+
12+
loadFixture('sample');
13+
browser.driver.executeScript('history.back()');
14+
var expectedValue = browser.params.browser === 'safari' ? '{{ 7 * 6 }}' : '';
15+
expect(element(by.css('input')).getAttribute('value')).toEqual(expectedValue);
16+
});
17+
});

0 commit comments

Comments
 (0)