DropdownSearcher.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 @keyup.enter='enterPressed')
  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[dispalyOption] }}
  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. dispalyOption :{
  31. type: Array,
  32. default: [],
  33. },
  34. acceptEnter: {
  35. type: Boolean,
  36. default: false
  37. }
  38. },
  39. watch: {
  40. search(value, lastValue) {
  41. value = value.trim()
  42. if (!value && value.length != lastValue.length) {
  43. this.selectedOption = null
  44. }
  45. this.showOptions = !!value && !this.selectedOption
  46. this.performSearch(value)
  47. }
  48. },
  49. methods: {
  50. enterPressed(){
  51. if(!this.acceptEnter)
  52. return
  53. let item = {
  54. 'item': this.search,
  55. 'state' : 'new'
  56. }
  57. if (this.getOptions().length === 1 && this.getOptions()[0].number === this.search)
  58. item = this.getOptions()[0]
  59. this.showOptions = false
  60. this.$emit('onSelect', item)
  61. },
  62. getOptions() {
  63. return this.results.length == 0 ? this.items : this.results
  64. },
  65. performSearch(value) {
  66. this.results = []
  67. if (this.selectedOption) {
  68. return
  69. }
  70. for (let item of this.items) {
  71. for (let field in item) {
  72. if (typeof item[field] !== 'string') {
  73. continue
  74. }
  75. if (this.keys.length !== 0 && this.keys.indexOf(field) === -1) {
  76. continue
  77. }
  78. if (item[field].toLowerCase().indexOf(value.toLowerCase()) !== -1) {
  79. this.results.push(item)
  80. break
  81. }
  82. }
  83. }
  84. },
  85. onClickOptions() {
  86. this.showOptions = !this.showOptions || !!this.search
  87. },
  88. onSelectOption(item) {
  89. this.selectedOption = item
  90. this.search = item[this.dispalyOption]
  91. this.results = []
  92. this.$emit('onSelect', item)
  93. }
  94. },
  95. data() {
  96. return {
  97. search: '',
  98. results: [],
  99. selectedOption: null,
  100. showOptions: false
  101. }
  102. }
  103. }
  104. </script>
  105. <style lang="sass">
  106. @import '../../assets/variables'
  107. .searcher
  108. width: 100%
  109. height: 35px
  110. position: relative
  111. .input-icon
  112. position: absolute
  113. top: 14px
  114. right: 10px
  115. font-size: 12pt
  116. color: $app-dark-color
  117. &:hover
  118. cursor: pointer
  119. .search-input
  120. width: 100%
  121. height: 100%
  122. border-radius: 0
  123. font-size: 12pt
  124. font-weight: normal
  125. .dropdown-options
  126. display: none
  127. position: absolute
  128. background: $app-light-color
  129. border: 1px solid $app-separator-color
  130. box-shadow: 0 3px 5px $app-separator-color
  131. z-index: 10
  132. top: 45px
  133. left: 0
  134. right: 0
  135. bottom: -325px
  136. padding: 0
  137. animation-duration: 500ms
  138. overflow-y: auto
  139. &.input-show
  140. display: block
  141. ul
  142. li
  143. height: 35px
  144. display: block
  145. text-align: left
  146. margin: 10px 0 0 10px
  147. font-size: 12pt
  148. font-weight: normal
  149. border-bottom: 1px solid $app-border-color
  150. &:last-child
  151. margin-bottom: 10px
  152. &:hover
  153. border-bottom: 2px solid $app-main-color
  154. cursor: pointer
  155. </style>