cb393ccb06a17ebfd136b6c091ea75dce10a84b8d80794cdff96df7a802abe95566e5c13e6a9d39854fa88c3b258d2e84ef56e3c0d89a55dc4428223c95ad5 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* @flow */
  2. /**
  3. * Expand input[v-model] with dynamic type bindings into v-if-else chains
  4. * Turn this:
  5. * <input v-model="data[type]" :type="type">
  6. * into this:
  7. * <input v-if="type === 'checkbox'" type="checkbox" v-model="data[type]">
  8. * <input v-else-if="type === 'radio'" type="radio" v-model="data[type]">
  9. * <input v-else :type="type" v-model="data[type]">
  10. */
  11. import {
  12. addRawAttr,
  13. getBindingAttr,
  14. getAndRemoveAttr
  15. } from 'compiler/helpers'
  16. import {
  17. processFor,
  18. processElement,
  19. addIfCondition,
  20. createASTElement
  21. } from 'compiler/parser/index'
  22. function preTransformNode (el: ASTElement, options: CompilerOptions) {
  23. if (el.tag === 'input') {
  24. const map = el.attrsMap
  25. if (!map['v-model']) {
  26. return
  27. }
  28. let typeBinding
  29. if (map[':type'] || map['v-bind:type']) {
  30. typeBinding = getBindingAttr(el, 'type')
  31. }
  32. if (!map.type && !typeBinding && map['v-bind']) {
  33. typeBinding = `(${map['v-bind']}).type`
  34. }
  35. if (typeBinding) {
  36. const ifCondition = getAndRemoveAttr(el, 'v-if', true)
  37. const ifConditionExtra = ifCondition ? `&&(${ifCondition})` : ``
  38. const hasElse = getAndRemoveAttr(el, 'v-else', true) != null
  39. const elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true)
  40. // 1. checkbox
  41. const branch0 = cloneASTElement(el)
  42. // process for on the main node
  43. processFor(branch0)
  44. addRawAttr(branch0, 'type', 'checkbox')
  45. processElement(branch0, options)
  46. branch0.processed = true // prevent it from double-processed
  47. branch0.if = `(${typeBinding})==='checkbox'` + ifConditionExtra
  48. addIfCondition(branch0, {
  49. exp: branch0.if,
  50. block: branch0
  51. })
  52. // 2. add radio else-if condition
  53. const branch1 = cloneASTElement(el)
  54. getAndRemoveAttr(branch1, 'v-for', true)
  55. addRawAttr(branch1, 'type', 'radio')
  56. processElement(branch1, options)
  57. addIfCondition(branch0, {
  58. exp: `(${typeBinding})==='radio'` + ifConditionExtra,
  59. block: branch1
  60. })
  61. // 3. other
  62. const branch2 = cloneASTElement(el)
  63. getAndRemoveAttr(branch2, 'v-for', true)
  64. addRawAttr(branch2, ':type', typeBinding)
  65. processElement(branch2, options)
  66. addIfCondition(branch0, {
  67. exp: ifCondition,
  68. block: branch2
  69. })
  70. if (hasElse) {
  71. branch0.else = true
  72. } else if (elseIfCondition) {
  73. branch0.elseif = elseIfCondition
  74. }
  75. return branch0
  76. }
  77. }
  78. }
  79. function cloneASTElement (el) {
  80. return createASTElement(el.tag, el.attrsList.slice(), el.parent)
  81. }
  82. export default {
  83. preTransformNode
  84. }