diff --git a/src/generators/dom/visitors/Element/Attribute.ts b/src/generators/dom/visitors/Element/Attribute.ts index 7fbb73394bf5..14f68b5a5e01 100644 --- a/src/generators/dom/visitors/Element/Attribute.ts +++ b/src/generators/dom/visitors/Element/Attribute.ts @@ -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' @@ -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); diff --git a/src/validate/html/validateElement.ts b/src/validate/html/validateElement.ts index 081fea60288b..6433ba8a2b9e 100644 --- a/src/validate/html/validateElement.ts +++ b/src/validate/html/validateElement.ts @@ -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( @@ -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 `, attribute.start @@ -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( @@ -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' ); @@ -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; diff --git a/test/runtime/samples/attribute-dynamic-type/_config.js b/test/runtime/samples/attribute-dynamic-type/_config.js new file mode 100644 index 000000000000..93a4e28acd6f --- /dev/null +++ b/test/runtime/samples/attribute-dynamic-type/_config.js @@ -0,0 +1,19 @@ +export default { + 'skip-ssr': true, + + data: { + inputType: 'text', + inputValue: 42 + }, + + html: ``, + + 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'); + } +}; diff --git a/test/runtime/samples/attribute-dynamic-type/main.html b/test/runtime/samples/attribute-dynamic-type/main.html new file mode 100644 index 000000000000..5bafd96cb361 --- /dev/null +++ b/test/runtime/samples/attribute-dynamic-type/main.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/validator/samples/binding-input-static-type/errors.json b/test/validator/samples/binding-input-static-type/errors.json new file mode 100644 index 000000000000..fbc8284ec4d6 --- /dev/null +++ b/test/validator/samples/binding-input-static-type/errors.json @@ -0,0 +1,8 @@ +[{ + "message": "'type' attribute cannot be dynamic if input uses two-way binding", + "loc": { + "line": 1, + "column": 24 + }, + "pos": 24 +}] \ No newline at end of file diff --git a/test/validator/samples/binding-input-static-type/input.html b/test/validator/samples/binding-input-static-type/input.html new file mode 100644 index 000000000000..4f54010bdc4a --- /dev/null +++ b/test/validator/samples/binding-input-static-type/input.html @@ -0,0 +1 @@ + \ No newline at end of file