Create Searchable component
MODIFY
app/Http/Controllers/RegisterController.php
app/Http/Controllers/RegisterController.php
@@ -14,7 +14,11 @@ use Mail;
class RegisterController extends Controller {
public function index() {
- $currencies = Currency::all();
+ $currencies = [];
+
+ foreach (Currency::all() as $currency) {
+ $currencies[] = ['key' => $currency->id, 'label' => $currency->symbol];
+ }
return view('register', compact('currencies'));
}

MODIFY
resources/assets/js/app.js
resources/assets/js/app.js
@@ -7,6 +7,23 @@ Vue.component('barchart', require('./components/BarChart.vue'))
Vue.component('dropdown', require('./components/Dropdown.vue'))
Vue.component('transaction-wizard', require('./components/TransactionWizard.vue'))
Vue.component('validation-error', require('./components/ValidationError.vue'))
+Vue.component('searchable', require('./components/Searchable.vue'))
+
+Vue.directive('click-outside', {
+ bind: function (e, binding, vnode) {
+ e.clickOutsideEvent = function (event) {
+ if (!(e == event.target || e.contains(event.target))) {
+ vnode.context[binding.expression](event)
+ }
+ }
+
+ document.body.addEventListener('click', e.clickOutsideEvent)
+ },
+
+ unbind: function (e) {
+ document.body.removeEventListener('click', e.clickOutsideEvent)
+ }
+})
const app = new Vue({
el: '#app'

ADD
resources/assets/js/components/Searchable.vue
+<template>
+ <div v-click-outside="hide">
+ <input type="hidden" :name="name" :value="inputValue" />
+ <div class="searchable__input" @click="toggleShown">
+ <span v-if="!selected">Select</span>
+ <span v-else v-html="selected.label"></span>
+ </div>
+ <div class="searchable__list" v-if="shown">
+ <div v-for="item in items" @click="select(item)" v-html="item.label"></div>
+ </div>
+ </div>
+</template>
+
+<script>
+ export default {
+ props: ['name', 'items', 'initial'],
+
+ data() {
+ return {
+ shown: false,
+ selected: this.initial ? this.getItemByKey(this.initial) : null
+ }
+ },
+
+ computed: {
+ inputValue() {
+ if (this.selected) {
+ return this.selected.key
+ }
+
+ return ''
+ }
+ },
+
+ methods: {
+ getItemByKey(key) {
+ for (let i = 0; i < this.items.length; i ++) {
+ if (this.items[i].key == key) {
+ return this.items[i]
+ }
+ }
+ },
+
+ toggleShown() {
+ this.shown = !this.shown
+ },
+
+ show() {
+ this.shown = true
+ },
+
+ hide() {
+ this.shown = false
+ },
+
+ select(payload) {
+ this.selected = payload
+
+ this.hide()
+ }
+ }
+ }
+</script>

MODIFY
resources/assets/sass/app.scss
resources/assets/sass/app.scss
@@ -71,3 +71,29 @@ canvas {
font-size: 14px;
font-style: italic;
}
+
+.searchable {
+ &__input {
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ &__list {
+ margin-top: 10px;
+ background: $colors-light-body;
+ max-height: 200px;
+ overflow-y: scroll;
+ border: 1px solid $colors-light-border;
+ border-radius: $dimensions-box-border-radius;
+
+ div {
+ padding: 10px;
+
+ &:hover {
+ background: #FFF;
+ cursor: pointer;
+ }
+ }
+ }
+}

MODIFY
resources/assets/sass/components/input.scss
resources/assets/sass/components/input.scss
}
.theme-light {
- input[type=text], input[type=email], input[type=password], select, textarea {
+ input[type=text], input[type=email], input[type=password], select, .searchable__input, textarea {
background: $colors-light-body;
border: 1px solid $colors-light-border;
}
}
.theme-dark {
- input[type=text], input[type=email], input[type=password], select, textarea {
+ input[type=text], input[type=email], input[type=password], select, .searchable__input, textarea {
color: #FFF;
background: $colors-dark-body;
border: 1px solid $colors-dark-border;
}
}
-input[type=text], input[type=email], input[type=password], select, textarea, .button {
+input[type=text], input[type=email], input[type=password], select, .searchable__input, textarea, .button {
font: inherit;
border-radius: $dimensions-box-border-radius;
}
-input[type=text], input[type=email], input[type=password], select, textarea {
+input[type=text], input[type=email], input[type=password], select, .searchable__input, textarea {
padding: $dimensions-input-padding;
width: 100%;
-webkit-appearance: none;

MODIFY
resources/views/register.blade.php
resources/views/register.blade.php
</div>
<div class="input">
<label>Currency</label>
- <select name="currency">
- @foreach ($currencies as $currency)
- <option value="{{ $currency->id }}" {{ old('currency') == $currency->id ? 'selected' : '' }}>{!! $currency->symbol !!} &middot; {{ $currency->name }}</option>
- @endforeach
- </select>
+ <searchable name="currency" :items='@json($currencies)' initial="{{ old('currency') }}"></searchable>
@include('partials.validation_error', ['payload' => 'currency'])
</div>
<button class="button">Register</button>

Create Searchable component