Skip to content
Permalink
Browse files

fix(input): 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.
  • Loading branch information
petebacondarwin committed Oct 7, 2016
1 parent 138fbf0 commit 298f8c4d13fbaa104845619e5518cb03c2aad05b
Showing with 36 additions and 6 deletions.
  1. +9 −6 src/ng/directive/input.js
  2. +10 −0 test/e2e/fixtures/input-hidden/index.html
  3. +17 −0 test/e2e/tests/input-hidden.spec.js
@@ -2002,13 +2002,16 @@ var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
return {
restrict: 'E',
require: ['?ngModel'],
link: {
pre: function(scope, element, attr, ctrls) {
if (ctrls[0]) {
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
$browser, $filter, $parse);
compile: function(tElement, tAttr) {
if (lowercase(tAttr.type) === 'hidden') tAttr.$set('autocomplete', 'off');
return {
pre: function(scope, element, attr, ctrls) {
if (ctrls[0]) {
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
$browser, $filter, $parse);
}
}
}
};
}
};
}];
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html ng-app>
<body>
<form>
<input type="hidden" value="{{value}}" />
<button ng-click="value = '{{ 7 * 6 }}'">Click me</button>
</form>
<script src="angular.js"></script>
</body>
</html>
@@ -0,0 +1,17 @@
'use strict';

describe('hidden thingy', function() {
it('should pass', function() {

loadFixture('input-hidden');
expect(element(by.css('input')).getAttribute('value')).toEqual('');

element(by.css('button')).click();
expect(element(by.css('input')).getAttribute('value')).toEqual('{{ 7 * 6 }}');

loadFixture('sample');
browser.driver.executeScript('history.back()');
var expectedValue = browser.params.browser === 'safari' ? '{{ 7 * 6 }}' : '';
expect(element(by.css('input')).getAttribute('value')).toEqual(expectedValue);
});
});

4 comments on commit 298f8c4

@TolonUK

This comment has been minimized.

Copy link

@TolonUK TolonUK replied Oct 11, 2016

Hi Pete, are you aware that when using angular v1.4.13 this breaks angular material checkboxes and date pickers which currently rely on the link attribute of the input object? v1.5.8 seems to work ok though.

Demo - http://codepen.io/anon/pen/gwzmzA (no ticks appear when the checkboxes are clicked - change the cdn links to 1.4.12 and it works ok)

Affected Angular Material lines
https://github.com/angular/material/blob/72d068593b7f353d32f8308870d2b0d1c7c759c9/src/components/checkbox/checkbox.js#L128
https://github.com/angular/material/blob/1b9245a675234f165cd273b8c9fc3dae4eb2b29b/src/components/datepicker/js/datepickerDirective.js#L395

Any idea whether this is an angular or material problem?

@petebacondarwin

This comment has been minimized.

Copy link
Member Author

@petebacondarwin petebacondarwin replied Oct 11, 2016

Thanks for highlighting this @TolonUK - never thought anyone would rely on that in their code!

@petebacondarwin

This comment has been minimized.

Copy link
Member Author

@petebacondarwin petebacondarwin replied Oct 11, 2016

We have fixed this in the 1.2.x, 1.4.x, 1.5.x and master branches; and have released new versions of 1.2 and 1.4. We hadn't yet released 1.5 or 1.6 so these have not had new releases.

The new 1.4 fix is 35f3a4a

@TolonUK

This comment has been minimized.

Copy link

@TolonUK TolonUK replied Oct 11, 2016

That's great, thanks Pete.

Please sign in to comment.
You can’t perform that action at this time.