diff --git a/packages/ember-htmlbars/tests/helpers/input_test.js b/packages/ember-htmlbars/tests/helpers/input_test.js
index 50f735a34e5..cedd56a72cf 100644
--- a/packages/ember-htmlbars/tests/helpers/input_test.js
+++ b/packages/ember-htmlbars/tests/helpers/input_test.js
@@ -8,6 +8,10 @@ import ComponentLookup from "ember-views/component_lookup";
import TextField from 'ember-views/views/text_field';
import Checkbox from 'ember-views/views/checkbox';
import EventDispatcher from 'ember-views/system/event_dispatcher';
+import {
+ disableInputTypeChanging,
+ resetInputTypeChanging
+} from 'ember-views/system/build-component-template';
var view;
var controller, registry, container;
@@ -265,6 +269,48 @@ QUnit.test("should change if the type changes", function() {
equal(view.$('input').attr('type'), 'text', "it changes after the type changes");
});
+QUnit.module("{{input type='text'}} - dynamic type in IE8 safe environment", {
+ setup() {
+ commonSetup();
+
+ disableInputTypeChanging();
+
+ controller = {
+ someProperty: 'password',
+ ie8Safe: true
+ };
+
+ view = View.extend({
+ container: container,
+ controller: controller,
+ template: compile('{{input type=someProperty}}')
+ }).create();
+
+ runAppend(view);
+ },
+
+ teardown() {
+ resetInputTypeChanging();
+
+ runDestroy(view);
+ runDestroy(container);
+ }
+});
+
+QUnit.test("should insert a text field into DOM", function() {
+ equal(view.$('input').attr('type'), 'password', "a bound property can be used to determine type in IE8.");
+});
+
+QUnit.test("should NOT change if the type changes", function() {
+ equal(view.$('input').attr('type'), 'password', "a bound property can be used to determine type in IE8.");
+
+ run(function() {
+ set(controller, 'someProperty', 'text');
+ });
+
+ equal(view.$('input').attr('type'), 'password', "it does NOT change after the type changes in IE8");
+});
+
QUnit.module("{{input}} - default type", {
setup() {
commonSetup();
diff --git a/packages/ember-views/lib/system/build-component-template.js b/packages/ember-views/lib/system/build-component-template.js
index d6957caafa4..f57e9fd57b3 100644
--- a/packages/ember-views/lib/system/build-component-template.js
+++ b/packages/ember-views/lib/system/build-component-template.js
@@ -26,7 +26,7 @@ export default function buildComponentTemplate({ component, layout, isAngleBrack
// element. We use `manualElement` to create a template that represents
// the wrapping element and yields to the previous block.
if (tagName !== '') {
- var attributes = normalizeComponentAttributes(component, isAngleBracket, attrs);
+ var attributes = normalizeComponentAttributes(component, isAngleBracket, attrs, tagName);
var elementTemplate = internal.manualElement(tagName, attributes);
elementTemplate.meta = meta;
@@ -43,6 +43,30 @@ export default function buildComponentTemplate({ component, layout, isAngleBrack
return { createdElement: !!tagName, block: blockToRender };
}
+// Static flag used to see if we can mutate the type attribute on input elements. IE8
+// does not support changing the type attribute after an element is inserted in
+// a tree.
+var isInputTypeAttributeMutable = (function() {
+ var docFragment = document.createDocumentFragment();
+ var mutableInputTypeTextElement = document.createElement('input');
+ mutableInputTypeTextElement.type = 'text';
+ try {
+ docFragment.appendChild(mutableInputTypeTextElement);
+ mutableInputTypeTextElement.setAttribute('type', 'password');
+ } catch (e) {
+ return false;
+ }
+ return true;
+})();
+
+var canChangeInputType = isInputTypeAttributeMutable;
+export function disableInputTypeChanging() {
+ canChangeInputType = false;
+}
+export function resetInputTypeChanging() {
+ canChangeInputType = isInputTypeAttributeMutable;
+}
+
function blockFor(template, options) {
Ember.assert("BUG: Must pass a template to blockFor", !!template);
return internal.blockFor(render, template, options);
@@ -113,7 +137,8 @@ function tagNameFor(view) {
// Takes a component and builds a normalized set of attribute
// bindings consumable by HTMLBars' `attribute` hook.
-function normalizeComponentAttributes(component, isAngleBracket, attrs) {
+function normalizeComponentAttributes(component, isAngleBracket, attrs, tagName) {
+ var hardCodeType = tagName === 'input' && !canChangeInputType;
var normalized = {};
var attributeBindings = component.attributeBindings;
var i, l;
@@ -135,17 +160,32 @@ function normalizeComponentAttributes(component, isAngleBracket, attrs) {
if (colonIndex !== -1) {
var attrProperty = attr.substring(0, colonIndex);
attrName = attr.substring(colonIndex + 1);
- expression = ['get', 'view.' + attrProperty];
+
+ if (attrName === 'type' && hardCodeType) {
+ expression = component.get(attrProperty) + '';
+ } else {
+ expression = ['get', 'view.' + attrProperty];
+ }
} else if (attrs[attr]) {
// TODO: For compatibility with 1.x, we probably need to `set`
// the component's attribute here if it is a CP, but we also
// probably want to suspend observers and allow the
// willUpdateAttrs logic to trigger observers at the correct time.
attrName = attr;
- expression = ['value', attrs[attr]];
+
+ if (attrName === 'type' && hardCodeType) {
+ expression = getValue(attrs[attr]) + '';
+ } else {
+ expression = ['value', attrs[attr]];
+ }
} else {
attrName = attr;
- expression = ['get', 'view.' + attr];
+
+ if (attrName === 'type' && hardCodeType) {
+ expression = component.get(attr) + '';
+ } else {
+ expression = ['get', 'view.' + attr];
+ }
}
Ember.assert('You cannot use class as an attributeBinding, use classNameBindings instead.', attrName !== 'class');
diff --git a/packages/ember-views/lib/views/text_field.js b/packages/ember-views/lib/views/text_field.js
index 629c82a2e74..b9e9b2bd35c 100644
--- a/packages/ember-views/lib/views/text_field.js
+++ b/packages/ember-views/lib/views/text_field.js
@@ -98,7 +98,9 @@ export default Component.extend(TextSupport, {
value: "",
/**
- The `type` attribute of the input element.
+ The `type` attribute of the input element. To remain compatible with IE8, this
+ cannot change after the element has been rendered. It is suggested to avoid using
+ a dynamic type attribute if you are supporting IE8 since it will be set once and never change.
@property type
@type String