model.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /* @flow */
  2. /**
  3. * Expand input[v-model] with dyanmic 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. getBindingAttr,
  13. getAndRemoveAttr
  14. } from 'compiler/helpers'
  15. import {
  16. processFor,
  17. processElement,
  18. addIfCondition,
  19. createASTElement
  20. } from 'compiler/parser/index'
  21. function preTransformNode (el: ASTElement, options: CompilerOptions) {
  22. if (el.tag === 'input') {
  23. const map = el.attrsMap
  24. if (map['v-model'] && (map['v-bind:type'] || map[':type'])) {
  25. const typeBinding: any = getBindingAttr(el, 'type')
  26. const ifCondition = getAndRemoveAttr(el, 'v-if', true)
  27. // 1. checkbox
  28. const branch0 = cloneASTElement(el)
  29. // process for on the main node
  30. processFor(branch0)
  31. addRawAttr(branch0, 'type', 'checkbox')
  32. processElement(branch0, options)
  33. branch0.processed = true // prevent it from double-processed
  34. branch0.if = `type==='checkbox'` + (ifCondition ? `&&(${ifCondition})` : ``)
  35. addIfCondition(branch0, {
  36. exp: branch0.if,
  37. block: branch0
  38. })
  39. // 2. add radio else-if condition
  40. const branch1 = cloneASTElement(el)
  41. getAndRemoveAttr(branch1, 'v-for', true)
  42. addRawAttr(branch1, 'type', 'radio')
  43. processElement(branch1, options)
  44. addIfCondition(branch0, {
  45. exp: `type==='radio'` + (ifCondition ? `&&(${ifCondition})` : ``),
  46. block: branch1
  47. })
  48. // 3. other
  49. const branch2 = cloneASTElement(el)
  50. getAndRemoveAttr(branch2, 'v-for', true)
  51. addRawAttr(branch2, ':type', typeBinding)
  52. processElement(branch2, options)
  53. addIfCondition(branch0, {
  54. exp: ifCondition,
  55. block: branch2
  56. })
  57. return branch0
  58. }
  59. }
  60. }
  61. function cloneASTElement (el) {
  62. return createASTElement(el.tag, el.attrsList.slice(), el.parent)
  63. }
  64. function addRawAttr (el, name, value) {
  65. el.attrsMap[name] = value
  66. el.attrsList.push({ name, value })
  67. }
  68. export default {
  69. preTransformNode
  70. }