Skip to content

Commit

Permalink
only enforce static type if input is bound (fixes #620)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Jun 11, 2017
1 parent 6eb80e3 commit ff40308
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 8 deletions.
7 changes: 3 additions & 4 deletions src/generators/dom/visitors/Element/Attribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ export default function visitAttribute(
const isIndirectlyBoundValue =
name === 'value' &&
(node.name === 'option' || // TODO check it's actually bound
(node.name === 'input' &&
/^(checkbox|radio)$/.test(getStaticAttributeValue(node, 'type'))));
(node.name === 'input' && node.attributes.find((attribute: Node) => attribute.type === 'Binding' && /checked|group/.test(attribute.name))));

const propertyName = isIndirectlyBoundValue
? '__value'
Expand Down Expand Up @@ -133,8 +132,8 @@ export default function visitAttribute(
const statement = propertyName
? `${state.parentNode}.${propertyName} = ${value};`
: `${generator.helper(
method
)}( ${state.parentNode}, '${name}', ${value} );`;
method
)}( ${state.parentNode}, '${name}', ${value} );`;

block.builders.create.addLine(statement);

Expand Down
10 changes: 6 additions & 4 deletions src/validate/html/validateElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export default function validateElement(validator: Validator, node: Node) {
attribute.start
);
}

checkTypeAttribute(validator, node);
} else if (name === 'checked') {
if (node.name !== 'input') {
validator.error(
Expand All @@ -33,7 +35,7 @@ export default function validateElement(validator: Validator, node: Node) {
);
}

if (getType(validator, node) !== 'checkbox') {
if (checkTypeAttribute(validator, node) !== 'checkbox') {
validator.error(
`'checked' binding can only be used with <input type="checkbox">`,
attribute.start
Expand All @@ -47,7 +49,7 @@ export default function validateElement(validator: Validator, node: Node) {
);
}

const type = getType(validator, node);
const type = checkTypeAttribute(validator, node);

if (type !== 'checkbox' && type !== 'radio') {
validator.error(
Expand Down Expand Up @@ -128,7 +130,7 @@ export default function validateElement(validator: Validator, node: Node) {
});
}

function getType(validator: Validator, node: Node) {
function checkTypeAttribute(validator: Validator, node: Node) {
const attribute = node.attributes.find(
(attribute: Node) => attribute.name === 'type'
);
Expand All @@ -139,7 +141,7 @@ function getType(validator: Validator, node: Node) {
}

if (attribute.value.length > 1 || attribute.value[0].type !== 'Text') {
validator.error(`'type attribute cannot be dynamic`, attribute.start);
validator.error(`'type' attribute cannot be dynamic if input uses two-way binding`, attribute.start);
}

return attribute.value[0].data;
Expand Down
19 changes: 19 additions & 0 deletions test/runtime/samples/attribute-dynamic-type/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export default {
'skip-ssr': true,

data: {
inputType: 'text',
inputValue: 42
},

html: `<input type="text">`,

test(assert, component, target) {
const input = target.querySelector('input');
assert.equal(input.type, 'text');
assert.equal(input.value, '42');

component.set({ inputType: 'number' });
assert.equal(input.type, 'number');
}
};
1 change: 1 addition & 0 deletions test/runtime/samples/attribute-dynamic-type/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<input type='{{inputType}}' value='{{inputValue}}'>
8 changes: 8 additions & 0 deletions test/validator/samples/binding-input-static-type/errors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[{
"message": "'type' attribute cannot be dynamic if input uses two-way binding",
"loc": {
"line": 1,
"column": 24
},
"pos": 24
}]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<input bind:value='foo' type='{{inputType}}'>

0 comments on commit ff40308

Please sign in to comment.