DropdownSearcher.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <template lang="pug">
  2. .searcher
  3. span.input-icon.fa.fa-search(@click='onClickOptions')
  4. input.search-input(v-model='search' :placeholder='placeholder' autofocus)
  5. .dropdown-options(:class="{'input-show': showOptions }")
  6. ul.input-options
  7. li.input-option(v-for='option in getOptions()' :key='option.id' @click='onSelectOption(option)') {{ option.name }}
  8. </template>
  9. <script>
  10. export default {
  11. props: {
  12. placeholder: {
  13. type: String,
  14. default: 'Buscar'
  15. },
  16. autofocus: {
  17. type: Boolean,
  18. default: false
  19. },
  20. items: {
  21. type: Array,
  22. default: [],
  23. required: true
  24. },
  25. keys: {
  26. type: Array,
  27. default: [],
  28. required: true
  29. }
  30. },
  31. watch: {
  32. search(value, lastValue) {
  33. value = value.trim()
  34. if (!value && value.length != lastValue.length) {
  35. this.selectedOption = null
  36. }
  37. this.showOptions = !!value && !this.selectedOption
  38. this.performSearch(value)
  39. }
  40. },
  41. methods: {
  42. getOptions() {
  43. return this.results.length == 0 ? this.items : this.results
  44. },
  45. performSearch(value) {
  46. this.results = []
  47. if (this.selectedOption) {
  48. return
  49. }
  50. for (let item of this.items) {
  51. for (let field in item) {
  52. if (typeof item[field] !== 'string') {
  53. continue
  54. }
  55. if (this.keys.length !== 0 && this.keys.indexOf(field) === -1) {
  56. continue
  57. }
  58. if (item[field].toLowerCase().indexOf(value.toLowerCase()) !== -1) {
  59. this.results.push(item)
  60. break
  61. }
  62. }
  63. }
  64. },
  65. onClickOptions() {
  66. this.showOptions = !this.showOptions || !!this.search
  67. },
  68. onSelectOption(item) {
  69. this.selectedOption = item
  70. this.search = item.name
  71. this.results = []
  72. this.$emit('onSelect', item)
  73. }
  74. },
  75. data() {
  76. return {
  77. search: '',
  78. results: [],
  79. selectedOption: null,
  80. showOptions: false
  81. }
  82. }
  83. }
  84. </script>
  85. <style lang="sass">
  86. @import '../../assets/variables'
  87. .searcher
  88. width: 100%
  89. height: 35px
  90. position: relative
  91. .input-icon
  92. position: absolute
  93. top: 14px
  94. right: 10px
  95. font-size: 12pt
  96. color: $app-dark-color
  97. &:hover
  98. cursor: pointer
  99. .search-input
  100. width: 100%
  101. height: 100%
  102. border-radius: 0
  103. font-size: 12pt
  104. font-weight: normal
  105. .dropdown-options
  106. display: none
  107. position: absolute
  108. background: $app-light-color
  109. border: 1px solid $app-separator-color
  110. box-shadow: 0 3px 5px $app-separator-color
  111. z-index: 10
  112. top: 45px
  113. left: 0
  114. right: 0
  115. bottom: -325px
  116. padding: 0
  117. animation-duration: 500ms
  118. overflow-y: auto
  119. &.input-show
  120. display: block
  121. ul
  122. li
  123. height: 35px
  124. display: block
  125. text-align: left
  126. margin: 10px 0 0 10px
  127. font-size: 12pt
  128. font-weight: normal
  129. border-bottom: 1px solid $app-border-color
  130. &:last-child
  131. margin-bottom: 10px
  132. &:hover
  133. border-bottom: 2px solid $app-main-color
  134. cursor: pointer
  135. </style>